Merge pull request #5205 from solgenomics/topic/generic_trial_upload
[sgn.git] / js / source / legacy / jqueryui.js
blob41575654103cd058a08db27c6b5d6996cd1483b6
1 /*! jQuery UI - v1.13.0 - 2021-10-07
2 * http://jqueryui.com
3 * Includes: widget.js, position.js, data.js, disable-selection.js, effect.js, effects/effect-blind.js, effects/effect-bounce.js, effects/effect-clip.js, effects/effect-drop.js, effects/effect-explode.js, effects/effect-fade.js, effects/effect-fold.js, effects/effect-highlight.js, effects/effect-puff.js, effects/effect-pulsate.js, effects/effect-scale.js, effects/effect-shake.js, effects/effect-size.js, effects/effect-slide.js, effects/effect-transfer.js, focusable.js, form-reset-mixin.js, jquery-patch.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js
4 * Copyright jQuery Foundation and other contributors; Licensed MIT */
6 ( function( factory ) {
7         "use strict";
8         
9         if ( typeof define === "function" && define.amd ) {
11                 // AMD. Register as an anonymous module.
12                 define( [ "jquery" ], factory );
13         } else {
15                 // Browser globals
16                 factory( jQuery );
17         }
18 } )( function( $ ) {
19 "use strict";
21 $.ui = $.ui || {};
23 var version = $.ui.version = "1.13.0";
26 /*!
27  * jQuery UI Widget 1.13.0
28  * http://jqueryui.com
29  *
30  * Copyright jQuery Foundation and other contributors
31  * Released under the MIT license.
32  * http://jquery.org/license
33  */
35 //>>label: Widget
36 //>>group: Core
37 //>>description: Provides a factory for creating stateful widgets with a common API.
38 //>>docs: http://api.jqueryui.com/jQuery.widget/
39 //>>demos: http://jqueryui.com/widget/
42 var widgetUuid = 0;
43 var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
44 var widgetSlice = Array.prototype.slice;
46 $.cleanData = ( function( orig ) {
47         return function( elems ) {
48                 var events, elem, i;
49                 for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
51                         // Only trigger remove when necessary to save time
52                         events = $._data( elem, "events" );
53                         if ( events && events.remove ) {
54                                 $( elem ).triggerHandler( "remove" );
55                         }
56                 }
57                 orig( elems );
58         };
59 } )( $.cleanData );
61 $.widget = function( name, base, prototype ) {
62         var existingConstructor, constructor, basePrototype;
64         // ProxiedPrototype allows the provided prototype to remain unmodified
65         // so that it can be used as a mixin for multiple widgets (#8876)
66         var proxiedPrototype = {};
68         var namespace = name.split( "." )[ 0 ];
69         name = name.split( "." )[ 1 ];
70         var fullName = namespace + "-" + name;
72         if ( !prototype ) {
73                 prototype = base;
74                 base = $.Widget;
75         }
77         if ( Array.isArray( prototype ) ) {
78                 prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
79         }
81         // Create selector for plugin
82         $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
83                 return !!$.data( elem, fullName );
84         };
86         $[ namespace ] = $[ namespace ] || {};
87         existingConstructor = $[ namespace ][ name ];
88         constructor = $[ namespace ][ name ] = function( options, element ) {
90                 // Allow instantiation without "new" keyword
91                 if ( !this._createWidget ) {
92                         return new constructor( options, element );
93                 }
95                 // Allow instantiation without initializing for simple inheritance
96                 // must use "new" keyword (the code above always passes args)
97                 if ( arguments.length ) {
98                         this._createWidget( options, element );
99                 }
100         };
102         // Extend with the existing constructor to carry over any static properties
103         $.extend( constructor, existingConstructor, {
104                 version: prototype.version,
106                 // Copy the object used to create the prototype in case we need to
107                 // redefine the widget later
108                 _proto: $.extend( {}, prototype ),
110                 // Track widgets that inherit from this widget in case this widget is
111                 // redefined after a widget inherits from it
112                 _childConstructors: []
113         } );
115         basePrototype = new base();
117         // We need to make the options hash a property directly on the new instance
118         // otherwise we'll modify the options hash on the prototype that we're
119         // inheriting from
120         basePrototype.options = $.widget.extend( {}, basePrototype.options );
121         $.each( prototype, function( prop, value ) {
122                 if ( typeof value !== "function" ) {
123                         proxiedPrototype[ prop ] = value;
124                         return;
125                 }
126                 proxiedPrototype[ prop ] = ( function() {
127                         function _super() {
128                                 return base.prototype[ prop ].apply( this, arguments );
129                         }
131                         function _superApply( args ) {
132                                 return base.prototype[ prop ].apply( this, args );
133                         }
135                         return function() {
136                                 var __super = this._super;
137                                 var __superApply = this._superApply;
138                                 var returnValue;
140                                 this._super = _super;
141                                 this._superApply = _superApply;
143                                 returnValue = value.apply( this, arguments );
145                                 this._super = __super;
146                                 this._superApply = __superApply;
148                                 return returnValue;
149                         };
150                 } )();
151         } );
152         constructor.prototype = $.widget.extend( basePrototype, {
154                 // TODO: remove support for widgetEventPrefix
155                 // always use the name + a colon as the prefix, e.g., draggable:start
156                 // don't prefix for widgets that aren't DOM-based
157                 widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
158         }, proxiedPrototype, {
159                 constructor: constructor,
160                 namespace: namespace,
161                 widgetName: name,
162                 widgetFullName: fullName
163         } );
165         // If this widget is being redefined then we need to find all widgets that
166         // are inheriting from it and redefine all of them so that they inherit from
167         // the new version of this widget. We're essentially trying to replace one
168         // level in the prototype chain.
169         if ( existingConstructor ) {
170                 $.each( existingConstructor._childConstructors, function( i, child ) {
171                         var childPrototype = child.prototype;
173                         // Redefine the child widget using the same prototype that was
174                         // originally used, but inherit from the new version of the base
175                         $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
176                                 child._proto );
177                 } );
179                 // Remove the list of existing child constructors from the old constructor
180                 // so the old child constructors can be garbage collected
181                 delete existingConstructor._childConstructors;
182         } else {
183                 base._childConstructors.push( constructor );
184         }
186         $.widget.bridge( name, constructor );
188         return constructor;
191 $.widget.extend = function( target ) {
192         var input = widgetSlice.call( arguments, 1 );
193         var inputIndex = 0;
194         var inputLength = input.length;
195         var key;
196         var value;
198         for ( ; inputIndex < inputLength; inputIndex++ ) {
199                 for ( key in input[ inputIndex ] ) {
200                         value = input[ inputIndex ][ key ];
201                         if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
203                                 // Clone objects
204                                 if ( $.isPlainObject( value ) ) {
205                                         target[ key ] = $.isPlainObject( target[ key ] ) ?
206                                                 $.widget.extend( {}, target[ key ], value ) :
208                                                 // Don't extend strings, arrays, etc. with objects
209                                                 $.widget.extend( {}, value );
211                                 // Copy everything else by reference
212                                 } else {
213                                         target[ key ] = value;
214                                 }
215                         }
216                 }
217         }
218         return target;
221 $.widget.bridge = function( name, object ) {
222         var fullName = object.prototype.widgetFullName || name;
223         $.fn[ name ] = function( options ) {
224                 var isMethodCall = typeof options === "string";
225                 var args = widgetSlice.call( arguments, 1 );
226                 var returnValue = this;
228                 if ( isMethodCall ) {
230                         // If this is an empty collection, we need to have the instance method
231                         // return undefined instead of the jQuery instance
232                         if ( !this.length && options === "instance" ) {
233                                 returnValue = undefined;
234                         } else {
235                                 this.each( function() {
236                                         var methodValue;
237                                         var instance = $.data( this, fullName );
239                                         if ( options === "instance" ) {
240                                                 returnValue = instance;
241                                                 return false;
242                                         }
244                                         if ( !instance ) {
245                                                 return $.error( "cannot call methods on " + name +
246                                                         " prior to initialization; " +
247                                                         "attempted to call method '" + options + "'" );
248                                         }
250                                         if ( typeof instance[ options ] !== "function" ||
251                                                 options.charAt( 0 ) === "_" ) {
252                                                 return $.error( "no such method '" + options + "' for " + name +
253                                                         " widget instance" );
254                                         }
256                                         methodValue = instance[ options ].apply( instance, args );
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 {
268                         // Allow multiple hashes to be passed on init
269                         if ( args.length ) {
270                                 options = $.widget.extend.apply( null, [ options ].concat( args ) );
271                         }
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                 }
286                 return returnValue;
287         };
290 $.Widget = function( /* options, element */ ) {};
291 $.Widget._childConstructors = [];
293 $.Widget.prototype = {
294         widgetName: "widget",
295         widgetEventPrefix: "",
296         defaultElement: "<div>",
298         options: {
299                 classes: {},
300                 disabled: false,
302                 // Callbacks
303                 create: null
304         },
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;
312                 this.bindings = $();
313                 this.hoverable = $();
314                 this.focusable = $();
315                 this.classesElementLookup = {};
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 ?
328                                 // Element within the document
329                                 element.ownerDocument :
331                                 // Element is window or document
332                                 element.document || element );
333                         this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
334                 }
336                 this.options = $.widget.extend( {},
337                         this.options,
338                         this._getCreateOptions(),
339                         options );
341                 this._create();
343                 if ( this.options.disabled ) {
344                         this._setOptionDisabled( this.options.disabled );
345                 }
347                 this._trigger( "create", null, this._getCreateEventData() );
348                 this._init();
349         },
351         _getCreateOptions: function() {
352                 return {};
353         },
355         _getCreateEventData: $.noop,
357         _create: $.noop,
359         _init: $.noop,
361         destroy: function() {
362                 var that = this;
364                 this._destroy();
365                 $.each( this.classesElementLookup, function( key, value ) {
366                         that._removeClass( value, key );
367                 } );
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" );
378                 // Clean up events and states
379                 this.bindings.off( this.eventNamespace );
380         },
382         _destroy: $.noop,
384         widget: function() {
385                 return this.element;
386         },
388         option: function( key, value ) {
389                 var options = key;
390                 var parts;
391                 var curOption;
392                 var i;
394                 if ( arguments.length === 0 ) {
396                         // Don't return a reference to the internal hash
397                         return $.widget.extend( {}, this.options );
398                 }
400                 if ( typeof key === "string" ) {
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                 }
425                 this._setOptions( options );
427                 return this;
428         },
430         _setOptions: function( options ) {
431                 var key;
433                 for ( key in options ) {
434                         this._setOption( key, options[ key ] );
435                 }
437                 return this;
438         },
440         _setOption: function( key, value ) {
441                 if ( key === "classes" ) {
442                         this._setOptionClasses( value );
443                 }
445                 this.options[ key ] = value;
447                 if ( key === "disabled" ) {
448                         this._setOptionDisabled( value );
449                 }
451                 return this;
452         },
454         _setOptionClasses: function( value ) {
455                 var classKey, elements, currentElements;
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                         }
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 );
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         },
485         _setOptionDisabled: function( value ) {
486                 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
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         },
495         enable: function() {
496                 return this._setOptions( { disabled: false } );
497         },
499         disable: function() {
500                 return this._setOptions( { disabled: true } );
501         },
503         _classes: function( options ) {
504                 var full = [];
505                 var that = this;
507                 options = $.extend( {
508                         element: this.element,
509                         classes: this.options.classes || {}
510                 }, options );
512                 function bindRemoveEvent() {
513                         options.element.each( function( _, element ) {
514                                 var isTracked = $.map( that.classesElementLookup, function( elements ) {
515                                         return elements;
516                                 } )
517                                         .some( function( elements ) {
518                                                 return elements.is( element );
519                                         } );
521                                 if ( !isTracked ) {
522                                         that._on( $( element ), {
523                                                 remove: "_untrackClassesElement"
524                                         } );
525                                 }
526                         } );
527                 }
529                 function processClassString( classes, checkOption ) {
530                         var current, i;
531                         for ( i = 0; i < classes.length; i++ ) {
532                                 current = that.classesElementLookup[ classes[ i ] ] || $();
533                                 if ( options.add ) {
534                                         bindRemoveEvent();
535                                         current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
536                                 } else {
537                                         current = $( current.not( options.element ).get() );
538                                 }
539                                 that.classesElementLookup[ classes[ i ] ] = current;
540                                 full.push( classes[ i ] );
541                                 if ( checkOption && options.classes[ classes[ i ] ] ) {
542                                         full.push( options.classes[ classes[ i ] ] );
543                                 }
544                         }
545                 }
547                 if ( options.keys ) {
548                         processClassString( options.keys.match( /\S+/g ) || [], true );
549                 }
550                 if ( options.extra ) {
551                         processClassString( options.extra.match( /\S+/g ) || [] );
552                 }
554                 return full.join( " " );
555         },
557         _untrackClassesElement: function( event ) {
558                 var that = this;
559                 $.each( that.classesElementLookup, function( key, value ) {
560                         if ( $.inArray( event.target, value ) !== -1 ) {
561                                 that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
562                         }
563                 } );
565                 this._off( $( event.target ) );
566         },
568         _removeClass: function( element, keys, extra ) {
569                 return this._toggleClass( element, keys, extra, false );
570         },
572         _addClass: function( element, keys, extra ) {
573                 return this._toggleClass( element, keys, extra, true );
574         },
576         _toggleClass: function( element, keys, extra, add ) {
577                 add = ( typeof add === "boolean" ) ? add : extra;
578                 var shift = ( typeof element === "string" || element === null ),
579                         options = {
580                                 extra: shift ? keys : extra,
581                                 keys: shift ? element : keys,
582                                 element: shift ? this.element : element,
583                                 add: add
584                         };
585                 options.element.toggleClass( this._classes( options ), add );
586                 return this;
587         },
589         _on: function( suppressDisabledCheck, element, handlers ) {
590                 var delegateElement;
591                 var instance = this;
593                 // No suppressDisabledCheck flag, shuffle arguments
594                 if ( typeof suppressDisabledCheck !== "boolean" ) {
595                         handlers = element;
596                         element = suppressDisabledCheck;
597                         suppressDisabledCheck = false;
598                 }
600                 // No element argument, shuffle and use this.element
601                 if ( !handlers ) {
602                         handlers = element;
603                         element = this.element;
604                         delegateElement = this.widget();
605                 } else {
606                         element = delegateElement = $( element );
607                         this.bindings = this.bindings.add( element );
608                 }
610                 $.each( handlers, function( event, handler ) {
611                         function handlerProxy() {
613                                 // Allow widgets to customize the disabled handling
614                                 // - disabled as an array instead of boolean
615                                 // - disabled class as method for disabling individual parts
616                                 if ( !suppressDisabledCheck &&
617                                                 ( instance.options.disabled === true ||
618                                                 $( this ).hasClass( "ui-state-disabled" ) ) ) {
619                                         return;
620                                 }
621                                 return ( typeof handler === "string" ? instance[ handler ] : handler )
622                                         .apply( instance, arguments );
623                         }
625                         // Copy the guid so direct unbinding works
626                         if ( typeof handler !== "string" ) {
627                                 handlerProxy.guid = handler.guid =
628                                         handler.guid || handlerProxy.guid || $.guid++;
629                         }
631                         var match = event.match( /^([\w:-]*)\s*(.*)$/ );
632                         var eventName = match[ 1 ] + instance.eventNamespace;
633                         var selector = match[ 2 ];
635                         if ( selector ) {
636                                 delegateElement.on( eventName, selector, handlerProxy );
637                         } else {
638                                 element.on( eventName, handlerProxy );
639                         }
640                 } );
641         },
643         _off: function( element, eventName ) {
644                 eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
645                         this.eventNamespace;
646                 element.off( eventName );
648                 // Clear the stack to avoid memory leaks (#10056)
649                 this.bindings = $( this.bindings.not( element ).get() );
650                 this.focusable = $( this.focusable.not( element ).get() );
651                 this.hoverable = $( this.hoverable.not( element ).get() );
652         },
654         _delay: function( handler, delay ) {
655                 function handlerProxy() {
656                         return ( typeof handler === "string" ? instance[ handler ] : handler )
657                                 .apply( instance, arguments );
658                 }
659                 var instance = this;
660                 return setTimeout( handlerProxy, delay || 0 );
661         },
663         _hoverable: function( element ) {
664                 this.hoverable = this.hoverable.add( element );
665                 this._on( element, {
666                         mouseenter: function( event ) {
667                                 this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
668                         },
669                         mouseleave: function( event ) {
670                                 this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
671                         }
672                 } );
673         },
675         _focusable: function( element ) {
676                 this.focusable = this.focusable.add( element );
677                 this._on( element, {
678                         focusin: function( event ) {
679                                 this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
680                         },
681                         focusout: function( event ) {
682                                 this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
683                         }
684                 } );
685         },
687         _trigger: function( type, event, data ) {
688                 var prop, orig;
689                 var callback = this.options[ type ];
691                 data = data || {};
692                 event = $.Event( event );
693                 event.type = ( type === this.widgetEventPrefix ?
694                         type :
695                         this.widgetEventPrefix + type ).toLowerCase();
697                 // The original event may come from any element
698                 // so we need to reset the target on the new event
699                 event.target = this.element[ 0 ];
701                 // Copy original event properties over to the new event
702                 orig = event.originalEvent;
703                 if ( orig ) {
704                         for ( prop in orig ) {
705                                 if ( !( prop in event ) ) {
706                                         event[ prop ] = orig[ prop ];
707                                 }
708                         }
709                 }
711                 this.element.trigger( event, data );
712                 return !( typeof callback === "function" &&
713                         callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
714                         event.isDefaultPrevented() );
715         }
718 $.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
719         $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
720                 if ( typeof options === "string" ) {
721                         options = { effect: options };
722                 }
724                 var hasOptions;
725                 var effectName = !options ?
726                         method :
727                         options === true || typeof options === "number" ?
728                                 defaultEffect :
729                                 options.effect || defaultEffect;
731                 options = options || {};
732                 if ( typeof options === "number" ) {
733                         options = { duration: options };
734                 } else if ( options === true ) {
735                         options = {};
736                 }
738                 hasOptions = !$.isEmptyObject( options );
739                 options.complete = callback;
741                 if ( options.delay ) {
742                         element.delay( options.delay );
743                 }
745                 if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
746                         element[ method ]( options );
747                 } else if ( effectName !== method && element[ effectName ] ) {
748                         element[ effectName ]( options.duration, options.easing, callback );
749                 } else {
750                         element.queue( function( next ) {
751                                 $( this )[ method ]();
752                                 if ( callback ) {
753                                         callback.call( element[ 0 ] );
754                                 }
755                                 next();
756                         } );
757                 }
758         };
759 } );
761 var widget = $.widget;
765  * jQuery UI Position 1.13.0
766  * http://jqueryui.com
768  * Copyright jQuery Foundation and other contributors
769  * Released under the MIT license.
770  * http://jquery.org/license
772  * http://api.jqueryui.com/position/
773  */
775 //>>label: Position
776 //>>group: Core
777 //>>description: Positions elements relative to other elements.
778 //>>docs: http://api.jqueryui.com/position/
779 //>>demos: http://jqueryui.com/position/
782 ( function() {
783 var cachedScrollbarWidth,
784         max = Math.max,
785         abs = Math.abs,
786         rhorizontal = /left|center|right/,
787         rvertical = /top|center|bottom/,
788         roffset = /[\+\-]\d+(\.[\d]+)?%?/,
789         rposition = /^\w+/,
790         rpercent = /%$/,
791         _position = $.fn.position;
793 function getOffsets( offsets, width, height ) {
794         return [
795                 parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
796                 parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
797         ];
800 function parseCss( element, property ) {
801         return parseInt( $.css( element, property ), 10 ) || 0;
804 function isWindow( obj ) {
805         return obj != null && obj === obj.window;
808 function getDimensions( elem ) {
809         var raw = elem[ 0 ];
810         if ( raw.nodeType === 9 ) {
811                 return {
812                         width: elem.width(),
813                         height: elem.height(),
814                         offset: { top: 0, left: 0 }
815                 };
816         }
817         if ( isWindow( raw ) ) {
818                 return {
819                         width: elem.width(),
820                         height: elem.height(),
821                         offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
822                 };
823         }
824         if ( raw.preventDefault ) {
825                 return {
826                         width: 0,
827                         height: 0,
828                         offset: { top: raw.pageY, left: raw.pageX }
829                 };
830         }
831         return {
832                 width: elem.outerWidth(),
833                 height: elem.outerHeight(),
834                 offset: elem.offset()
835         };
838 $.position = {
839         scrollbarWidth: function() {
840                 if ( cachedScrollbarWidth !== undefined ) {
841                         return cachedScrollbarWidth;
842                 }
843                 var w1, w2,
844                         div = $( "<div style=" +
845                                 "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
846                                 "<div style='height:300px;width:auto;'></div></div>" ),
847                         innerDiv = div.children()[ 0 ];
849                 $( "body" ).append( div );
850                 w1 = innerDiv.offsetWidth;
851                 div.css( "overflow", "scroll" );
853                 w2 = innerDiv.offsetWidth;
855                 if ( w1 === w2 ) {
856                         w2 = div[ 0 ].clientWidth;
857                 }
859                 div.remove();
861                 return ( cachedScrollbarWidth = w1 - w2 );
862         },
863         getScrollInfo: function( within ) {
864                 var overflowX = within.isWindow || within.isDocument ? "" :
865                                 within.element.css( "overflow-x" ),
866                         overflowY = within.isWindow || within.isDocument ? "" :
867                                 within.element.css( "overflow-y" ),
868                         hasOverflowX = overflowX === "scroll" ||
869                                 ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
870                         hasOverflowY = overflowY === "scroll" ||
871                                 ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
872                 return {
873                         width: hasOverflowY ? $.position.scrollbarWidth() : 0,
874                         height: hasOverflowX ? $.position.scrollbarWidth() : 0
875                 };
876         },
877         getWithinInfo: function( element ) {
878                 var withinElement = $( element || window ),
879                         isElemWindow = isWindow( withinElement[ 0 ] ),
880                         isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
881                         hasOffset = !isElemWindow && !isDocument;
882                 return {
883                         element: withinElement,
884                         isWindow: isElemWindow,
885                         isDocument: isDocument,
886                         offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
887                         scrollLeft: withinElement.scrollLeft(),
888                         scrollTop: withinElement.scrollTop(),
889                         width: withinElement.outerWidth(),
890                         height: withinElement.outerHeight()
891                 };
892         }
895 $.fn.position = function( options ) {
896         if ( !options || !options.of ) {
897                 return _position.apply( this, arguments );
898         }
900         // Make a copy, we don't want to modify arguments
901         options = $.extend( {}, options );
903         var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
905                 // Make sure string options are treated as CSS selectors
906                 target = typeof options.of === "string" ?
907                         $( document ).find( options.of ) :
908                         $( options.of ),
910                 within = $.position.getWithinInfo( options.within ),
911                 scrollInfo = $.position.getScrollInfo( within ),
912                 collision = ( options.collision || "flip" ).split( " " ),
913                 offsets = {};
915         dimensions = getDimensions( target );
916         if ( target[ 0 ].preventDefault ) {
918                 // Force left top to allow flipping
919                 options.at = "left top";
920         }
921         targetWidth = dimensions.width;
922         targetHeight = dimensions.height;
923         targetOffset = dimensions.offset;
925         // Clone to reuse original targetOffset later
926         basePosition = $.extend( {}, targetOffset );
928         // Force my and at to have valid horizontal and vertical positions
929         // if a value is missing or invalid, it will be converted to center
930         $.each( [ "my", "at" ], function() {
931                 var pos = ( options[ this ] || "" ).split( " " ),
932                         horizontalOffset,
933                         verticalOffset;
935                 if ( pos.length === 1 ) {
936                         pos = rhorizontal.test( pos[ 0 ] ) ?
937                                 pos.concat( [ "center" ] ) :
938                                 rvertical.test( pos[ 0 ] ) ?
939                                         [ "center" ].concat( pos ) :
940                                         [ "center", "center" ];
941                 }
942                 pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
943                 pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
945                 // Calculate offsets
946                 horizontalOffset = roffset.exec( pos[ 0 ] );
947                 verticalOffset = roffset.exec( pos[ 1 ] );
948                 offsets[ this ] = [
949                         horizontalOffset ? horizontalOffset[ 0 ] : 0,
950                         verticalOffset ? verticalOffset[ 0 ] : 0
951                 ];
953                 // Reduce to just the positions without the offsets
954                 options[ this ] = [
955                         rposition.exec( pos[ 0 ] )[ 0 ],
956                         rposition.exec( pos[ 1 ] )[ 0 ]
957                 ];
958         } );
960         // Normalize collision option
961         if ( collision.length === 1 ) {
962                 collision[ 1 ] = collision[ 0 ];
963         }
965         if ( options.at[ 0 ] === "right" ) {
966                 basePosition.left += targetWidth;
967         } else if ( options.at[ 0 ] === "center" ) {
968                 basePosition.left += targetWidth / 2;
969         }
971         if ( options.at[ 1 ] === "bottom" ) {
972                 basePosition.top += targetHeight;
973         } else if ( options.at[ 1 ] === "center" ) {
974                 basePosition.top += targetHeight / 2;
975         }
977         atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
978         basePosition.left += atOffset[ 0 ];
979         basePosition.top += atOffset[ 1 ];
981         return this.each( function() {
982                 var collisionPosition, using,
983                         elem = $( this ),
984                         elemWidth = elem.outerWidth(),
985                         elemHeight = elem.outerHeight(),
986                         marginLeft = parseCss( this, "marginLeft" ),
987                         marginTop = parseCss( this, "marginTop" ),
988                         collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
989                                 scrollInfo.width,
990                         collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
991                                 scrollInfo.height,
992                         position = $.extend( {}, basePosition ),
993                         myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
995                 if ( options.my[ 0 ] === "right" ) {
996                         position.left -= elemWidth;
997                 } else if ( options.my[ 0 ] === "center" ) {
998                         position.left -= elemWidth / 2;
999                 }
1001                 if ( options.my[ 1 ] === "bottom" ) {
1002                         position.top -= elemHeight;
1003                 } else if ( options.my[ 1 ] === "center" ) {
1004                         position.top -= elemHeight / 2;
1005                 }
1007                 position.left += myOffset[ 0 ];
1008                 position.top += myOffset[ 1 ];
1010                 collisionPosition = {
1011                         marginLeft: marginLeft,
1012                         marginTop: marginTop
1013                 };
1015                 $.each( [ "left", "top" ], function( i, dir ) {
1016                         if ( $.ui.position[ collision[ i ] ] ) {
1017                                 $.ui.position[ collision[ i ] ][ dir ]( position, {
1018                                         targetWidth: targetWidth,
1019                                         targetHeight: targetHeight,
1020                                         elemWidth: elemWidth,
1021                                         elemHeight: elemHeight,
1022                                         collisionPosition: collisionPosition,
1023                                         collisionWidth: collisionWidth,
1024                                         collisionHeight: collisionHeight,
1025                                         offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1026                                         my: options.my,
1027                                         at: options.at,
1028                                         within: within,
1029                                         elem: elem
1030                                 } );
1031                         }
1032                 } );
1034                 if ( options.using ) {
1036                         // Adds feedback as second argument to using callback, if present
1037                         using = function( props ) {
1038                                 var left = targetOffset.left - position.left,
1039                                         right = left + targetWidth - elemWidth,
1040                                         top = targetOffset.top - position.top,
1041                                         bottom = top + targetHeight - elemHeight,
1042                                         feedback = {
1043                                                 target: {
1044                                                         element: target,
1045                                                         left: targetOffset.left,
1046                                                         top: targetOffset.top,
1047                                                         width: targetWidth,
1048                                                         height: targetHeight
1049                                                 },
1050                                                 element: {
1051                                                         element: elem,
1052                                                         left: position.left,
1053                                                         top: position.top,
1054                                                         width: elemWidth,
1055                                                         height: elemHeight
1056                                                 },
1057                                                 horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1058                                                 vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1059                                         };
1060                                 if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1061                                         feedback.horizontal = "center";
1062                                 }
1063                                 if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1064                                         feedback.vertical = "middle";
1065                                 }
1066                                 if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1067                                         feedback.important = "horizontal";
1068                                 } else {
1069                                         feedback.important = "vertical";
1070                                 }
1071                                 options.using.call( this, props, feedback );
1072                         };
1073                 }
1075                 elem.offset( $.extend( position, { using: using } ) );
1076         } );
1079 $.ui.position = {
1080         fit: {
1081                 left: function( position, data ) {
1082                         var within = data.within,
1083                                 withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1084                                 outerWidth = within.width,
1085                                 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1086                                 overLeft = withinOffset - collisionPosLeft,
1087                                 overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1088                                 newOverRight;
1090                         // Element is wider than within
1091                         if ( data.collisionWidth > outerWidth ) {
1093                                 // Element is initially over the left side of within
1094                                 if ( overLeft > 0 && overRight <= 0 ) {
1095                                         newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1096                                                 withinOffset;
1097                                         position.left += overLeft - newOverRight;
1099                                 // Element is initially over right side of within
1100                                 } else if ( overRight > 0 && overLeft <= 0 ) {
1101                                         position.left = withinOffset;
1103                                 // Element is initially over both left and right sides of within
1104                                 } else {
1105                                         if ( overLeft > overRight ) {
1106                                                 position.left = withinOffset + outerWidth - data.collisionWidth;
1107                                         } else {
1108                                                 position.left = withinOffset;
1109                                         }
1110                                 }
1112                         // Too far left -> align with left edge
1113                         } else if ( overLeft > 0 ) {
1114                                 position.left += overLeft;
1116                         // Too far right -> align with right edge
1117                         } else if ( overRight > 0 ) {
1118                                 position.left -= overRight;
1120                         // Adjust based on position and margin
1121                         } else {
1122                                 position.left = max( position.left - collisionPosLeft, position.left );
1123                         }
1124                 },
1125                 top: function( position, data ) {
1126                         var within = data.within,
1127                                 withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1128                                 outerHeight = data.within.height,
1129                                 collisionPosTop = position.top - data.collisionPosition.marginTop,
1130                                 overTop = withinOffset - collisionPosTop,
1131                                 overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1132                                 newOverBottom;
1134                         // Element is taller than within
1135                         if ( data.collisionHeight > outerHeight ) {
1137                                 // Element is initially over the top of within
1138                                 if ( overTop > 0 && overBottom <= 0 ) {
1139                                         newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1140                                                 withinOffset;
1141                                         position.top += overTop - newOverBottom;
1143                                 // Element is initially over bottom of within
1144                                 } else if ( overBottom > 0 && overTop <= 0 ) {
1145                                         position.top = withinOffset;
1147                                 // Element is initially over both top and bottom of within
1148                                 } else {
1149                                         if ( overTop > overBottom ) {
1150                                                 position.top = withinOffset + outerHeight - data.collisionHeight;
1151                                         } else {
1152                                                 position.top = withinOffset;
1153                                         }
1154                                 }
1156                         // Too far up -> align with top
1157                         } else if ( overTop > 0 ) {
1158                                 position.top += overTop;
1160                         // Too far down -> align with bottom edge
1161                         } else if ( overBottom > 0 ) {
1162                                 position.top -= overBottom;
1164                         // Adjust based on position and margin
1165                         } else {
1166                                 position.top = max( position.top - collisionPosTop, position.top );
1167                         }
1168                 }
1169         },
1170         flip: {
1171                 left: function( position, data ) {
1172                         var within = data.within,
1173                                 withinOffset = within.offset.left + within.scrollLeft,
1174                                 outerWidth = within.width,
1175                                 offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1176                                 collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1177                                 overLeft = collisionPosLeft - offsetLeft,
1178                                 overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1179                                 myOffset = data.my[ 0 ] === "left" ?
1180                                         -data.elemWidth :
1181                                         data.my[ 0 ] === "right" ?
1182                                                 data.elemWidth :
1183                                                 0,
1184                                 atOffset = data.at[ 0 ] === "left" ?
1185                                         data.targetWidth :
1186                                         data.at[ 0 ] === "right" ?
1187                                                 -data.targetWidth :
1188                                                 0,
1189                                 offset = -2 * data.offset[ 0 ],
1190                                 newOverRight,
1191                                 newOverLeft;
1193                         if ( overLeft < 0 ) {
1194                                 newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1195                                         outerWidth - withinOffset;
1196                                 if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1197                                         position.left += myOffset + atOffset + offset;
1198                                 }
1199                         } else if ( overRight > 0 ) {
1200                                 newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1201                                         atOffset + offset - offsetLeft;
1202                                 if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1203                                         position.left += myOffset + atOffset + offset;
1204                                 }
1205                         }
1206                 },
1207                 top: function( position, data ) {
1208                         var within = data.within,
1209                                 withinOffset = within.offset.top + within.scrollTop,
1210                                 outerHeight = within.height,
1211                                 offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1212                                 collisionPosTop = position.top - data.collisionPosition.marginTop,
1213                                 overTop = collisionPosTop - offsetTop,
1214                                 overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1215                                 top = data.my[ 1 ] === "top",
1216                                 myOffset = top ?
1217                                         -data.elemHeight :
1218                                         data.my[ 1 ] === "bottom" ?
1219                                                 data.elemHeight :
1220                                                 0,
1221                                 atOffset = data.at[ 1 ] === "top" ?
1222                                         data.targetHeight :
1223                                         data.at[ 1 ] === "bottom" ?
1224                                                 -data.targetHeight :
1225                                                 0,
1226                                 offset = -2 * data.offset[ 1 ],
1227                                 newOverTop,
1228                                 newOverBottom;
1229                         if ( overTop < 0 ) {
1230                                 newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1231                                         outerHeight - withinOffset;
1232                                 if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1233                                         position.top += myOffset + atOffset + offset;
1234                                 }
1235                         } else if ( overBottom > 0 ) {
1236                                 newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1237                                         offset - offsetTop;
1238                                 if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1239                                         position.top += myOffset + atOffset + offset;
1240                                 }
1241                         }
1242                 }
1243         },
1244         flipfit: {
1245                 left: function() {
1246                         $.ui.position.flip.left.apply( this, arguments );
1247                         $.ui.position.fit.left.apply( this, arguments );
1248                 },
1249                 top: function() {
1250                         $.ui.position.flip.top.apply( this, arguments );
1251                         $.ui.position.fit.top.apply( this, arguments );
1252                 }
1253         }
1256 } )();
1258 var position = $.ui.position;
1262  * jQuery UI :data 1.13.0
1263  * http://jqueryui.com
1265  * Copyright jQuery Foundation and other contributors
1266  * Released under the MIT license.
1267  * http://jquery.org/license
1268  */
1270 //>>label: :data Selector
1271 //>>group: Core
1272 //>>description: Selects elements which have data stored under the specified key.
1273 //>>docs: http://api.jqueryui.com/data-selector/
1276 var data = $.extend( $.expr.pseudos, {
1277         data: $.expr.createPseudo ?
1278                 $.expr.createPseudo( function( dataName ) {
1279                         return function( elem ) {
1280                                 return !!$.data( elem, dataName );
1281                         };
1282                 } ) :
1284                 // Support: jQuery <1.8
1285                 function( elem, i, match ) {
1286                         return !!$.data( elem, match[ 3 ] );
1287                 }
1288 } );
1291  * jQuery UI Disable Selection 1.13.0
1292  * http://jqueryui.com
1294  * Copyright jQuery Foundation and other contributors
1295  * Released under the MIT license.
1296  * http://jquery.org/license
1297  */
1299 //>>label: disableSelection
1300 //>>group: Core
1301 //>>description: Disable selection of text content within the set of matched elements.
1302 //>>docs: http://api.jqueryui.com/disableSelection/
1304 // This file is deprecated
1306 var disableSelection = $.fn.extend( {
1307         disableSelection: ( function() {
1308                 var eventType = "onselectstart" in document.createElement( "div" ) ?
1309                         "selectstart" :
1310                         "mousedown";
1312                 return function() {
1313                         return this.on( eventType + ".ui-disableSelection", function( event ) {
1314                                 event.preventDefault();
1315                         } );
1316                 };
1317         } )(),
1319         enableSelection: function() {
1320                 return this.off( ".ui-disableSelection" );
1321         }
1322 } );
1326 // Create a local jQuery because jQuery Color relies on it and the
1327 // global may not exist with AMD and a custom build (#10199).
1328 // This module is a noop if used as a regular AMD module.
1329 // eslint-disable-next-line no-unused-vars
1330 var jQuery = $;
1334  * jQuery Color Animations v2.2.0
1335  * https://github.com/jquery/jquery-color
1337  * Copyright OpenJS Foundation and other contributors
1338  * Released under the MIT license.
1339  * http://jquery.org/license
1341  * Date: Sun May 10 09:02:36 2020 +0200
1342  */
1346         var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
1347                 "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
1349         class2type = {},
1350         toString = class2type.toString,
1352         // plusequals test for += 100 -= 100
1353         rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
1355         // a set of RE's that can match strings and generate color tuples.
1356         stringParsers = [ {
1357                         re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1358                         parse: function( execResult ) {
1359                                 return [
1360                                         execResult[ 1 ],
1361                                         execResult[ 2 ],
1362                                         execResult[ 3 ],
1363                                         execResult[ 4 ]
1364                                 ];
1365                         }
1366                 }, {
1367                         re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1368                         parse: function( execResult ) {
1369                                 return [
1370                                         execResult[ 1 ] * 2.55,
1371                                         execResult[ 2 ] * 2.55,
1372                                         execResult[ 3 ] * 2.55,
1373                                         execResult[ 4 ]
1374                                 ];
1375                         }
1376                 }, {
1378                         // this regex ignores A-F because it's compared against an already lowercased string
1379                         re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/,
1380                         parse: function( execResult ) {
1381                                 return [
1382                                         parseInt( execResult[ 1 ], 16 ),
1383                                         parseInt( execResult[ 2 ], 16 ),
1384                                         parseInt( execResult[ 3 ], 16 ),
1385                                         execResult[ 4 ] ?
1386                                                 ( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) :
1387                                                 1
1388                                 ];
1389                         }
1390                 }, {
1392                         // this regex ignores A-F because it's compared against an already lowercased string
1393                         re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/,
1394                         parse: function( execResult ) {
1395                                 return [
1396                                         parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
1397                                         parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
1398                                         parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ),
1399                                         execResult[ 4 ] ?
1400                                                 ( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 )
1401                                                         .toFixed( 2 ) :
1402                                                 1
1403                                 ];
1404                         }
1405                 }, {
1406                         re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1407                         space: "hsla",
1408                         parse: function( execResult ) {
1409                                 return [
1410                                         execResult[ 1 ],
1411                                         execResult[ 2 ] / 100,
1412                                         execResult[ 3 ] / 100,
1413                                         execResult[ 4 ]
1414                                 ];
1415                         }
1416                 } ],
1418         // jQuery.Color( )
1419         color = jQuery.Color = function( color, green, blue, alpha ) {
1420                 return new jQuery.Color.fn.parse( color, green, blue, alpha );
1421         },
1422         spaces = {
1423                 rgba: {
1424                         props: {
1425                                 red: {
1426                                         idx: 0,
1427                                         type: "byte"
1428                                 },
1429                                 green: {
1430                                         idx: 1,
1431                                         type: "byte"
1432                                 },
1433                                 blue: {
1434                                         idx: 2,
1435                                         type: "byte"
1436                                 }
1437                         }
1438                 },
1440                 hsla: {
1441                         props: {
1442                                 hue: {
1443                                         idx: 0,
1444                                         type: "degrees"
1445                                 },
1446                                 saturation: {
1447                                         idx: 1,
1448                                         type: "percent"
1449                                 },
1450                                 lightness: {
1451                                         idx: 2,
1452                                         type: "percent"
1453                                 }
1454                         }
1455                 }
1456         },
1457         propTypes = {
1458                 "byte": {
1459                         floor: true,
1460                         max: 255
1461                 },
1462                 "percent": {
1463                         max: 1
1464                 },
1465                 "degrees": {
1466                         mod: 360,
1467                         floor: true
1468                 }
1469         },
1470         support = color.support = {},
1472         // element for support tests
1473         supportElem = jQuery( "<p>" )[ 0 ],
1475         // colors = jQuery.Color.names
1476         colors,
1478         // local aliases of functions called often
1479         each = jQuery.each;
1481 // determine rgba support immediately
1482 supportElem.style.cssText = "background-color:rgba(1,1,1,.5)";
1483 support.rgba = supportElem.style.backgroundColor.indexOf( "rgba" ) > -1;
1485 // define cache name and alpha properties
1486 // for rgba and hsla spaces
1487 each( spaces, function( spaceName, space ) {
1488         space.cache = "_" + spaceName;
1489         space.props.alpha = {
1490                 idx: 3,
1491                 type: "percent",
1492                 def: 1
1493         };
1494 } );
1496 // Populate the class2type map
1497 jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
1498         function( _i, name ) {
1499                 class2type[ "[object " + name + "]" ] = name.toLowerCase();
1500         } );
1502 function getType( obj ) {
1503         if ( obj == null ) {
1504                 return obj + "";
1505         }
1507         return typeof obj === "object" ?
1508                 class2type[ toString.call( obj ) ] || "object" :
1509                 typeof obj;
1512 function clamp( value, prop, allowEmpty ) {
1513         var type = propTypes[ prop.type ] || {};
1515         if ( value == null ) {
1516                 return ( allowEmpty || !prop.def ) ? null : prop.def;
1517         }
1519         // ~~ is an short way of doing floor for positive numbers
1520         value = type.floor ? ~~value : parseFloat( value );
1522         // IE will pass in empty strings as value for alpha,
1523         // which will hit this case
1524         if ( isNaN( value ) ) {
1525                 return prop.def;
1526         }
1528         if ( type.mod ) {
1530                 // we add mod before modding to make sure that negatives values
1531                 // get converted properly: -10 -> 350
1532                 return ( value + type.mod ) % type.mod;
1533         }
1535         // for now all property types without mod have min and max
1536         return Math.min( type.max, Math.max( 0, value ) );
1539 function stringParse( string ) {
1540         var inst = color(),
1541                 rgba = inst._rgba = [];
1543         string = string.toLowerCase();
1545         each( stringParsers, function( _i, parser ) {
1546                 var parsed,
1547                         match = parser.re.exec( string ),
1548                         values = match && parser.parse( match ),
1549                         spaceName = parser.space || "rgba";
1551                 if ( values ) {
1552                         parsed = inst[ spaceName ]( values );
1554                         // if this was an rgba parse the assignment might happen twice
1555                         // oh well....
1556                         inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
1557                         rgba = inst._rgba = parsed._rgba;
1559                         // exit each( stringParsers ) here because we matched
1560                         return false;
1561                 }
1562         } );
1564         // Found a stringParser that handled it
1565         if ( rgba.length ) {
1567                 // if this came from a parsed string, force "transparent" when alpha is 0
1568                 // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
1569                 if ( rgba.join() === "0,0,0,0" ) {
1570                         jQuery.extend( rgba, colors.transparent );
1571                 }
1572                 return inst;
1573         }
1575         // named colors
1576         return colors[ string ];
1579 color.fn = jQuery.extend( color.prototype, {
1580         parse: function( red, green, blue, alpha ) {
1581                 if ( red === undefined ) {
1582                         this._rgba = [ null, null, null, null ];
1583                         return this;
1584                 }
1585                 if ( red.jquery || red.nodeType ) {
1586                         red = jQuery( red ).css( green );
1587                         green = undefined;
1588                 }
1590                 var inst = this,
1591                         type = getType( red ),
1592                         rgba = this._rgba = [];
1594                 // more than 1 argument specified - assume ( red, green, blue, alpha )
1595                 if ( green !== undefined ) {
1596                         red = [ red, green, blue, alpha ];
1597                         type = "array";
1598                 }
1600                 if ( type === "string" ) {
1601                         return this.parse( stringParse( red ) || colors._default );
1602                 }
1604                 if ( type === "array" ) {
1605                         each( spaces.rgba.props, function( _key, prop ) {
1606                                 rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
1607                         } );
1608                         return this;
1609                 }
1611                 if ( type === "object" ) {
1612                         if ( red instanceof color ) {
1613                                 each( spaces, function( _spaceName, space ) {
1614                                         if ( red[ space.cache ] ) {
1615                                                 inst[ space.cache ] = red[ space.cache ].slice();
1616                                         }
1617                                 } );
1618                         } else {
1619                                 each( spaces, function( _spaceName, space ) {
1620                                         var cache = space.cache;
1621                                         each( space.props, function( key, prop ) {
1623                                                 // if the cache doesn't exist, and we know how to convert
1624                                                 if ( !inst[ cache ] && space.to ) {
1626                                                         // if the value was null, we don't need to copy it
1627                                                         // if the key was alpha, we don't need to copy it either
1628                                                         if ( key === "alpha" || red[ key ] == null ) {
1629                                                                 return;
1630                                                         }
1631                                                         inst[ cache ] = space.to( inst._rgba );
1632                                                 }
1634                                                 // this is the only case where we allow nulls for ALL properties.
1635                                                 // call clamp with alwaysAllowEmpty
1636                                                 inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
1637                                         } );
1639                                         // everything defined but alpha?
1640                                         if ( inst[ cache ] && jQuery.inArray( null, inst[ cache ].slice( 0, 3 ) ) < 0 ) {
1642                                                 // use the default of 1
1643                                                 if ( inst[ cache ][ 3 ] == null ) {
1644                                                         inst[ cache ][ 3 ] = 1;
1645                                                 }
1647                                                 if ( space.from ) {
1648                                                         inst._rgba = space.from( inst[ cache ] );
1649                                                 }
1650                                         }
1651                                 } );
1652                         }
1653                         return this;
1654                 }
1655         },
1656         is: function( compare ) {
1657                 var is = color( compare ),
1658                         same = true,
1659                         inst = this;
1661                 each( spaces, function( _, space ) {
1662                         var localCache,
1663                                 isCache = is[ space.cache ];
1664                         if ( isCache ) {
1665                                 localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
1666                                 each( space.props, function( _, prop ) {
1667                                         if ( isCache[ prop.idx ] != null ) {
1668                                                 same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
1669                                                 return same;
1670                                         }
1671                                 } );
1672                         }
1673                         return same;
1674                 } );
1675                 return same;
1676         },
1677         _space: function() {
1678                 var used = [],
1679                         inst = this;
1680                 each( spaces, function( spaceName, space ) {
1681                         if ( inst[ space.cache ] ) {
1682                                 used.push( spaceName );
1683                         }
1684                 } );
1685                 return used.pop();
1686         },
1687         transition: function( other, distance ) {
1688                 var end = color( other ),
1689                         spaceName = end._space(),
1690                         space = spaces[ spaceName ],
1691                         startColor = this.alpha() === 0 ? color( "transparent" ) : this,
1692                         start = startColor[ space.cache ] || space.to( startColor._rgba ),
1693                         result = start.slice();
1695                 end = end[ space.cache ];
1696                 each( space.props, function( _key, prop ) {
1697                         var index = prop.idx,
1698                                 startValue = start[ index ],
1699                                 endValue = end[ index ],
1700                                 type = propTypes[ prop.type ] || {};
1702                         // if null, don't override start value
1703                         if ( endValue === null ) {
1704                                 return;
1705                         }
1707                         // if null - use end
1708                         if ( startValue === null ) {
1709                                 result[ index ] = endValue;
1710                         } else {
1711                                 if ( type.mod ) {
1712                                         if ( endValue - startValue > type.mod / 2 ) {
1713                                                 startValue += type.mod;
1714                                         } else if ( startValue - endValue > type.mod / 2 ) {
1715                                                 startValue -= type.mod;
1716                                         }
1717                                 }
1718                                 result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
1719                         }
1720                 } );
1721                 return this[ spaceName ]( result );
1722         },
1723         blend: function( opaque ) {
1725                 // if we are already opaque - return ourself
1726                 if ( this._rgba[ 3 ] === 1 ) {
1727                         return this;
1728                 }
1730                 var rgb = this._rgba.slice(),
1731                         a = rgb.pop(),
1732                         blend = color( opaque )._rgba;
1734                 return color( jQuery.map( rgb, function( v, i ) {
1735                         return ( 1 - a ) * blend[ i ] + a * v;
1736                 } ) );
1737         },
1738         toRgbaString: function() {
1739                 var prefix = "rgba(",
1740                         rgba = jQuery.map( this._rgba, function( v, i ) {
1741                                 if ( v != null ) {
1742                                         return v;
1743                                 }
1744                                 return i > 2 ? 1 : 0;
1745                         } );
1747                 if ( rgba[ 3 ] === 1 ) {
1748                         rgba.pop();
1749                         prefix = "rgb(";
1750                 }
1752                 return prefix + rgba.join() + ")";
1753         },
1754         toHslaString: function() {
1755                 var prefix = "hsla(",
1756                         hsla = jQuery.map( this.hsla(), function( v, i ) {
1757                                 if ( v == null ) {
1758                                         v = i > 2 ? 1 : 0;
1759                                 }
1761                                 // catch 1 and 2
1762                                 if ( i && i < 3 ) {
1763                                         v = Math.round( v * 100 ) + "%";
1764                                 }
1765                                 return v;
1766                         } );
1768                 if ( hsla[ 3 ] === 1 ) {
1769                         hsla.pop();
1770                         prefix = "hsl(";
1771                 }
1772                 return prefix + hsla.join() + ")";
1773         },
1774         toHexString: function( includeAlpha ) {
1775                 var rgba = this._rgba.slice(),
1776                         alpha = rgba.pop();
1778                 if ( includeAlpha ) {
1779                         rgba.push( ~~( alpha * 255 ) );
1780                 }
1782                 return "#" + jQuery.map( rgba, function( v ) {
1784                         // default to 0 when nulls exist
1785                         v = ( v || 0 ).toString( 16 );
1786                         return v.length === 1 ? "0" + v : v;
1787                 } ).join( "" );
1788         },
1789         toString: function() {
1790                 return this._rgba[ 3 ] === 0 ? "transparent" : this.toRgbaString();
1791         }
1792 } );
1793 color.fn.parse.prototype = color.fn;
1795 // hsla conversions adapted from:
1796 // https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
1798 function hue2rgb( p, q, h ) {
1799         h = ( h + 1 ) % 1;
1800         if ( h * 6 < 1 ) {
1801                 return p + ( q - p ) * h * 6;
1802         }
1803         if ( h * 2 < 1 ) {
1804                 return q;
1805         }
1806         if ( h * 3 < 2 ) {
1807                 return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
1808         }
1809         return p;
1812 spaces.hsla.to = function( rgba ) {
1813         if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
1814                 return [ null, null, null, rgba[ 3 ] ];
1815         }
1816         var r = rgba[ 0 ] / 255,
1817                 g = rgba[ 1 ] / 255,
1818                 b = rgba[ 2 ] / 255,
1819                 a = rgba[ 3 ],
1820                 max = Math.max( r, g, b ),
1821                 min = Math.min( r, g, b ),
1822                 diff = max - min,
1823                 add = max + min,
1824                 l = add * 0.5,
1825                 h, s;
1827         if ( min === max ) {
1828                 h = 0;
1829         } else if ( r === max ) {
1830                 h = ( 60 * ( g - b ) / diff ) + 360;
1831         } else if ( g === max ) {
1832                 h = ( 60 * ( b - r ) / diff ) + 120;
1833         } else {
1834                 h = ( 60 * ( r - g ) / diff ) + 240;
1835         }
1837         // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
1838         // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
1839         if ( diff === 0 ) {
1840                 s = 0;
1841         } else if ( l <= 0.5 ) {
1842                 s = diff / add;
1843         } else {
1844                 s = diff / ( 2 - add );
1845         }
1846         return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
1849 spaces.hsla.from = function( hsla ) {
1850         if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
1851                 return [ null, null, null, hsla[ 3 ] ];
1852         }
1853         var h = hsla[ 0 ] / 360,
1854                 s = hsla[ 1 ],
1855                 l = hsla[ 2 ],
1856                 a = hsla[ 3 ],
1857                 q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
1858                 p = 2 * l - q;
1860         return [
1861                 Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
1862                 Math.round( hue2rgb( p, q, h ) * 255 ),
1863                 Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
1864                 a
1865         ];
1869 each( spaces, function( spaceName, space ) {
1870         var props = space.props,
1871                 cache = space.cache,
1872                 to = space.to,
1873                 from = space.from;
1875         // makes rgba() and hsla()
1876         color.fn[ spaceName ] = function( value ) {
1878                 // generate a cache for this space if it doesn't exist
1879                 if ( to && !this[ cache ] ) {
1880                         this[ cache ] = to( this._rgba );
1881                 }
1882                 if ( value === undefined ) {
1883                         return this[ cache ].slice();
1884                 }
1886                 var ret,
1887                         type = getType( value ),
1888                         arr = ( type === "array" || type === "object" ) ? value : arguments,
1889                         local = this[ cache ].slice();
1891                 each( props, function( key, prop ) {
1892                         var val = arr[ type === "object" ? key : prop.idx ];
1893                         if ( val == null ) {
1894                                 val = local[ prop.idx ];
1895                         }
1896                         local[ prop.idx ] = clamp( val, prop );
1897                 } );
1899                 if ( from ) {
1900                         ret = color( from( local ) );
1901                         ret[ cache ] = local;
1902                         return ret;
1903                 } else {
1904                         return color( local );
1905                 }
1906         };
1908         // makes red() green() blue() alpha() hue() saturation() lightness()
1909         each( props, function( key, prop ) {
1911                 // alpha is included in more than one space
1912                 if ( color.fn[ key ] ) {
1913                         return;
1914                 }
1915                 color.fn[ key ] = function( value ) {
1916                         var local, cur, match, fn,
1917                                 vtype = getType( value );
1919                         if ( key === "alpha" ) {
1920                                 fn = this._hsla ? "hsla" : "rgba";
1921                         } else {
1922                                 fn = spaceName;
1923                         }
1924                         local = this[ fn ]();
1925                         cur = local[ prop.idx ];
1927                         if ( vtype === "undefined" ) {
1928                                 return cur;
1929                         }
1931                         if ( vtype === "function" ) {
1932                                 value = value.call( this, cur );
1933                                 vtype = getType( value );
1934                         }
1935                         if ( value == null && prop.empty ) {
1936                                 return this;
1937                         }
1938                         if ( vtype === "string" ) {
1939                                 match = rplusequals.exec( value );
1940                                 if ( match ) {
1941                                         value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
1942                                 }
1943                         }
1944                         local[ prop.idx ] = value;
1945                         return this[ fn ]( local );
1946                 };
1947         } );
1948 } );
1950 // add cssHook and .fx.step function for each named hook.
1951 // accept a space separated string of properties
1952 color.hook = function( hook ) {
1953         var hooks = hook.split( " " );
1954         each( hooks, function( _i, hook ) {
1955                 jQuery.cssHooks[ hook ] = {
1956                         set: function( elem, value ) {
1957                                 var parsed, curElem,
1958                                         backgroundColor = "";
1960                                 if ( value !== "transparent" && ( getType( value ) !== "string" || ( parsed = stringParse( value ) ) ) ) {
1961                                         value = color( parsed || value );
1962                                         if ( !support.rgba && value._rgba[ 3 ] !== 1 ) {
1963                                                 curElem = hook === "backgroundColor" ? elem.parentNode : elem;
1964                                                 while (
1965                                                         ( backgroundColor === "" || backgroundColor === "transparent" ) &&
1966                                                         curElem && curElem.style
1967                                                 ) {
1968                                                         try {
1969                                                                 backgroundColor = jQuery.css( curElem, "backgroundColor" );
1970                                                                 curElem = curElem.parentNode;
1971                                                         } catch ( e ) {
1972                                                         }
1973                                                 }
1975                                                 value = value.blend( backgroundColor && backgroundColor !== "transparent" ?
1976                                                         backgroundColor :
1977                                                         "_default" );
1978                                         }
1980                                         value = value.toRgbaString();
1981                                 }
1982                                 try {
1983                                         elem.style[ hook ] = value;
1984                                 } catch ( e ) {
1986                                         // wrapped to prevent IE from throwing errors on "invalid" values like 'auto' or 'inherit'
1987                                 }
1988                         }
1989                 };
1990                 jQuery.fx.step[ hook ] = function( fx ) {
1991                         if ( !fx.colorInit ) {
1992                                 fx.start = color( fx.elem, hook );
1993                                 fx.end = color( fx.end );
1994                                 fx.colorInit = true;
1995                         }
1996                         jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
1997                 };
1998         } );
2002 color.hook( stepHooks );
2004 jQuery.cssHooks.borderColor = {
2005         expand: function( value ) {
2006                 var expanded = {};
2008                 each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) {
2009                         expanded[ "border" + part + "Color" ] = value;
2010                 } );
2011                 return expanded;
2012         }
2015 // Basic color names only.
2016 // Usage of any of the other color names requires adding yourself or including
2017 // jquery.color.svg-names.js.
2018 colors = jQuery.Color.names = {
2020         // 4.1. Basic color keywords
2021         aqua: "#00ffff",
2022         black: "#000000",
2023         blue: "#0000ff",
2024         fuchsia: "#ff00ff",
2025         gray: "#808080",
2026         green: "#008000",
2027         lime: "#00ff00",
2028         maroon: "#800000",
2029         navy: "#000080",
2030         olive: "#808000",
2031         purple: "#800080",
2032         red: "#ff0000",
2033         silver: "#c0c0c0",
2034         teal: "#008080",
2035         white: "#ffffff",
2036         yellow: "#ffff00",
2038         // 4.2.3. "transparent" color keyword
2039         transparent: [ null, null, null, 0 ],
2041         _default: "#ffffff"
2046  * jQuery UI Effects 1.13.0
2047  * http://jqueryui.com
2049  * Copyright jQuery Foundation and other contributors
2050  * Released under the MIT license.
2051  * http://jquery.org/license
2052  */
2054 //>>label: Effects Core
2055 //>>group: Effects
2056 /* eslint-disable max-len */
2057 //>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
2058 /* eslint-enable max-len */
2059 //>>docs: http://api.jqueryui.com/category/effects-core/
2060 //>>demos: http://jqueryui.com/effect/
2063 var dataSpace = "ui-effects-",
2064         dataSpaceStyle = "ui-effects-style",
2065         dataSpaceAnimated = "ui-effects-animated";
2067 $.effects = {
2068         effect: {}
2071 /******************************************************************************/
2072 /****************************** CLASS ANIMATIONS ******************************/
2073 /******************************************************************************/
2074 ( function() {
2076 var classAnimationActions = [ "add", "remove", "toggle" ],
2077         shorthandStyles = {
2078                 border: 1,
2079                 borderBottom: 1,
2080                 borderColor: 1,
2081                 borderLeft: 1,
2082                 borderRight: 1,
2083                 borderTop: 1,
2084                 borderWidth: 1,
2085                 margin: 1,
2086                 padding: 1
2087         };
2089 $.each(
2090         [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
2091         function( _, prop ) {
2092                 $.fx.step[ prop ] = function( fx ) {
2093                         if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
2094                                 jQuery.style( fx.elem, prop, fx.end );
2095                                 fx.setAttr = true;
2096                         }
2097                 };
2098         }
2101 function camelCase( string ) {
2102         return string.replace( /-([\da-z])/gi, function( all, letter ) {
2103                 return letter.toUpperCase();
2104         } );
2107 function getElementStyles( elem ) {
2108         var key, len,
2109                 style = elem.ownerDocument.defaultView ?
2110                         elem.ownerDocument.defaultView.getComputedStyle( elem, null ) :
2111                         elem.currentStyle,
2112                 styles = {};
2114         if ( style && style.length && style[ 0 ] && style[ style[ 0 ] ] ) {
2115                 len = style.length;
2116                 while ( len-- ) {
2117                         key = style[ len ];
2118                         if ( typeof style[ key ] === "string" ) {
2119                                 styles[ camelCase( key ) ] = style[ key ];
2120                         }
2121                 }
2123         // Support: Opera, IE <9
2124         } else {
2125                 for ( key in style ) {
2126                         if ( typeof style[ key ] === "string" ) {
2127                                 styles[ key ] = style[ key ];
2128                         }
2129                 }
2130         }
2132         return styles;
2135 function styleDifference( oldStyle, newStyle ) {
2136         var diff = {},
2137                 name, value;
2139         for ( name in newStyle ) {
2140                 value = newStyle[ name ];
2141                 if ( oldStyle[ name ] !== value ) {
2142                         if ( !shorthandStyles[ name ] ) {
2143                                 if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
2144                                         diff[ name ] = value;
2145                                 }
2146                         }
2147                 }
2148         }
2150         return diff;
2153 // Support: jQuery <1.8
2154 if ( !$.fn.addBack ) {
2155         $.fn.addBack = function( selector ) {
2156                 return this.add( selector == null ?
2157                         this.prevObject : this.prevObject.filter( selector )
2158                 );
2159         };
2162 $.effects.animateClass = function( value, duration, easing, callback ) {
2163         var o = $.speed( duration, easing, callback );
2165         return this.queue( function() {
2166                 var animated = $( this ),
2167                         baseClass = animated.attr( "class" ) || "",
2168                         applyClassChange,
2169                         allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
2171                 // Map the animated objects to store the original styles.
2172                 allAnimations = allAnimations.map( function() {
2173                         var el = $( this );
2174                         return {
2175                                 el: el,
2176                                 start: getElementStyles( this )
2177                         };
2178                 } );
2180                 // Apply class change
2181                 applyClassChange = function() {
2182                         $.each( classAnimationActions, function( i, action ) {
2183                                 if ( value[ action ] ) {
2184                                         animated[ action + "Class" ]( value[ action ] );
2185                                 }
2186                         } );
2187                 };
2188                 applyClassChange();
2190                 // Map all animated objects again - calculate new styles and diff
2191                 allAnimations = allAnimations.map( function() {
2192                         this.end = getElementStyles( this.el[ 0 ] );
2193                         this.diff = styleDifference( this.start, this.end );
2194                         return this;
2195                 } );
2197                 // Apply original class
2198                 animated.attr( "class", baseClass );
2200                 // Map all animated objects again - this time collecting a promise
2201                 allAnimations = allAnimations.map( function() {
2202                         var styleInfo = this,
2203                                 dfd = $.Deferred(),
2204                                 opts = $.extend( {}, o, {
2205                                         queue: false,
2206                                         complete: function() {
2207                                                 dfd.resolve( styleInfo );
2208                                         }
2209                                 } );
2211                         this.el.animate( this.diff, opts );
2212                         return dfd.promise();
2213                 } );
2215                 // Once all animations have completed:
2216                 $.when.apply( $, allAnimations.get() ).done( function() {
2218                         // Set the final class
2219                         applyClassChange();
2221                         // For each animated element,
2222                         // clear all css properties that were animated
2223                         $.each( arguments, function() {
2224                                 var el = this.el;
2225                                 $.each( this.diff, function( key ) {
2226                                         el.css( key, "" );
2227                                 } );
2228                         } );
2230                         // This is guarnteed to be there if you use jQuery.speed()
2231                         // it also handles dequeuing the next anim...
2232                         o.complete.call( animated[ 0 ] );
2233                 } );
2234         } );
2237 $.fn.extend( {
2238         addClass: ( function( orig ) {
2239                 return function( classNames, speed, easing, callback ) {
2240                         return speed ?
2241                                 $.effects.animateClass.call( this,
2242                                         { add: classNames }, speed, easing, callback ) :
2243                                 orig.apply( this, arguments );
2244                 };
2245         } )( $.fn.addClass ),
2247         removeClass: ( function( orig ) {
2248                 return function( classNames, speed, easing, callback ) {
2249                         return arguments.length > 1 ?
2250                                 $.effects.animateClass.call( this,
2251                                         { remove: classNames }, speed, easing, callback ) :
2252                                 orig.apply( this, arguments );
2253                 };
2254         } )( $.fn.removeClass ),
2256         toggleClass: ( function( orig ) {
2257                 return function( classNames, force, speed, easing, callback ) {
2258                         if ( typeof force === "boolean" || force === undefined ) {
2259                                 if ( !speed ) {
2261                                         // Without speed parameter
2262                                         return orig.apply( this, arguments );
2263                                 } else {
2264                                         return $.effects.animateClass.call( this,
2265                                                 ( force ? { add: classNames } : { remove: classNames } ),
2266                                                 speed, easing, callback );
2267                                 }
2268                         } else {
2270                                 // Without force parameter
2271                                 return $.effects.animateClass.call( this,
2272                                         { toggle: classNames }, force, speed, easing );
2273                         }
2274                 };
2275         } )( $.fn.toggleClass ),
2277         switchClass: function( remove, add, speed, easing, callback ) {
2278                 return $.effects.animateClass.call( this, {
2279                         add: add,
2280                         remove: remove
2281                 }, speed, easing, callback );
2282         }
2283 } );
2285 } )();
2287 /******************************************************************************/
2288 /*********************************** EFFECTS **********************************/
2289 /******************************************************************************/
2291 ( function() {
2293 if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) {
2294         $.expr.pseudos.animated = ( function( orig ) {
2295                 return function( elem ) {
2296                         return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
2297                 };
2298         } )( $.expr.pseudos.animated );
2301 if ( $.uiBackCompat !== false ) {
2302         $.extend( $.effects, {
2304                 // Saves a set of properties in a data storage
2305                 save: function( element, set ) {
2306                         var i = 0, length = set.length;
2307                         for ( ; i < length; i++ ) {
2308                                 if ( set[ i ] !== null ) {
2309                                         element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
2310                                 }
2311                         }
2312                 },
2314                 // Restores a set of previously saved properties from a data storage
2315                 restore: function( element, set ) {
2316                         var val, i = 0, length = set.length;
2317                         for ( ; i < length; i++ ) {
2318                                 if ( set[ i ] !== null ) {
2319                                         val = element.data( dataSpace + set[ i ] );
2320                                         element.css( set[ i ], val );
2321                                 }
2322                         }
2323                 },
2325                 setMode: function( el, mode ) {
2326                         if ( mode === "toggle" ) {
2327                                 mode = el.is( ":hidden" ) ? "show" : "hide";
2328                         }
2329                         return mode;
2330                 },
2332                 // Wraps the element around a wrapper that copies position properties
2333                 createWrapper: function( element ) {
2335                         // If the element is already wrapped, return it
2336                         if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2337                                 return element.parent();
2338                         }
2340                         // Wrap the element
2341                         var props = {
2342                                         width: element.outerWidth( true ),
2343                                         height: element.outerHeight( true ),
2344                                         "float": element.css( "float" )
2345                                 },
2346                                 wrapper = $( "<div></div>" )
2347                                         .addClass( "ui-effects-wrapper" )
2348                                         .css( {
2349                                                 fontSize: "100%",
2350                                                 background: "transparent",
2351                                                 border: "none",
2352                                                 margin: 0,
2353                                                 padding: 0
2354                                         } ),
2356                                 // Store the size in case width/height are defined in % - Fixes #5245
2357                                 size = {
2358                                         width: element.width(),
2359                                         height: element.height()
2360                                 },
2361                                 active = document.activeElement;
2363                         // Support: Firefox
2364                         // Firefox incorrectly exposes anonymous content
2365                         // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
2366                         try {
2367                                 // eslint-disable-next-line no-unused-expressions
2368                                 active.id;
2369                         } catch ( e ) {
2370                                 active = document.body;
2371                         }
2373                         element.wrap( wrapper );
2375                         // Fixes #7595 - Elements lose focus when wrapped.
2376                         if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2377                                 $( active ).trigger( "focus" );
2378                         }
2380                         // Hotfix for jQuery 1.4 since some change in wrap() seems to actually
2381                         // lose the reference to the wrapped element
2382                         wrapper = element.parent();
2384                         // Transfer positioning properties to the wrapper
2385                         if ( element.css( "position" ) === "static" ) {
2386                                 wrapper.css( { position: "relative" } );
2387                                 element.css( { position: "relative" } );
2388                         } else {
2389                                 $.extend( props, {
2390                                         position: element.css( "position" ),
2391                                         zIndex: element.css( "z-index" )
2392                                 } );
2393                                 $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
2394                                         props[ pos ] = element.css( pos );
2395                                         if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
2396                                                 props[ pos ] = "auto";
2397                                         }
2398                                 } );
2399                                 element.css( {
2400                                         position: "relative",
2401                                         top: 0,
2402                                         left: 0,
2403                                         right: "auto",
2404                                         bottom: "auto"
2405                                 } );
2406                         }
2407                         element.css( size );
2409                         return wrapper.css( props ).show();
2410                 },
2412                 removeWrapper: function( element ) {
2413                         var active = document.activeElement;
2415                         if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2416                                 element.parent().replaceWith( element );
2418                                 // Fixes #7595 - Elements lose focus when wrapped.
2419                                 if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2420                                         $( active ).trigger( "focus" );
2421                                 }
2422                         }
2424                         return element;
2425                 }
2426         } );
2429 $.extend( $.effects, {
2430         version: "1.13.0",
2432         define: function( name, mode, effect ) {
2433                 if ( !effect ) {
2434                         effect = mode;
2435                         mode = "effect";
2436                 }
2438                 $.effects.effect[ name ] = effect;
2439                 $.effects.effect[ name ].mode = mode;
2441                 return effect;
2442         },
2444         scaledDimensions: function( element, percent, direction ) {
2445                 if ( percent === 0 ) {
2446                         return {
2447                                 height: 0,
2448                                 width: 0,
2449                                 outerHeight: 0,
2450                                 outerWidth: 0
2451                         };
2452                 }
2454                 var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
2455                         y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
2457                 return {
2458                         height: element.height() * y,
2459                         width: element.width() * x,
2460                         outerHeight: element.outerHeight() * y,
2461                         outerWidth: element.outerWidth() * x
2462                 };
2464         },
2466         clipToBox: function( animation ) {
2467                 return {
2468                         width: animation.clip.right - animation.clip.left,
2469                         height: animation.clip.bottom - animation.clip.top,
2470                         left: animation.clip.left,
2471                         top: animation.clip.top
2472                 };
2473         },
2475         // Injects recently queued functions to be first in line (after "inprogress")
2476         unshift: function( element, queueLength, count ) {
2477                 var queue = element.queue();
2479                 if ( queueLength > 1 ) {
2480                         queue.splice.apply( queue,
2481                                 [ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
2482                 }
2483                 element.dequeue();
2484         },
2486         saveStyle: function( element ) {
2487                 element.data( dataSpaceStyle, element[ 0 ].style.cssText );
2488         },
2490         restoreStyle: function( element ) {
2491                 element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
2492                 element.removeData( dataSpaceStyle );
2493         },
2495         mode: function( element, mode ) {
2496                 var hidden = element.is( ":hidden" );
2498                 if ( mode === "toggle" ) {
2499                         mode = hidden ? "show" : "hide";
2500                 }
2501                 if ( hidden ? mode === "hide" : mode === "show" ) {
2502                         mode = "none";
2503                 }
2504                 return mode;
2505         },
2507         // Translates a [top,left] array into a baseline value
2508         getBaseline: function( origin, original ) {
2509                 var y, x;
2511                 switch ( origin[ 0 ] ) {
2512                 case "top":
2513                         y = 0;
2514                         break;
2515                 case "middle":
2516                         y = 0.5;
2517                         break;
2518                 case "bottom":
2519                         y = 1;
2520                         break;
2521                 default:
2522                         y = origin[ 0 ] / original.height;
2523                 }
2525                 switch ( origin[ 1 ] ) {
2526                 case "left":
2527                         x = 0;
2528                         break;
2529                 case "center":
2530                         x = 0.5;
2531                         break;
2532                 case "right":
2533                         x = 1;
2534                         break;
2535                 default:
2536                         x = origin[ 1 ] / original.width;
2537                 }
2539                 return {
2540                         x: x,
2541                         y: y
2542                 };
2543         },
2545         // Creates a placeholder element so that the original element can be made absolute
2546         createPlaceholder: function( element ) {
2547                 var placeholder,
2548                         cssPosition = element.css( "position" ),
2549                         position = element.position();
2551                 // Lock in margins first to account for form elements, which
2552                 // will change margin if you explicitly set height
2553                 // see: http://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
2554                 // Support: Safari
2555                 element.css( {
2556                         marginTop: element.css( "marginTop" ),
2557                         marginBottom: element.css( "marginBottom" ),
2558                         marginLeft: element.css( "marginLeft" ),
2559                         marginRight: element.css( "marginRight" )
2560                 } )
2561                 .outerWidth( element.outerWidth() )
2562                 .outerHeight( element.outerHeight() );
2564                 if ( /^(static|relative)/.test( cssPosition ) ) {
2565                         cssPosition = "absolute";
2567                         placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
2569                                 // Convert inline to inline block to account for inline elements
2570                                 // that turn to inline block based on content (like img)
2571                                 display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
2572                                         "inline-block" :
2573                                         "block",
2574                                 visibility: "hidden",
2576                                 // Margins need to be set to account for margin collapse
2577                                 marginTop: element.css( "marginTop" ),
2578                                 marginBottom: element.css( "marginBottom" ),
2579                                 marginLeft: element.css( "marginLeft" ),
2580                                 marginRight: element.css( "marginRight" ),
2581                                 "float": element.css( "float" )
2582                         } )
2583                         .outerWidth( element.outerWidth() )
2584                         .outerHeight( element.outerHeight() )
2585                         .addClass( "ui-effects-placeholder" );
2587                         element.data( dataSpace + "placeholder", placeholder );
2588                 }
2590                 element.css( {
2591                         position: cssPosition,
2592                         left: position.left,
2593                         top: position.top
2594                 } );
2596                 return placeholder;
2597         },
2599         removePlaceholder: function( element ) {
2600                 var dataKey = dataSpace + "placeholder",
2601                                 placeholder = element.data( dataKey );
2603                 if ( placeholder ) {
2604                         placeholder.remove();
2605                         element.removeData( dataKey );
2606                 }
2607         },
2609         // Removes a placeholder if it exists and restores
2610         // properties that were modified during placeholder creation
2611         cleanUp: function( element ) {
2612                 $.effects.restoreStyle( element );
2613                 $.effects.removePlaceholder( element );
2614         },
2616         setTransition: function( element, list, factor, value ) {
2617                 value = value || {};
2618                 $.each( list, function( i, x ) {
2619                         var unit = element.cssUnit( x );
2620                         if ( unit[ 0 ] > 0 ) {
2621                                 value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
2622                         }
2623                 } );
2624                 return value;
2625         }
2626 } );
2628 // Return an effect options object for the given parameters:
2629 function _normalizeArguments( effect, options, speed, callback ) {
2631         // Allow passing all options as the first parameter
2632         if ( $.isPlainObject( effect ) ) {
2633                 options = effect;
2634                 effect = effect.effect;
2635         }
2637         // Convert to an object
2638         effect = { effect: effect };
2640         // Catch (effect, null, ...)
2641         if ( options == null ) {
2642                 options = {};
2643         }
2645         // Catch (effect, callback)
2646         if ( typeof options === "function" ) {
2647                 callback = options;
2648                 speed = null;
2649                 options = {};
2650         }
2652         // Catch (effect, speed, ?)
2653         if ( typeof options === "number" || $.fx.speeds[ options ] ) {
2654                 callback = speed;
2655                 speed = options;
2656                 options = {};
2657         }
2659         // Catch (effect, options, callback)
2660         if ( typeof speed === "function" ) {
2661                 callback = speed;
2662                 speed = null;
2663         }
2665         // Add options to effect
2666         if ( options ) {
2667                 $.extend( effect, options );
2668         }
2670         speed = speed || options.duration;
2671         effect.duration = $.fx.off ? 0 :
2672                 typeof speed === "number" ? speed :
2673                 speed in $.fx.speeds ? $.fx.speeds[ speed ] :
2674                 $.fx.speeds._default;
2676         effect.complete = callback || options.complete;
2678         return effect;
2681 function standardAnimationOption( option ) {
2683         // Valid standard speeds (nothing, number, named speed)
2684         if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
2685                 return true;
2686         }
2688         // Invalid strings - treat as "normal" speed
2689         if ( typeof option === "string" && !$.effects.effect[ option ] ) {
2690                 return true;
2691         }
2693         // Complete callback
2694         if ( typeof option === "function" ) {
2695                 return true;
2696         }
2698         // Options hash (but not naming an effect)
2699         if ( typeof option === "object" && !option.effect ) {
2700                 return true;
2701         }
2703         // Didn't match any standard API
2704         return false;
2707 $.fn.extend( {
2708         effect: function( /* effect, options, speed, callback */ ) {
2709                 var args = _normalizeArguments.apply( this, arguments ),
2710                         effectMethod = $.effects.effect[ args.effect ],
2711                         defaultMode = effectMethod.mode,
2712                         queue = args.queue,
2713                         queueName = queue || "fx",
2714                         complete = args.complete,
2715                         mode = args.mode,
2716                         modes = [],
2717                         prefilter = function( next ) {
2718                                 var el = $( this ),
2719                                         normalizedMode = $.effects.mode( el, mode ) || defaultMode;
2721                                 // Sentinel for duck-punching the :animated pseudo-selector
2722                                 el.data( dataSpaceAnimated, true );
2724                                 // Save effect mode for later use,
2725                                 // we can't just call $.effects.mode again later,
2726                                 // as the .show() below destroys the initial state
2727                                 modes.push( normalizedMode );
2729                                 // See $.uiBackCompat inside of run() for removal of defaultMode in 1.14
2730                                 if ( defaultMode && ( normalizedMode === "show" ||
2731                                                 ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
2732                                         el.show();
2733                                 }
2735                                 if ( !defaultMode || normalizedMode !== "none" ) {
2736                                         $.effects.saveStyle( el );
2737                                 }
2739                                 if ( typeof next === "function" ) {
2740                                         next();
2741                                 }
2742                         };
2744                 if ( $.fx.off || !effectMethod ) {
2746                         // Delegate to the original method (e.g., .show()) if possible
2747                         if ( mode ) {
2748                                 return this[ mode ]( args.duration, complete );
2749                         } else {
2750                                 return this.each( function() {
2751                                         if ( complete ) {
2752                                                 complete.call( this );
2753                                         }
2754                                 } );
2755                         }
2756                 }
2758                 function run( next ) {
2759                         var elem = $( this );
2761                         function cleanup() {
2762                                 elem.removeData( dataSpaceAnimated );
2764                                 $.effects.cleanUp( elem );
2766                                 if ( args.mode === "hide" ) {
2767                                         elem.hide();
2768                                 }
2770                                 done();
2771                         }
2773                         function done() {
2774                                 if ( typeof complete === "function" ) {
2775                                         complete.call( elem[ 0 ] );
2776                                 }
2778                                 if ( typeof next === "function" ) {
2779                                         next();
2780                                 }
2781                         }
2783                         // Override mode option on a per element basis,
2784                         // as toggle can be either show or hide depending on element state
2785                         args.mode = modes.shift();
2787                         if ( $.uiBackCompat !== false && !defaultMode ) {
2788                                 if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
2790                                         // Call the core method to track "olddisplay" properly
2791                                         elem[ mode ]();
2792                                         done();
2793                                 } else {
2794                                         effectMethod.call( elem[ 0 ], args, done );
2795                                 }
2796                         } else {
2797                                 if ( args.mode === "none" ) {
2799                                         // Call the core method to track "olddisplay" properly
2800                                         elem[ mode ]();
2801                                         done();
2802                                 } else {
2803                                         effectMethod.call( elem[ 0 ], args, cleanup );
2804                                 }
2805                         }
2806                 }
2808                 // Run prefilter on all elements first to ensure that
2809                 // any showing or hiding happens before placeholder creation,
2810                 // which ensures that any layout changes are correctly captured.
2811                 return queue === false ?
2812                         this.each( prefilter ).each( run ) :
2813                         this.queue( queueName, prefilter ).queue( queueName, run );
2814         },
2816         show: ( function( orig ) {
2817                 return function( option ) {
2818                         if ( standardAnimationOption( option ) ) {
2819                                 return orig.apply( this, arguments );
2820                         } else {
2821                                 var args = _normalizeArguments.apply( this, arguments );
2822                                 args.mode = "show";
2823                                 return this.effect.call( this, args );
2824                         }
2825                 };
2826         } )( $.fn.show ),
2828         hide: ( function( orig ) {
2829                 return function( option ) {
2830                         if ( standardAnimationOption( option ) ) {
2831                                 return orig.apply( this, arguments );
2832                         } else {
2833                                 var args = _normalizeArguments.apply( this, arguments );
2834                                 args.mode = "hide";
2835                                 return this.effect.call( this, args );
2836                         }
2837                 };
2838         } )( $.fn.hide ),
2840         toggle: ( function( orig ) {
2841                 return function( option ) {
2842                         if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
2843                                 return orig.apply( this, arguments );
2844                         } else {
2845                                 var args = _normalizeArguments.apply( this, arguments );
2846                                 args.mode = "toggle";
2847                                 return this.effect.call( this, args );
2848                         }
2849                 };
2850         } )( $.fn.toggle ),
2852         cssUnit: function( key ) {
2853                 var style = this.css( key ),
2854                         val = [];
2856                 $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
2857                         if ( style.indexOf( unit ) > 0 ) {
2858                                 val = [ parseFloat( style ), unit ];
2859                         }
2860                 } );
2861                 return val;
2862         },
2864         cssClip: function( clipObj ) {
2865                 if ( clipObj ) {
2866                         return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
2867                                 clipObj.bottom + "px " + clipObj.left + "px)" );
2868                 }
2869                 return parseClip( this.css( "clip" ), this );
2870         },
2872         transfer: function( options, done ) {
2873                 var element = $( this ),
2874                         target = $( options.to ),
2875                         targetFixed = target.css( "position" ) === "fixed",
2876                         body = $( "body" ),
2877                         fixTop = targetFixed ? body.scrollTop() : 0,
2878                         fixLeft = targetFixed ? body.scrollLeft() : 0,
2879                         endPosition = target.offset(),
2880                         animation = {
2881                                 top: endPosition.top - fixTop,
2882                                 left: endPosition.left - fixLeft,
2883                                 height: target.innerHeight(),
2884                                 width: target.innerWidth()
2885                         },
2886                         startPosition = element.offset(),
2887                         transfer = $( "<div class='ui-effects-transfer'></div>" );
2889                 transfer
2890                         .appendTo( "body" )
2891                         .addClass( options.className )
2892                         .css( {
2893                                 top: startPosition.top - fixTop,
2894                                 left: startPosition.left - fixLeft,
2895                                 height: element.innerHeight(),
2896                                 width: element.innerWidth(),
2897                                 position: targetFixed ? "fixed" : "absolute"
2898                         } )
2899                         .animate( animation, options.duration, options.easing, function() {
2900                                 transfer.remove();
2901                                 if ( typeof done === "function" ) {
2902                                         done();
2903                                 }
2904                         } );
2905         }
2906 } );
2908 function parseClip( str, element ) {
2909                 var outerWidth = element.outerWidth(),
2910                         outerHeight = element.outerHeight(),
2911                         clipRegex = /^rect\((-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto),?\s*(-?\d*\.?\d*px|-?\d+%|auto)\)$/,
2912                         values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
2914                 return {
2915                         top: parseFloat( values[ 1 ] ) || 0,
2916                         right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
2917                         bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
2918                         left: parseFloat( values[ 4 ] ) || 0
2919                 };
2922 $.fx.step.clip = function( fx ) {
2923         if ( !fx.clipInit ) {
2924                 fx.start = $( fx.elem ).cssClip();
2925                 if ( typeof fx.end === "string" ) {
2926                         fx.end = parseClip( fx.end, fx.elem );
2927                 }
2928                 fx.clipInit = true;
2929         }
2931         $( fx.elem ).cssClip( {
2932                 top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
2933                 right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
2934                 bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
2935                 left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
2936         } );
2939 } )();
2941 /******************************************************************************/
2942 /*********************************** EASING ***********************************/
2943 /******************************************************************************/
2945 ( function() {
2947 // Based on easing equations from Robert Penner (http://www.robertpenner.com/easing)
2949 var baseEasings = {};
2951 $.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
2952         baseEasings[ name ] = function( p ) {
2953                 return Math.pow( p, i + 2 );
2954         };
2955 } );
2957 $.extend( baseEasings, {
2958         Sine: function( p ) {
2959                 return 1 - Math.cos( p * Math.PI / 2 );
2960         },
2961         Circ: function( p ) {
2962                 return 1 - Math.sqrt( 1 - p * p );
2963         },
2964         Elastic: function( p ) {
2965                 return p === 0 || p === 1 ? p :
2966                         -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
2967         },
2968         Back: function( p ) {
2969                 return p * p * ( 3 * p - 2 );
2970         },
2971         Bounce: function( p ) {
2972                 var pow2,
2973                         bounce = 4;
2975                 while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
2976                 return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
2977         }
2978 } );
2980 $.each( baseEasings, function( name, easeIn ) {
2981         $.easing[ "easeIn" + name ] = easeIn;
2982         $.easing[ "easeOut" + name ] = function( p ) {
2983                 return 1 - easeIn( 1 - p );
2984         };
2985         $.easing[ "easeInOut" + name ] = function( p ) {
2986                 return p < 0.5 ?
2987                         easeIn( p * 2 ) / 2 :
2988                         1 - easeIn( p * -2 + 2 ) / 2;
2989         };
2990 } );
2992 } )();
2994 var effect = $.effects;
2998  * jQuery UI Effects Blind 1.13.0
2999  * http://jqueryui.com
3001  * Copyright jQuery Foundation and other contributors
3002  * Released under the MIT license.
3003  * http://jquery.org/license
3004  */
3006 //>>label: Blind Effect
3007 //>>group: Effects
3008 //>>description: Blinds the element.
3009 //>>docs: http://api.jqueryui.com/blind-effect/
3010 //>>demos: http://jqueryui.com/effect/
3013 var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
3014         var map = {
3015                         up: [ "bottom", "top" ],
3016                         vertical: [ "bottom", "top" ],
3017                         down: [ "top", "bottom" ],
3018                         left: [ "right", "left" ],
3019                         horizontal: [ "right", "left" ],
3020                         right: [ "left", "right" ]
3021                 },
3022                 element = $( this ),
3023                 direction = options.direction || "up",
3024                 start = element.cssClip(),
3025                 animate = { clip: $.extend( {}, start ) },
3026                 placeholder = $.effects.createPlaceholder( element );
3028         animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
3030         if ( options.mode === "show" ) {
3031                 element.cssClip( animate.clip );
3032                 if ( placeholder ) {
3033                         placeholder.css( $.effects.clipToBox( animate ) );
3034                 }
3036                 animate.clip = start;
3037         }
3039         if ( placeholder ) {
3040                 placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
3041         }
3043         element.animate( animate, {
3044                 queue: false,
3045                 duration: options.duration,
3046                 easing: options.easing,
3047                 complete: done
3048         } );
3049 } );
3053  * jQuery UI Effects Bounce 1.13.0
3054  * http://jqueryui.com
3056  * Copyright jQuery Foundation and other contributors
3057  * Released under the MIT license.
3058  * http://jquery.org/license
3059  */
3061 //>>label: Bounce Effect
3062 //>>group: Effects
3063 //>>description: Bounces an element horizontally or vertically n times.
3064 //>>docs: http://api.jqueryui.com/bounce-effect/
3065 //>>demos: http://jqueryui.com/effect/
3068 var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
3069         var upAnim, downAnim, refValue,
3070                 element = $( this ),
3072                 // Defaults:
3073                 mode = options.mode,
3074                 hide = mode === "hide",
3075                 show = mode === "show",
3076                 direction = options.direction || "up",
3077                 distance = options.distance,
3078                 times = options.times || 5,
3080                 // Number of internal animations
3081                 anims = times * 2 + ( show || hide ? 1 : 0 ),
3082                 speed = options.duration / anims,
3083                 easing = options.easing,
3085                 // Utility:
3086                 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3087                 motion = ( direction === "up" || direction === "left" ),
3088                 i = 0,
3090                 queuelen = element.queue().length;
3092         $.effects.createPlaceholder( element );
3094         refValue = element.css( ref );
3096         // Default distance for the BIGGEST bounce is the outer Distance / 3
3097         if ( !distance ) {
3098                 distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
3099         }
3101         if ( show ) {
3102                 downAnim = { opacity: 1 };
3103                 downAnim[ ref ] = refValue;
3105                 // If we are showing, force opacity 0 and set the initial position
3106                 // then do the "first" animation
3107                 element
3108                         .css( "opacity", 0 )
3109                         .css( ref, motion ? -distance * 2 : distance * 2 )
3110                         .animate( downAnim, speed, easing );
3111         }
3113         // Start at the smallest distance if we are hiding
3114         if ( hide ) {
3115                 distance = distance / Math.pow( 2, times - 1 );
3116         }
3118         downAnim = {};
3119         downAnim[ ref ] = refValue;
3121         // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
3122         for ( ; i < times; i++ ) {
3123                 upAnim = {};
3124                 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3126                 element
3127                         .animate( upAnim, speed, easing )
3128                         .animate( downAnim, speed, easing );
3130                 distance = hide ? distance * 2 : distance / 2;
3131         }
3133         // Last Bounce when Hiding
3134         if ( hide ) {
3135                 upAnim = { opacity: 0 };
3136                 upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3138                 element.animate( upAnim, speed, easing );
3139         }
3141         element.queue( done );
3143         $.effects.unshift( element, queuelen, anims + 1 );
3144 } );
3148  * jQuery UI Effects Clip 1.13.0
3149  * http://jqueryui.com
3151  * Copyright jQuery Foundation and other contributors
3152  * Released under the MIT license.
3153  * http://jquery.org/license
3154  */
3156 //>>label: Clip Effect
3157 //>>group: Effects
3158 //>>description: Clips the element on and off like an old TV.
3159 //>>docs: http://api.jqueryui.com/clip-effect/
3160 //>>demos: http://jqueryui.com/effect/
3163 var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
3164         var start,
3165                 animate = {},
3166                 element = $( this ),
3167                 direction = options.direction || "vertical",
3168                 both = direction === "both",
3169                 horizontal = both || direction === "horizontal",
3170                 vertical = both || direction === "vertical";
3172         start = element.cssClip();
3173         animate.clip = {
3174                 top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
3175                 right: horizontal ? ( start.right - start.left ) / 2 : start.right,
3176                 bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
3177                 left: horizontal ? ( start.right - start.left ) / 2 : start.left
3178         };
3180         $.effects.createPlaceholder( element );
3182         if ( options.mode === "show" ) {
3183                 element.cssClip( animate.clip );
3184                 animate.clip = start;
3185         }
3187         element.animate( animate, {
3188                 queue: false,
3189                 duration: options.duration,
3190                 easing: options.easing,
3191                 complete: done
3192         } );
3194 } );
3198  * jQuery UI Effects Drop 1.13.0
3199  * http://jqueryui.com
3201  * Copyright jQuery Foundation and other contributors
3202  * Released under the MIT license.
3203  * http://jquery.org/license
3204  */
3206 //>>label: Drop Effect
3207 //>>group: Effects
3208 //>>description: Moves an element in one direction and hides it at the same time.
3209 //>>docs: http://api.jqueryui.com/drop-effect/
3210 //>>demos: http://jqueryui.com/effect/
3213 var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
3215         var distance,
3216                 element = $( this ),
3217                 mode = options.mode,
3218                 show = mode === "show",
3219                 direction = options.direction || "left",
3220                 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3221                 motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
3222                 oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
3223                 animation = {
3224                         opacity: 0
3225                 };
3227         $.effects.createPlaceholder( element );
3229         distance = options.distance ||
3230                 element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
3232         animation[ ref ] = motion + distance;
3234         if ( show ) {
3235                 element.css( animation );
3237                 animation[ ref ] = oppositeMotion + distance;
3238                 animation.opacity = 1;
3239         }
3241         // Animate
3242         element.animate( animation, {
3243                 queue: false,
3244                 duration: options.duration,
3245                 easing: options.easing,
3246                 complete: done
3247         } );
3248 } );
3252  * jQuery UI Effects Explode 1.13.0
3253  * http://jqueryui.com
3255  * Copyright jQuery Foundation and other contributors
3256  * Released under the MIT license.
3257  * http://jquery.org/license
3258  */
3260 //>>label: Explode Effect
3261 //>>group: Effects
3262 /* eslint-disable max-len */
3263 //>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
3264 /* eslint-enable max-len */
3265 //>>docs: http://api.jqueryui.com/explode-effect/
3266 //>>demos: http://jqueryui.com/effect/
3269 var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
3271         var i, j, left, top, mx, my,
3272                 rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
3273                 cells = rows,
3274                 element = $( this ),
3275                 mode = options.mode,
3276                 show = mode === "show",
3278                 // Show and then visibility:hidden the element before calculating offset
3279                 offset = element.show().css( "visibility", "hidden" ).offset(),
3281                 // Width and height of a piece
3282                 width = Math.ceil( element.outerWidth() / cells ),
3283                 height = Math.ceil( element.outerHeight() / rows ),
3284                 pieces = [];
3286         // Children animate complete:
3287         function childComplete() {
3288                 pieces.push( this );
3289                 if ( pieces.length === rows * cells ) {
3290                         animComplete();
3291                 }
3292         }
3294         // Clone the element for each row and cell.
3295         for ( i = 0; i < rows; i++ ) { // ===>
3296                 top = offset.top + i * height;
3297                 my = i - ( rows - 1 ) / 2;
3299                 for ( j = 0; j < cells; j++ ) { // |||
3300                         left = offset.left + j * width;
3301                         mx = j - ( cells - 1 ) / 2;
3303                         // Create a clone of the now hidden main element that will be absolute positioned
3304                         // within a wrapper div off the -left and -top equal to size of our pieces
3305                         element
3306                                 .clone()
3307                                 .appendTo( "body" )
3308                                 .wrap( "<div></div>" )
3309                                 .css( {
3310                                         position: "absolute",
3311                                         visibility: "visible",
3312                                         left: -j * width,
3313                                         top: -i * height
3314                                 } )
3316                                 // Select the wrapper - make it overflow: hidden and absolute positioned based on
3317                                 // where the original was located +left and +top equal to the size of pieces
3318                                 .parent()
3319                                         .addClass( "ui-effects-explode" )
3320                                         .css( {
3321                                                 position: "absolute",
3322                                                 overflow: "hidden",
3323                                                 width: width,
3324                                                 height: height,
3325                                                 left: left + ( show ? mx * width : 0 ),
3326                                                 top: top + ( show ? my * height : 0 ),
3327                                                 opacity: show ? 0 : 1
3328                                         } )
3329                                         .animate( {
3330                                                 left: left + ( show ? 0 : mx * width ),
3331                                                 top: top + ( show ? 0 : my * height ),
3332                                                 opacity: show ? 1 : 0
3333                                         }, options.duration || 500, options.easing, childComplete );
3334                 }
3335         }
3337         function animComplete() {
3338                 element.css( {
3339                         visibility: "visible"
3340                 } );
3341                 $( pieces ).remove();
3342                 done();
3343         }
3344 } );
3348  * jQuery UI Effects Fade 1.13.0
3349  * http://jqueryui.com
3351  * Copyright jQuery Foundation and other contributors
3352  * Released under the MIT license.
3353  * http://jquery.org/license
3354  */
3356 //>>label: Fade Effect
3357 //>>group: Effects
3358 //>>description: Fades the element.
3359 //>>docs: http://api.jqueryui.com/fade-effect/
3360 //>>demos: http://jqueryui.com/effect/
3363 var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
3364         var show = options.mode === "show";
3366         $( this )
3367                 .css( "opacity", show ? 0 : 1 )
3368                 .animate( {
3369                         opacity: show ? 1 : 0
3370                 }, {
3371                         queue: false,
3372                         duration: options.duration,
3373                         easing: options.easing,
3374                         complete: done
3375                 } );
3376 } );
3380  * jQuery UI Effects Fold 1.13.0
3381  * http://jqueryui.com
3383  * Copyright jQuery Foundation and other contributors
3384  * Released under the MIT license.
3385  * http://jquery.org/license
3386  */
3388 //>>label: Fold Effect
3389 //>>group: Effects
3390 //>>description: Folds an element first horizontally and then vertically.
3391 //>>docs: http://api.jqueryui.com/fold-effect/
3392 //>>demos: http://jqueryui.com/effect/
3395 var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
3397         // Create element
3398         var element = $( this ),
3399                 mode = options.mode,
3400                 show = mode === "show",
3401                 hide = mode === "hide",
3402                 size = options.size || 15,
3403                 percent = /([0-9]+)%/.exec( size ),
3404                 horizFirst = !!options.horizFirst,
3405                 ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
3406                 duration = options.duration / 2,
3408                 placeholder = $.effects.createPlaceholder( element ),
3410                 start = element.cssClip(),
3411                 animation1 = { clip: $.extend( {}, start ) },
3412                 animation2 = { clip: $.extend( {}, start ) },
3414                 distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
3416                 queuelen = element.queue().length;
3418         if ( percent ) {
3419                 size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
3420         }
3421         animation1.clip[ ref[ 0 ] ] = size;
3422         animation2.clip[ ref[ 0 ] ] = size;
3423         animation2.clip[ ref[ 1 ] ] = 0;
3425         if ( show ) {
3426                 element.cssClip( animation2.clip );
3427                 if ( placeholder ) {
3428                         placeholder.css( $.effects.clipToBox( animation2 ) );
3429                 }
3431                 animation2.clip = start;
3432         }
3434         // Animate
3435         element
3436                 .queue( function( next ) {
3437                         if ( placeholder ) {
3438                                 placeholder
3439                                         .animate( $.effects.clipToBox( animation1 ), duration, options.easing )
3440                                         .animate( $.effects.clipToBox( animation2 ), duration, options.easing );
3441                         }
3443                         next();
3444                 } )
3445                 .animate( animation1, duration, options.easing )
3446                 .animate( animation2, duration, options.easing )
3447                 .queue( done );
3449         $.effects.unshift( element, queuelen, 4 );
3450 } );
3454  * jQuery UI Effects Highlight 1.13.0
3455  * http://jqueryui.com
3457  * Copyright jQuery Foundation and other contributors
3458  * Released under the MIT license.
3459  * http://jquery.org/license
3460  */
3462 //>>label: Highlight Effect
3463 //>>group: Effects
3464 //>>description: Highlights the background of an element in a defined color for a custom duration.
3465 //>>docs: http://api.jqueryui.com/highlight-effect/
3466 //>>demos: http://jqueryui.com/effect/
3469 var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
3470         var element = $( this ),
3471                 animation = {
3472                         backgroundColor: element.css( "backgroundColor" )
3473                 };
3475         if ( options.mode === "hide" ) {
3476                 animation.opacity = 0;
3477         }
3479         $.effects.saveStyle( element );
3481         element
3482                 .css( {
3483                         backgroundImage: "none",
3484                         backgroundColor: options.color || "#ffff99"
3485                 } )
3486                 .animate( animation, {
3487                         queue: false,
3488                         duration: options.duration,
3489                         easing: options.easing,
3490                         complete: done
3491                 } );
3492 } );
3496  * jQuery UI Effects Size 1.13.0
3497  * http://jqueryui.com
3499  * Copyright jQuery Foundation and other contributors
3500  * Released under the MIT license.
3501  * http://jquery.org/license
3502  */
3504 //>>label: Size Effect
3505 //>>group: Effects
3506 //>>description: Resize an element to a specified width and height.
3507 //>>docs: http://api.jqueryui.com/size-effect/
3508 //>>demos: http://jqueryui.com/effect/
3511 var effectsEffectSize = $.effects.define( "size", function( options, done ) {
3513         // Create element
3514         var baseline, factor, temp,
3515                 element = $( this ),
3517                 // Copy for children
3518                 cProps = [ "fontSize" ],
3519                 vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
3520                 hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
3522                 // Set options
3523                 mode = options.mode,
3524                 restore = mode !== "effect",
3525                 scale = options.scale || "both",
3526                 origin = options.origin || [ "middle", "center" ],
3527                 position = element.css( "position" ),
3528                 pos = element.position(),
3529                 original = $.effects.scaledDimensions( element ),
3530                 from = options.from || original,
3531                 to = options.to || $.effects.scaledDimensions( element, 0 );
3533         $.effects.createPlaceholder( element );
3535         if ( mode === "show" ) {
3536                 temp = from;
3537                 from = to;
3538                 to = temp;
3539         }
3541         // Set scaling factor
3542         factor = {
3543                 from: {
3544                         y: from.height / original.height,
3545                         x: from.width / original.width
3546                 },
3547                 to: {
3548                         y: to.height / original.height,
3549                         x: to.width / original.width
3550                 }
3551         };
3553         // Scale the css box
3554         if ( scale === "box" || scale === "both" ) {
3556                 // Vertical props scaling
3557                 if ( factor.from.y !== factor.to.y ) {
3558                         from = $.effects.setTransition( element, vProps, factor.from.y, from );
3559                         to = $.effects.setTransition( element, vProps, factor.to.y, to );
3560                 }
3562                 // Horizontal props scaling
3563                 if ( factor.from.x !== factor.to.x ) {
3564                         from = $.effects.setTransition( element, hProps, factor.from.x, from );
3565                         to = $.effects.setTransition( element, hProps, factor.to.x, to );
3566                 }
3567         }
3569         // Scale the content
3570         if ( scale === "content" || scale === "both" ) {
3572                 // Vertical props scaling
3573                 if ( factor.from.y !== factor.to.y ) {
3574                         from = $.effects.setTransition( element, cProps, factor.from.y, from );
3575                         to = $.effects.setTransition( element, cProps, factor.to.y, to );
3576                 }
3577         }
3579         // Adjust the position properties based on the provided origin points
3580         if ( origin ) {
3581                 baseline = $.effects.getBaseline( origin, original );
3582                 from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
3583                 from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
3584                 to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
3585                 to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
3586         }
3587         delete from.outerHeight;
3588         delete from.outerWidth;
3589         element.css( from );
3591         // Animate the children if desired
3592         if ( scale === "content" || scale === "both" ) {
3594                 vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
3595                 hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
3597                 // Only animate children with width attributes specified
3598                 // TODO: is this right? should we include anything with css width specified as well
3599                 element.find( "*[width]" ).each( function() {
3600                         var child = $( this ),
3601                                 childOriginal = $.effects.scaledDimensions( child ),
3602                                 childFrom = {
3603                                         height: childOriginal.height * factor.from.y,
3604                                         width: childOriginal.width * factor.from.x,
3605                                         outerHeight: childOriginal.outerHeight * factor.from.y,
3606                                         outerWidth: childOriginal.outerWidth * factor.from.x
3607                                 },
3608                                 childTo = {
3609                                         height: childOriginal.height * factor.to.y,
3610                                         width: childOriginal.width * factor.to.x,
3611                                         outerHeight: childOriginal.height * factor.to.y,
3612                                         outerWidth: childOriginal.width * factor.to.x
3613                                 };
3615                         // Vertical props scaling
3616                         if ( factor.from.y !== factor.to.y ) {
3617                                 childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
3618                                 childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
3619                         }
3621                         // Horizontal props scaling
3622                         if ( factor.from.x !== factor.to.x ) {
3623                                 childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
3624                                 childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
3625                         }
3627                         if ( restore ) {
3628                                 $.effects.saveStyle( child );
3629                         }
3631                         // Animate children
3632                         child.css( childFrom );
3633                         child.animate( childTo, options.duration, options.easing, function() {
3635                                 // Restore children
3636                                 if ( restore ) {
3637                                         $.effects.restoreStyle( child );
3638                                 }
3639                         } );
3640                 } );
3641         }
3643         // Animate
3644         element.animate( to, {
3645                 queue: false,
3646                 duration: options.duration,
3647                 easing: options.easing,
3648                 complete: function() {
3650                         var offset = element.offset();
3652                         if ( to.opacity === 0 ) {
3653                                 element.css( "opacity", from.opacity );
3654                         }
3656                         if ( !restore ) {
3657                                 element
3658                                         .css( "position", position === "static" ? "relative" : position )
3659                                         .offset( offset );
3661                                 // Need to save style here so that automatic style restoration
3662                                 // doesn't restore to the original styles from before the animation.
3663                                 $.effects.saveStyle( element );
3664                         }
3666                         done();
3667                 }
3668         } );
3670 } );
3674  * jQuery UI Effects Scale 1.13.0
3675  * http://jqueryui.com
3677  * Copyright jQuery Foundation and other contributors
3678  * Released under the MIT license.
3679  * http://jquery.org/license
3680  */
3682 //>>label: Scale Effect
3683 //>>group: Effects
3684 //>>description: Grows or shrinks an element and its content.
3685 //>>docs: http://api.jqueryui.com/scale-effect/
3686 //>>demos: http://jqueryui.com/effect/
3689 var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
3691         // Create element
3692         var el = $( this ),
3693                 mode = options.mode,
3694                 percent = parseInt( options.percent, 10 ) ||
3695                         ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
3697                 newOptions = $.extend( true, {
3698                         from: $.effects.scaledDimensions( el ),
3699                         to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
3700                         origin: options.origin || [ "middle", "center" ]
3701                 }, options );
3703         // Fade option to support puff
3704         if ( options.fade ) {
3705                 newOptions.from.opacity = 1;
3706                 newOptions.to.opacity = 0;
3707         }
3709         $.effects.effect.size.call( this, newOptions, done );
3710 } );
3714  * jQuery UI Effects Puff 1.13.0
3715  * http://jqueryui.com
3717  * Copyright jQuery Foundation and other contributors
3718  * Released under the MIT license.
3719  * http://jquery.org/license
3720  */
3722 //>>label: Puff Effect
3723 //>>group: Effects
3724 //>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
3725 //>>docs: http://api.jqueryui.com/puff-effect/
3726 //>>demos: http://jqueryui.com/effect/
3729 var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
3730         var newOptions = $.extend( true, {}, options, {
3731                 fade: true,
3732                 percent: parseInt( options.percent, 10 ) || 150
3733         } );
3735         $.effects.effect.scale.call( this, newOptions, done );
3736 } );
3740  * jQuery UI Effects Pulsate 1.13.0
3741  * http://jqueryui.com
3743  * Copyright jQuery Foundation and other contributors
3744  * Released under the MIT license.
3745  * http://jquery.org/license
3746  */
3748 //>>label: Pulsate Effect
3749 //>>group: Effects
3750 //>>description: Pulsates an element n times by changing the opacity to zero and back.
3751 //>>docs: http://api.jqueryui.com/pulsate-effect/
3752 //>>demos: http://jqueryui.com/effect/
3755 var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
3756         var element = $( this ),
3757                 mode = options.mode,
3758                 show = mode === "show",
3759                 hide = mode === "hide",
3760                 showhide = show || hide,
3762                 // Showing or hiding leaves off the "last" animation
3763                 anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
3764                 duration = options.duration / anims,
3765                 animateTo = 0,
3766                 i = 1,
3767                 queuelen = element.queue().length;
3769         if ( show || !element.is( ":visible" ) ) {
3770                 element.css( "opacity", 0 ).show();
3771                 animateTo = 1;
3772         }
3774         // Anims - 1 opacity "toggles"
3775         for ( ; i < anims; i++ ) {
3776                 element.animate( { opacity: animateTo }, duration, options.easing );
3777                 animateTo = 1 - animateTo;
3778         }
3780         element.animate( { opacity: animateTo }, duration, options.easing );
3782         element.queue( done );
3784         $.effects.unshift( element, queuelen, anims + 1 );
3785 } );
3789  * jQuery UI Effects Shake 1.13.0
3790  * http://jqueryui.com
3792  * Copyright jQuery Foundation and other contributors
3793  * Released under the MIT license.
3794  * http://jquery.org/license
3795  */
3797 //>>label: Shake Effect
3798 //>>group: Effects
3799 //>>description: Shakes an element horizontally or vertically n times.
3800 //>>docs: http://api.jqueryui.com/shake-effect/
3801 //>>demos: http://jqueryui.com/effect/
3804 var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
3806         var i = 1,
3807                 element = $( this ),
3808                 direction = options.direction || "left",
3809                 distance = options.distance || 20,
3810                 times = options.times || 3,
3811                 anims = times * 2 + 1,
3812                 speed = Math.round( options.duration / anims ),
3813                 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3814                 positiveMotion = ( direction === "up" || direction === "left" ),
3815                 animation = {},
3816                 animation1 = {},
3817                 animation2 = {},
3819                 queuelen = element.queue().length;
3821         $.effects.createPlaceholder( element );
3823         // Animation
3824         animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
3825         animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
3826         animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
3828         // Animate
3829         element.animate( animation, speed, options.easing );
3831         // Shakes
3832         for ( ; i < times; i++ ) {
3833                 element
3834                         .animate( animation1, speed, options.easing )
3835                         .animate( animation2, speed, options.easing );
3836         }
3838         element
3839                 .animate( animation1, speed, options.easing )
3840                 .animate( animation, speed / 2, options.easing )
3841                 .queue( done );
3843         $.effects.unshift( element, queuelen, anims + 1 );
3844 } );
3848  * jQuery UI Effects Slide 1.13.0
3849  * http://jqueryui.com
3851  * Copyright jQuery Foundation and other contributors
3852  * Released under the MIT license.
3853  * http://jquery.org/license
3854  */
3856 //>>label: Slide Effect
3857 //>>group: Effects
3858 //>>description: Slides an element in and out of the viewport.
3859 //>>docs: http://api.jqueryui.com/slide-effect/
3860 //>>demos: http://jqueryui.com/effect/
3863 var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
3864         var startClip, startRef,
3865                 element = $( this ),
3866                 map = {
3867                         up: [ "bottom", "top" ],
3868                         down: [ "top", "bottom" ],
3869                         left: [ "right", "left" ],
3870                         right: [ "left", "right" ]
3871                 },
3872                 mode = options.mode,
3873                 direction = options.direction || "left",
3874                 ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3875                 positiveMotion = ( direction === "up" || direction === "left" ),
3876                 distance = options.distance ||
3877                         element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
3878                 animation = {};
3880         $.effects.createPlaceholder( element );
3882         startClip = element.cssClip();
3883         startRef = element.position()[ ref ];
3885         // Define hide animation
3886         animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
3887         animation.clip = element.cssClip();
3888         animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
3890         // Reverse the animation if we're showing
3891         if ( mode === "show" ) {
3892                 element.cssClip( animation.clip );
3893                 element.css( ref, animation[ ref ] );
3894                 animation.clip = startClip;
3895                 animation[ ref ] = startRef;
3896         }
3898         // Actually animate
3899         element.animate( animation, {
3900                 queue: false,
3901                 duration: options.duration,
3902                 easing: options.easing,
3903                 complete: done
3904         } );
3905 } );
3909  * jQuery UI Effects Transfer 1.13.0
3910  * http://jqueryui.com
3912  * Copyright jQuery Foundation and other contributors
3913  * Released under the MIT license.
3914  * http://jquery.org/license
3915  */
3917 //>>label: Transfer Effect
3918 //>>group: Effects
3919 //>>description: Displays a transfer effect from one element to another.
3920 //>>docs: http://api.jqueryui.com/transfer-effect/
3921 //>>demos: http://jqueryui.com/effect/
3924 var effect;
3925 if ( $.uiBackCompat !== false ) {
3926         effect = $.effects.define( "transfer", function( options, done ) {
3927                 $( this ).transfer( options, done );
3928         } );
3930 var effectsEffectTransfer = effect;
3934  * jQuery UI Focusable 1.13.0
3935  * http://jqueryui.com
3937  * Copyright jQuery Foundation and other contributors
3938  * Released under the MIT license.
3939  * http://jquery.org/license
3940  */
3942 //>>label: :focusable Selector
3943 //>>group: Core
3944 //>>description: Selects elements which can be focused.
3945 //>>docs: http://api.jqueryui.com/focusable-selector/
3948 // Selectors
3949 $.ui.focusable = function( element, hasTabindex ) {
3950         var map, mapName, img, focusableIfVisible, fieldset,
3951                 nodeName = element.nodeName.toLowerCase();
3953         if ( "area" === nodeName ) {
3954                 map = element.parentNode;
3955                 mapName = map.name;
3956                 if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
3957                         return false;
3958                 }
3959                 img = $( "img[usemap='#" + mapName + "']" );
3960                 return img.length > 0 && img.is( ":visible" );
3961         }
3963         if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
3964                 focusableIfVisible = !element.disabled;
3966                 if ( focusableIfVisible ) {
3968                         // Form controls within a disabled fieldset are disabled.
3969                         // However, controls within the fieldset's legend do not get disabled.
3970                         // Since controls generally aren't placed inside legends, we skip
3971                         // this portion of the check.
3972                         fieldset = $( element ).closest( "fieldset" )[ 0 ];
3973                         if ( fieldset ) {
3974                                 focusableIfVisible = !fieldset.disabled;
3975                         }
3976                 }
3977         } else if ( "a" === nodeName ) {
3978                 focusableIfVisible = element.href || hasTabindex;
3979         } else {
3980                 focusableIfVisible = hasTabindex;
3981         }
3983         return focusableIfVisible && $( element ).is( ":visible" ) && visible( $( element ) );
3986 // Support: IE 8 only
3987 // IE 8 doesn't resolve inherit to visible/hidden for computed values
3988 function visible( element ) {
3989         var visibility = element.css( "visibility" );
3990         while ( visibility === "inherit" ) {
3991                 element = element.parent();
3992                 visibility = element.css( "visibility" );
3993         }
3994         return visibility === "visible";
3997 $.extend( $.expr.pseudos, {
3998         focusable: function( element ) {
3999                 return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
4000         }
4001 } );
4003 var focusable = $.ui.focusable;
4007 // Support: IE8 Only
4008 // IE8 does not support the form attribute and when it is supplied. It overwrites the form prop
4009 // with a string, so we need to find the proper form.
4010 var form = $.fn._form = function() {
4011         return typeof this[ 0 ].form === "string" ? this.closest( "form" ) : $( this[ 0 ].form );
4016  * jQuery UI Form Reset Mixin 1.13.0
4017  * http://jqueryui.com
4019  * Copyright jQuery Foundation and other contributors
4020  * Released under the MIT license.
4021  * http://jquery.org/license
4022  */
4024 //>>label: Form Reset Mixin
4025 //>>group: Core
4026 //>>description: Refresh input widgets when their form is reset
4027 //>>docs: http://api.jqueryui.com/form-reset-mixin/
4030 var formResetMixin = $.ui.formResetMixin = {
4031         _formResetHandler: function() {
4032                 var form = $( this );
4034                 // Wait for the form reset to actually happen before refreshing
4035                 setTimeout( function() {
4036                         var instances = form.data( "ui-form-reset-instances" );
4037                         $.each( instances, function() {
4038                                 this.refresh();
4039                         } );
4040                 } );
4041         },
4043         _bindFormResetHandler: function() {
4044                 this.form = this.element._form();
4045                 if ( !this.form.length ) {
4046                         return;
4047                 }
4049                 var instances = this.form.data( "ui-form-reset-instances" ) || [];
4050                 if ( !instances.length ) {
4052                         // We don't use _on() here because we use a single event handler per form
4053                         this.form.on( "reset.ui-form-reset", this._formResetHandler );
4054                 }
4055                 instances.push( this );
4056                 this.form.data( "ui-form-reset-instances", instances );
4057         },
4059         _unbindFormResetHandler: function() {
4060                 if ( !this.form.length ) {
4061                         return;
4062                 }
4064                 var instances = this.form.data( "ui-form-reset-instances" );
4065                 instances.splice( $.inArray( this, instances ), 1 );
4066                 if ( instances.length ) {
4067                         this.form.data( "ui-form-reset-instances", instances );
4068                 } else {
4069                         this.form
4070                                 .removeData( "ui-form-reset-instances" )
4071                                 .off( "reset.ui-form-reset" );
4072                 }
4073         }
4078  * jQuery UI Support for jQuery core 1.8.x and newer 1.13.0
4079  * http://jqueryui.com
4081  * Copyright jQuery Foundation and other contributors
4082  * Released under the MIT license.
4083  * http://jquery.org/license
4085  */
4087 //>>label: jQuery 1.8+ Support
4088 //>>group: Core
4089 //>>description: Support version 1.8.x and newer of jQuery core
4092 // Support: jQuery 1.9.x or older
4093 // $.expr[ ":" ] is deprecated.
4094 if ( !$.expr.pseudos ) {
4095         $.expr.pseudos = $.expr[ ":" ];
4098 // Support: jQuery 1.11.x or older
4099 // $.unique has been renamed to $.uniqueSort
4100 if ( !$.uniqueSort ) {
4101         $.uniqueSort = $.unique;
4104 // Support: jQuery 2.2.x or older.
4105 // This method has been defined in jQuery 3.0.0.
4106 // Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
4107 if ( !$.escapeSelector ) {
4109         // CSS string/identifier serialization
4110         // https://drafts.csswg.org/cssom/#common-serializing-idioms
4111         var rcssescape = /([\0-\x1f\x7f]|^-?\d)|^-$|[^\x80-\uFFFF\w-]/g;
4113         var fcssescape = function( ch, asCodePoint ) {
4114                 if ( asCodePoint ) {
4116                         // U+0000 NULL becomes U+FFFD REPLACEMENT CHARACTER
4117                         if ( ch === "\0" ) {
4118                                 return "\uFFFD";
4119                         }
4121                         // Control characters and (dependent upon position) numbers get escaped as code points
4122                         return ch.slice( 0, -1 ) + "\\" + ch.charCodeAt( ch.length - 1 ).toString( 16 ) + " ";
4123                 }
4125                 // Other potentially-special ASCII characters get backslash-escaped
4126                 return "\\" + ch;
4127         };
4129         $.escapeSelector = function( sel ) {
4130                 return ( sel + "" ).replace( rcssescape, fcssescape );
4131         };
4134 // Support: jQuery 3.4.x or older
4135 // These methods have been defined in jQuery 3.5.0.
4136 if ( !$.fn.even || !$.fn.odd ) {
4137         $.fn.extend( {
4138                 even: function() {
4139                         return this.filter( function( i ) {
4140                                 return i % 2 === 0;
4141                         } );
4142                 },
4143                 odd: function() {
4144                         return this.filter( function( i ) {
4145                                 return i % 2 === 1;
4146                         } );
4147                 }
4148         } );
4153  * jQuery UI Keycode 1.13.0
4154  * http://jqueryui.com
4156  * Copyright jQuery Foundation and other contributors
4157  * Released under the MIT license.
4158  * http://jquery.org/license
4159  */
4161 //>>label: Keycode
4162 //>>group: Core
4163 //>>description: Provide keycodes as keynames
4164 //>>docs: http://api.jqueryui.com/jQuery.ui.keyCode/
4167 var keycode = $.ui.keyCode = {
4168         BACKSPACE: 8,
4169         COMMA: 188,
4170         DELETE: 46,
4171         DOWN: 40,
4172         END: 35,
4173         ENTER: 13,
4174         ESCAPE: 27,
4175         HOME: 36,
4176         LEFT: 37,
4177         PAGE_DOWN: 34,
4178         PAGE_UP: 33,
4179         PERIOD: 190,
4180         RIGHT: 39,
4181         SPACE: 32,
4182         TAB: 9,
4183         UP: 38
4188  * jQuery UI Labels 1.13.0
4189  * http://jqueryui.com
4191  * Copyright jQuery Foundation and other contributors
4192  * Released under the MIT license.
4193  * http://jquery.org/license
4194  */
4196 //>>label: labels
4197 //>>group: Core
4198 //>>description: Find all the labels associated with a given input
4199 //>>docs: http://api.jqueryui.com/labels/
4202 var labels = $.fn.labels = function() {
4203         var ancestor, selector, id, labels, ancestors;
4205         if ( !this.length ) {
4206                 return this.pushStack( [] );
4207         }
4209         // Check control.labels first
4210         if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
4211                 return this.pushStack( this[ 0 ].labels );
4212         }
4214         // Support: IE <= 11, FF <= 37, Android <= 2.3 only
4215         // Above browsers do not support control.labels. Everything below is to support them
4216         // as well as document fragments. control.labels does not work on document fragments
4217         labels = this.eq( 0 ).parents( "label" );
4219         // Look for the label based on the id
4220         id = this.attr( "id" );
4221         if ( id ) {
4223                 // We don't search against the document in case the element
4224                 // is disconnected from the DOM
4225                 ancestor = this.eq( 0 ).parents().last();
4227                 // Get a full set of top level ancestors
4228                 ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
4230                 // Create a selector for the label based on the id
4231                 selector = "label[for='" + $.escapeSelector( id ) + "']";
4233                 labels = labels.add( ancestors.find( selector ).addBack( selector ) );
4235         }
4237         // Return whatever we have found for labels
4238         return this.pushStack( labels );
4243  * jQuery UI Scroll Parent 1.13.0
4244  * http://jqueryui.com
4246  * Copyright jQuery Foundation and other contributors
4247  * Released under the MIT license.
4248  * http://jquery.org/license
4249  */
4251 //>>label: scrollParent
4252 //>>group: Core
4253 //>>description: Get the closest ancestor element that is scrollable.
4254 //>>docs: http://api.jqueryui.com/scrollParent/
4257 var scrollParent = $.fn.scrollParent = function( includeHidden ) {
4258         var position = this.css( "position" ),
4259                 excludeStaticParent = position === "absolute",
4260                 overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
4261                 scrollParent = this.parents().filter( function() {
4262                         var parent = $( this );
4263                         if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
4264                                 return false;
4265                         }
4266                         return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
4267                                 parent.css( "overflow-x" ) );
4268                 } ).eq( 0 );
4270         return position === "fixed" || !scrollParent.length ?
4271                 $( this[ 0 ].ownerDocument || document ) :
4272                 scrollParent;
4277  * jQuery UI Tabbable 1.13.0
4278  * http://jqueryui.com
4280  * Copyright jQuery Foundation and other contributors
4281  * Released under the MIT license.
4282  * http://jquery.org/license
4283  */
4285 //>>label: :tabbable Selector
4286 //>>group: Core
4287 //>>description: Selects elements which can be tabbed to.
4288 //>>docs: http://api.jqueryui.com/tabbable-selector/
4291 var tabbable = $.extend( $.expr.pseudos, {
4292         tabbable: function( element ) {
4293                 var tabIndex = $.attr( element, "tabindex" ),
4294                         hasTabindex = tabIndex != null;
4295                 return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
4296         }
4297 } );
4301  * jQuery UI Unique ID 1.13.0
4302  * http://jqueryui.com
4304  * Copyright jQuery Foundation and other contributors
4305  * Released under the MIT license.
4306  * http://jquery.org/license
4307  */
4309 //>>label: uniqueId
4310 //>>group: Core
4311 //>>description: Functions to generate and remove uniqueId's
4312 //>>docs: http://api.jqueryui.com/uniqueId/
4315 var uniqueId = $.fn.extend( {
4316         uniqueId: ( function() {
4317                 var uuid = 0;
4319                 return function() {
4320                         return this.each( function() {
4321                                 if ( !this.id ) {
4322                                         this.id = "ui-id-" + ( ++uuid );
4323                                 }
4324                         } );
4325                 };
4326         } )(),
4328         removeUniqueId: function() {
4329                 return this.each( function() {
4330                         if ( /^ui-id-\d+$/.test( this.id ) ) {
4331                                 $( this ).removeAttr( "id" );
4332                         }
4333                 } );
4334         }
4335 } );
4339  * jQuery UI Accordion 1.13.0
4340  * http://jqueryui.com
4342  * Copyright jQuery Foundation and other contributors
4343  * Released under the MIT license.
4344  * http://jquery.org/license
4345  */
4347 //>>label: Accordion
4348 //>>group: Widgets
4349 /* eslint-disable max-len */
4350 //>>description: Displays collapsible content panels for presenting information in a limited amount of space.
4351 /* eslint-enable max-len */
4352 //>>docs: http://api.jqueryui.com/accordion/
4353 //>>demos: http://jqueryui.com/accordion/
4354 //>>css.structure: ../../themes/base/core.css
4355 //>>css.structure: ../../themes/base/accordion.css
4356 //>>css.theme: ../../themes/base/theme.css
4359 var widgetsAccordion = $.widget( "ui.accordion", {
4360         version: "1.13.0",
4361         options: {
4362                 active: 0,
4363                 animate: {},
4364                 classes: {
4365                         "ui-accordion-header": "ui-corner-top",
4366                         "ui-accordion-header-collapsed": "ui-corner-all",
4367                         "ui-accordion-content": "ui-corner-bottom"
4368                 },
4369                 collapsible: false,
4370                 event: "click",
4371                 header: function( elem ) {
4372                         return elem.find( "> li > :first-child" ).add( elem.find( "> :not(li)" ).even() );
4373                 },
4374                 heightStyle: "auto",
4375                 icons: {
4376                         activeHeader: "ui-icon-triangle-1-s",
4377                         header: "ui-icon-triangle-1-e"
4378                 },
4380                 // Callbacks
4381                 activate: null,
4382                 beforeActivate: null
4383         },
4385         hideProps: {
4386                 borderTopWidth: "hide",
4387                 borderBottomWidth: "hide",
4388                 paddingTop: "hide",
4389                 paddingBottom: "hide",
4390                 height: "hide"
4391         },
4393         showProps: {
4394                 borderTopWidth: "show",
4395                 borderBottomWidth: "show",
4396                 paddingTop: "show",
4397                 paddingBottom: "show",
4398                 height: "show"
4399         },
4401         _create: function() {
4402                 var options = this.options;
4404                 this.prevShow = this.prevHide = $();
4405                 this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
4406                 this.element.attr( "role", "tablist" );
4408                 // Don't allow collapsible: false and active: false / null
4409                 if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
4410                         options.active = 0;
4411                 }
4413                 this._processPanels();
4415                 // handle negative values
4416                 if ( options.active < 0 ) {
4417                         options.active += this.headers.length;
4418                 }
4419                 this._refresh();
4420         },
4422         _getCreateEventData: function() {
4423                 return {
4424                         header: this.active,
4425                         panel: !this.active.length ? $() : this.active.next()
4426                 };
4427         },
4429         _createIcons: function() {
4430                 var icon, children,
4431                         icons = this.options.icons;
4433                 if ( icons ) {
4434                         icon = $( "<span>" );
4435                         this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
4436                         icon.prependTo( this.headers );
4437                         children = this.active.children( ".ui-accordion-header-icon" );
4438                         this._removeClass( children, icons.header )
4439                                 ._addClass( children, null, icons.activeHeader )
4440                                 ._addClass( this.headers, "ui-accordion-icons" );
4441                 }
4442         },
4444         _destroyIcons: function() {
4445                 this._removeClass( this.headers, "ui-accordion-icons" );
4446                 this.headers.children( ".ui-accordion-header-icon" ).remove();
4447         },
4449         _destroy: function() {
4450                 var contents;
4452                 // Clean up main element
4453                 this.element.removeAttr( "role" );
4455                 // Clean up headers
4456                 this.headers
4457                         .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
4458                         .removeUniqueId();
4460                 this._destroyIcons();
4462                 // Clean up content panels
4463                 contents = this.headers.next()
4464                         .css( "display", "" )
4465                         .removeAttr( "role aria-hidden aria-labelledby" )
4466                         .removeUniqueId();
4468                 if ( this.options.heightStyle !== "content" ) {
4469                         contents.css( "height", "" );
4470                 }
4471         },
4473         _setOption: function( key, value ) {
4474                 if ( key === "active" ) {
4476                         // _activate() will handle invalid values and update this.options
4477                         this._activate( value );
4478                         return;
4479                 }
4481                 if ( key === "event" ) {
4482                         if ( this.options.event ) {
4483                                 this._off( this.headers, this.options.event );
4484                         }
4485                         this._setupEvents( value );
4486                 }
4488                 this._super( key, value );
4490                 // Setting collapsible: false while collapsed; open first panel
4491                 if ( key === "collapsible" && !value && this.options.active === false ) {
4492                         this._activate( 0 );
4493                 }
4495                 if ( key === "icons" ) {
4496                         this._destroyIcons();
4497                         if ( value ) {
4498                                 this._createIcons();
4499                         }
4500                 }
4501         },
4503         _setOptionDisabled: function( value ) {
4504                 this._super( value );
4506                 this.element.attr( "aria-disabled", value );
4508                 // Support: IE8 Only
4509                 // #5332 / #6059 - opacity doesn't cascade to positioned elements in IE
4510                 // so we need to add the disabled class to the headers and panels
4511                 this._toggleClass( null, "ui-state-disabled", !!value );
4512                 this._toggleClass( this.headers.add( this.headers.next() ), null, "ui-state-disabled",
4513                         !!value );
4514         },
4516         _keydown: function( event ) {
4517                 if ( event.altKey || event.ctrlKey ) {
4518                         return;
4519                 }
4521                 var keyCode = $.ui.keyCode,
4522                         length = this.headers.length,
4523                         currentIndex = this.headers.index( event.target ),
4524                         toFocus = false;
4526                 switch ( event.keyCode ) {
4527                 case keyCode.RIGHT:
4528                 case keyCode.DOWN:
4529                         toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4530                         break;
4531                 case keyCode.LEFT:
4532                 case keyCode.UP:
4533                         toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4534                         break;
4535                 case keyCode.SPACE:
4536                 case keyCode.ENTER:
4537                         this._eventHandler( event );
4538                         break;
4539                 case keyCode.HOME:
4540                         toFocus = this.headers[ 0 ];
4541                         break;
4542                 case keyCode.END:
4543                         toFocus = this.headers[ length - 1 ];
4544                         break;
4545                 }
4547                 if ( toFocus ) {
4548                         $( event.target ).attr( "tabIndex", -1 );
4549                         $( toFocus ).attr( "tabIndex", 0 );
4550                         $( toFocus ).trigger( "focus" );
4551                         event.preventDefault();
4552                 }
4553         },
4555         _panelKeyDown: function( event ) {
4556                 if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
4557                         $( event.currentTarget ).prev().trigger( "focus" );
4558                 }
4559         },
4561         refresh: function() {
4562                 var options = this.options;
4563                 this._processPanels();
4565                 // Was collapsed or no panel
4566                 if ( ( options.active === false && options.collapsible === true ) ||
4567                                 !this.headers.length ) {
4568                         options.active = false;
4569                         this.active = $();
4571                 // active false only when collapsible is true
4572                 } else if ( options.active === false ) {
4573                         this._activate( 0 );
4575                 // was active, but active panel is gone
4576                 } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
4578                         // all remaining panel are disabled
4579                         if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
4580                                 options.active = false;
4581                                 this.active = $();
4583                         // activate previous panel
4584                         } else {
4585                                 this._activate( Math.max( 0, options.active - 1 ) );
4586                         }
4588                 // was active, active panel still exists
4589                 } else {
4591                         // make sure active index is correct
4592                         options.active = this.headers.index( this.active );
4593                 }
4595                 this._destroyIcons();
4597                 this._refresh();
4598         },
4600         _processPanels: function() {
4601                 var prevHeaders = this.headers,
4602                         prevPanels = this.panels;
4604                 if ( typeof this.options.header === "function" ) {
4605                         this.headers = this.options.header( this.element );
4606                 } else {
4607                         this.headers = this.element.find( this.options.header );
4608                 }
4609                 this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
4610                         "ui-state-default" );
4612                 this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
4613                 this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
4615                 // Avoid memory leaks (#10056)
4616                 if ( prevPanels ) {
4617                         this._off( prevHeaders.not( this.headers ) );
4618                         this._off( prevPanels.not( this.panels ) );
4619                 }
4620         },
4622         _refresh: function() {
4623                 var maxHeight,
4624                         options = this.options,
4625                         heightStyle = options.heightStyle,
4626                         parent = this.element.parent();
4628                 this.active = this._findActive( options.active );
4629                 this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
4630                         ._removeClass( this.active, "ui-accordion-header-collapsed" );
4631                 this._addClass( this.active.next(), "ui-accordion-content-active" );
4632                 this.active.next().show();
4634                 this.headers
4635                         .attr( "role", "tab" )
4636                         .each( function() {
4637                                 var header = $( this ),
4638                                         headerId = header.uniqueId().attr( "id" ),
4639                                         panel = header.next(),
4640                                         panelId = panel.uniqueId().attr( "id" );
4641                                 header.attr( "aria-controls", panelId );
4642                                 panel.attr( "aria-labelledby", headerId );
4643                         } )
4644                         .next()
4645                                 .attr( "role", "tabpanel" );
4647                 this.headers
4648                         .not( this.active )
4649                                 .attr( {
4650                                         "aria-selected": "false",
4651                                         "aria-expanded": "false",
4652                                         tabIndex: -1
4653                                 } )
4654                                 .next()
4655                                         .attr( {
4656                                                 "aria-hidden": "true"
4657                                         } )
4658                                         .hide();
4660                 // Make sure at least one header is in the tab order
4661                 if ( !this.active.length ) {
4662                         this.headers.eq( 0 ).attr( "tabIndex", 0 );
4663                 } else {
4664                         this.active.attr( {
4665                                 "aria-selected": "true",
4666                                 "aria-expanded": "true",
4667                                 tabIndex: 0
4668                         } )
4669                                 .next()
4670                                         .attr( {
4671                                                 "aria-hidden": "false"
4672                                         } );
4673                 }
4675                 this._createIcons();
4677                 this._setupEvents( options.event );
4679                 if ( heightStyle === "fill" ) {
4680                         maxHeight = parent.height();
4681                         this.element.siblings( ":visible" ).each( function() {
4682                                 var elem = $( this ),
4683                                         position = elem.css( "position" );
4685                                 if ( position === "absolute" || position === "fixed" ) {
4686                                         return;
4687                                 }
4688                                 maxHeight -= elem.outerHeight( true );
4689                         } );
4691                         this.headers.each( function() {
4692                                 maxHeight -= $( this ).outerHeight( true );
4693                         } );
4695                         this.headers.next()
4696                                 .each( function() {
4697                                         $( this ).height( Math.max( 0, maxHeight -
4698                                                 $( this ).innerHeight() + $( this ).height() ) );
4699                                 } )
4700                                 .css( "overflow", "auto" );
4701                 } else if ( heightStyle === "auto" ) {
4702                         maxHeight = 0;
4703                         this.headers.next()
4704                                 .each( function() {
4705                                         var isVisible = $( this ).is( ":visible" );
4706                                         if ( !isVisible ) {
4707                                                 $( this ).show();
4708                                         }
4709                                         maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
4710                                         if ( !isVisible ) {
4711                                                 $( this ).hide();
4712                                         }
4713                                 } )
4714                                 .height( maxHeight );
4715                 }
4716         },
4718         _activate: function( index ) {
4719                 var active = this._findActive( index )[ 0 ];
4721                 // Trying to activate the already active panel
4722                 if ( active === this.active[ 0 ] ) {
4723                         return;
4724                 }
4726                 // Trying to collapse, simulate a click on the currently active header
4727                 active = active || this.active[ 0 ];
4729                 this._eventHandler( {
4730                         target: active,
4731                         currentTarget: active,
4732                         preventDefault: $.noop
4733                 } );
4734         },
4736         _findActive: function( selector ) {
4737                 return typeof selector === "number" ? this.headers.eq( selector ) : $();
4738         },
4740         _setupEvents: function( event ) {
4741                 var events = {
4742                         keydown: "_keydown"
4743                 };
4744                 if ( event ) {
4745                         $.each( event.split( " " ), function( index, eventName ) {
4746                                 events[ eventName ] = "_eventHandler";
4747                         } );
4748                 }
4750                 this._off( this.headers.add( this.headers.next() ) );
4751                 this._on( this.headers, events );
4752                 this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
4753                 this._hoverable( this.headers );
4754                 this._focusable( this.headers );
4755         },
4757         _eventHandler: function( event ) {
4758                 var activeChildren, clickedChildren,
4759                         options = this.options,
4760                         active = this.active,
4761                         clicked = $( event.currentTarget ),
4762                         clickedIsActive = clicked[ 0 ] === active[ 0 ],
4763                         collapsing = clickedIsActive && options.collapsible,
4764                         toShow = collapsing ? $() : clicked.next(),
4765                         toHide = active.next(),
4766                         eventData = {
4767                                 oldHeader: active,
4768                                 oldPanel: toHide,
4769                                 newHeader: collapsing ? $() : clicked,
4770                                 newPanel: toShow
4771                         };
4773                 event.preventDefault();
4775                 if (
4777                                 // click on active header, but not collapsible
4778                                 ( clickedIsActive && !options.collapsible ) ||
4780                                 // allow canceling activation
4781                                 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
4782                         return;
4783                 }
4785                 options.active = collapsing ? false : this.headers.index( clicked );
4787                 // When the call to ._toggle() comes after the class changes
4788                 // it causes a very odd bug in IE 8 (see #6720)
4789                 this.active = clickedIsActive ? $() : clicked;
4790                 this._toggle( eventData );
4792                 // Switch classes
4793                 // corner classes on the previously active header stay after the animation
4794                 this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
4795                 if ( options.icons ) {
4796                         activeChildren = active.children( ".ui-accordion-header-icon" );
4797                         this._removeClass( activeChildren, null, options.icons.activeHeader )
4798                                 ._addClass( activeChildren, null, options.icons.header );
4799                 }
4801                 if ( !clickedIsActive ) {
4802                         this._removeClass( clicked, "ui-accordion-header-collapsed" )
4803                                 ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
4804                         if ( options.icons ) {
4805                                 clickedChildren = clicked.children( ".ui-accordion-header-icon" );
4806                                 this._removeClass( clickedChildren, null, options.icons.header )
4807                                         ._addClass( clickedChildren, null, options.icons.activeHeader );
4808                         }
4810                         this._addClass( clicked.next(), "ui-accordion-content-active" );
4811                 }
4812         },
4814         _toggle: function( data ) {
4815                 var toShow = data.newPanel,
4816                         toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
4818                 // Handle activating a panel during the animation for another activation
4819                 this.prevShow.add( this.prevHide ).stop( true, true );
4820                 this.prevShow = toShow;
4821                 this.prevHide = toHide;
4823                 if ( this.options.animate ) {
4824                         this._animate( toShow, toHide, data );
4825                 } else {
4826                         toHide.hide();
4827                         toShow.show();
4828                         this._toggleComplete( data );
4829                 }
4831                 toHide.attr( {
4832                         "aria-hidden": "true"
4833                 } );
4834                 toHide.prev().attr( {
4835                         "aria-selected": "false",
4836                         "aria-expanded": "false"
4837                 } );
4839                 // if we're switching panels, remove the old header from the tab order
4840                 // if we're opening from collapsed state, remove the previous header from the tab order
4841                 // if we're collapsing, then keep the collapsing header in the tab order
4842                 if ( toShow.length && toHide.length ) {
4843                         toHide.prev().attr( {
4844                                 "tabIndex": -1,
4845                                 "aria-expanded": "false"
4846                         } );
4847                 } else if ( toShow.length ) {
4848                         this.headers.filter( function() {
4849                                 return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
4850                         } )
4851                                 .attr( "tabIndex", -1 );
4852                 }
4854                 toShow
4855                         .attr( "aria-hidden", "false" )
4856                         .prev()
4857                                 .attr( {
4858                                         "aria-selected": "true",
4859                                         "aria-expanded": "true",
4860                                         tabIndex: 0
4861                                 } );
4862         },
4864         _animate: function( toShow, toHide, data ) {
4865                 var total, easing, duration,
4866                         that = this,
4867                         adjust = 0,
4868                         boxSizing = toShow.css( "box-sizing" ),
4869                         down = toShow.length &&
4870                                 ( !toHide.length || ( toShow.index() < toHide.index() ) ),
4871                         animate = this.options.animate || {},
4872                         options = down && animate.down || animate,
4873                         complete = function() {
4874                                 that._toggleComplete( data );
4875                         };
4877                 if ( typeof options === "number" ) {
4878                         duration = options;
4879                 }
4880                 if ( typeof options === "string" ) {
4881                         easing = options;
4882                 }
4884                 // fall back from options to animation in case of partial down settings
4885                 easing = easing || options.easing || animate.easing;
4886                 duration = duration || options.duration || animate.duration;
4888                 if ( !toHide.length ) {
4889                         return toShow.animate( this.showProps, duration, easing, complete );
4890                 }
4891                 if ( !toShow.length ) {
4892                         return toHide.animate( this.hideProps, duration, easing, complete );
4893                 }
4895                 total = toShow.show().outerHeight();
4896                 toHide.animate( this.hideProps, {
4897                         duration: duration,
4898                         easing: easing,
4899                         step: function( now, fx ) {
4900                                 fx.now = Math.round( now );
4901                         }
4902                 } );
4903                 toShow
4904                         .hide()
4905                         .animate( this.showProps, {
4906                                 duration: duration,
4907                                 easing: easing,
4908                                 complete: complete,
4909                                 step: function( now, fx ) {
4910                                         fx.now = Math.round( now );
4911                                         if ( fx.prop !== "height" ) {
4912                                                 if ( boxSizing === "content-box" ) {
4913                                                         adjust += fx.now;
4914                                                 }
4915                                         } else if ( that.options.heightStyle !== "content" ) {
4916                                                 fx.now = Math.round( total - toHide.outerHeight() - adjust );
4917                                                 adjust = 0;
4918                                         }
4919                                 }
4920                         } );
4921         },
4923         _toggleComplete: function( data ) {
4924                 var toHide = data.oldPanel,
4925                         prev = toHide.prev();
4927                 this._removeClass( toHide, "ui-accordion-content-active" );
4928                 this._removeClass( prev, "ui-accordion-header-active" )
4929                         ._addClass( prev, "ui-accordion-header-collapsed" );
4931                 // Work around for rendering bug in IE (#5421)
4932                 if ( toHide.length ) {
4933                         toHide.parent()[ 0 ].className = toHide.parent()[ 0 ].className;
4934                 }
4935                 this._trigger( "activate", null, data );
4936         }
4937 } );
4941 var safeActiveElement = $.ui.safeActiveElement = function( document ) {
4942         var activeElement;
4944         // Support: IE 9 only
4945         // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
4946         try {
4947                 activeElement = document.activeElement;
4948         } catch ( error ) {
4949                 activeElement = document.body;
4950         }
4952         // Support: IE 9 - 11 only
4953         // IE may return null instead of an element
4954         // Interestingly, this only seems to occur when NOT in an iframe
4955         if ( !activeElement ) {
4956                 activeElement = document.body;
4957         }
4959         // Support: IE 11 only
4960         // IE11 returns a seemingly empty object in some cases when accessing
4961         // document.activeElement from an <iframe>
4962         if ( !activeElement.nodeName ) {
4963                 activeElement = document.body;
4964         }
4966         return activeElement;
4971  * jQuery UI Menu 1.13.0
4972  * http://jqueryui.com
4974  * Copyright jQuery Foundation and other contributors
4975  * Released under the MIT license.
4976  * http://jquery.org/license
4977  */
4979 //>>label: Menu
4980 //>>group: Widgets
4981 //>>description: Creates nestable menus.
4982 //>>docs: http://api.jqueryui.com/menu/
4983 //>>demos: http://jqueryui.com/menu/
4984 //>>css.structure: ../../themes/base/core.css
4985 //>>css.structure: ../../themes/base/menu.css
4986 //>>css.theme: ../../themes/base/theme.css
4989 var widgetsMenu = $.widget( "ui.menu", {
4990         version: "1.13.0",
4991         defaultElement: "<ul>",
4992         delay: 300,
4993         options: {
4994                 icons: {
4995                         submenu: "ui-icon-caret-1-e"
4996                 },
4997                 items: "> *",
4998                 menus: "ul",
4999                 position: {
5000                         my: "left top",
5001                         at: "right top"
5002                 },
5003                 role: "menu",
5005                 // Callbacks
5006                 blur: null,
5007                 focus: null,
5008                 select: null
5009         },
5011         _create: function() {
5012                 this.activeMenu = this.element;
5014                 // Flag used to prevent firing of the click handler
5015                 // as the event bubbles up through nested menus
5016                 this.mouseHandled = false;
5017                 this.lastMousePosition = { x: null, y: null };
5018                 this.element
5019                         .uniqueId()
5020                         .attr( {
5021                                 role: this.options.role,
5022                                 tabIndex: 0
5023                         } );
5025                 this._addClass( "ui-menu", "ui-widget ui-widget-content" );
5026                 this._on( {
5028                         // Prevent focus from sticking to links inside menu after clicking
5029                         // them (focus should always stay on UL during navigation).
5030                         "mousedown .ui-menu-item": function( event ) {
5031                                 event.preventDefault();
5033                                 this._activateItem( event );
5034                         },
5035                         "click .ui-menu-item": function( event ) {
5036                                 var target = $( event.target );
5037                                 var active = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
5038                                 if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
5039                                         this.select( event );
5041                                         // Only set the mouseHandled flag if the event will bubble, see #9469.
5042                                         if ( !event.isPropagationStopped() ) {
5043                                                 this.mouseHandled = true;
5044                                         }
5046                                         // Open submenu on click
5047                                         if ( target.has( ".ui-menu" ).length ) {
5048                                                 this.expand( event );
5049                                         } else if ( !this.element.is( ":focus" ) &&
5050                                                         active.closest( ".ui-menu" ).length ) {
5052                                                 // Redirect focus to the menu
5053                                                 this.element.trigger( "focus", [ true ] );
5055                                                 // If the active item is on the top level, let it stay active.
5056                                                 // Otherwise, blur the active item since it is no longer visible.
5057                                                 if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
5058                                                         clearTimeout( this.timer );
5059                                                 }
5060                                         }
5061                                 }
5062                         },
5063                         "mouseenter .ui-menu-item": "_activateItem",
5064                         "mousemove .ui-menu-item": "_activateItem",
5065                         mouseleave: "collapseAll",
5066                         "mouseleave .ui-menu": "collapseAll",
5067                         focus: function( event, keepActiveItem ) {
5069                                 // If there's already an active item, keep it active
5070                                 // If not, activate the first item
5071                                 var item = this.active || this._menuItems().first();
5073                                 if ( !keepActiveItem ) {
5074                                         this.focus( event, item );
5075                                 }
5076                         },
5077                         blur: function( event ) {
5078                                 this._delay( function() {
5079                                         var notContained = !$.contains(
5080                                                 this.element[ 0 ],
5081                                                 $.ui.safeActiveElement( this.document[ 0 ] )
5082                                         );
5083                                         if ( notContained ) {
5084                                                 this.collapseAll( event );
5085                                         }
5086                                 } );
5087                         },
5088                         keydown: "_keydown"
5089                 } );
5091                 this.refresh();
5093                 // Clicks outside of a menu collapse any open menus
5094                 this._on( this.document, {
5095                         click: function( event ) {
5096                                 if ( this._closeOnDocumentClick( event ) ) {
5097                                         this.collapseAll( event, true );
5098                                 }
5100                                 // Reset the mouseHandled flag
5101                                 this.mouseHandled = false;
5102                         }
5103                 } );
5104         },
5106         _activateItem: function( event ) {
5108                 // Ignore mouse events while typeahead is active, see #10458.
5109                 // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
5110                 // is over an item in the menu
5111                 if ( this.previousFilter ) {
5112                         return;
5113                 }
5115                 // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
5116                 if ( event.clientX === this.lastMousePosition.x &&
5117                                 event.clientY === this.lastMousePosition.y ) {
5118                         return;
5119                 }
5121                 this.lastMousePosition = {
5122                         x: event.clientX,
5123                         y: event.clientY
5124                 };
5126                 var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
5127                         target = $( event.currentTarget );
5129                 // Ignore bubbled events on parent items, see #11641
5130                 if ( actualTarget[ 0 ] !== target[ 0 ] ) {
5131                         return;
5132                 }
5134                 // If the item is already active, there's nothing to do
5135                 if ( target.is( ".ui-state-active" ) ) {
5136                         return;
5137                 }
5139                 // Remove ui-state-active class from siblings of the newly focused menu item
5140                 // to avoid a jump caused by adjacent elements both having a class with a border
5141                 this._removeClass( target.siblings().children( ".ui-state-active" ),
5142                         null, "ui-state-active" );
5143                 this.focus( event, target );
5144         },
5146         _destroy: function() {
5147                 var items = this.element.find( ".ui-menu-item" )
5148                                 .removeAttr( "role aria-disabled" ),
5149                         submenus = items.children( ".ui-menu-item-wrapper" )
5150                                 .removeUniqueId()
5151                                 .removeAttr( "tabIndex role aria-haspopup" );
5153                 // Destroy (sub)menus
5154                 this.element
5155                         .removeAttr( "aria-activedescendant" )
5156                         .find( ".ui-menu" ).addBack()
5157                                 .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
5158                                         "tabIndex" )
5159                                 .removeUniqueId()
5160                                 .show();
5162                 submenus.children().each( function() {
5163                         var elem = $( this );
5164                         if ( elem.data( "ui-menu-submenu-caret" ) ) {
5165                                 elem.remove();
5166                         }
5167                 } );
5168         },
5170         _keydown: function( event ) {
5171                 var match, prev, character, skip,
5172                         preventDefault = true;
5174                 switch ( event.keyCode ) {
5175                 case $.ui.keyCode.PAGE_UP:
5176                         this.previousPage( event );
5177                         break;
5178                 case $.ui.keyCode.PAGE_DOWN:
5179                         this.nextPage( event );
5180                         break;
5181                 case $.ui.keyCode.HOME:
5182                         this._move( "first", "first", event );
5183                         break;
5184                 case $.ui.keyCode.END:
5185                         this._move( "last", "last", event );
5186                         break;
5187                 case $.ui.keyCode.UP:
5188                         this.previous( event );
5189                         break;
5190                 case $.ui.keyCode.DOWN:
5191                         this.next( event );
5192                         break;
5193                 case $.ui.keyCode.LEFT:
5194                         this.collapse( event );
5195                         break;
5196                 case $.ui.keyCode.RIGHT:
5197                         if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5198                                 this.expand( event );
5199                         }
5200                         break;
5201                 case $.ui.keyCode.ENTER:
5202                 case $.ui.keyCode.SPACE:
5203                         this._activate( event );
5204                         break;
5205                 case $.ui.keyCode.ESCAPE:
5206                         this.collapse( event );
5207                         break;
5208                 default:
5209                         preventDefault = false;
5210                         prev = this.previousFilter || "";
5211                         skip = false;
5213                         // Support number pad values
5214                         character = event.keyCode >= 96 && event.keyCode <= 105 ?
5215                                 ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
5217                         clearTimeout( this.filterTimer );
5219                         if ( character === prev ) {
5220                                 skip = true;
5221                         } else {
5222                                 character = prev + character;
5223                         }
5225                         match = this._filterMenuItems( character );
5226                         match = skip && match.index( this.active.next() ) !== -1 ?
5227                                 this.active.nextAll( ".ui-menu-item" ) :
5228                                 match;
5230                         // If no matches on the current filter, reset to the last character pressed
5231                         // to move down the menu to the first item that starts with that character
5232                         if ( !match.length ) {
5233                                 character = String.fromCharCode( event.keyCode );
5234                                 match = this._filterMenuItems( character );
5235                         }
5237                         if ( match.length ) {
5238                                 this.focus( event, match );
5239                                 this.previousFilter = character;
5240                                 this.filterTimer = this._delay( function() {
5241                                         delete this.previousFilter;
5242                                 }, 1000 );
5243                         } else {
5244                                 delete this.previousFilter;
5245                         }
5246                 }
5248                 if ( preventDefault ) {
5249                         event.preventDefault();
5250                 }
5251         },
5253         _activate: function( event ) {
5254                 if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5255                         if ( this.active.children( "[aria-haspopup='true']" ).length ) {
5256                                 this.expand( event );
5257                         } else {
5258                                 this.select( event );
5259                         }
5260                 }
5261         },
5263         refresh: function() {
5264                 var menus, items, newSubmenus, newItems, newWrappers,
5265                         that = this,
5266                         icon = this.options.icons.submenu,
5267                         submenus = this.element.find( this.options.menus );
5269                 this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
5271                 // Initialize nested menus
5272                 newSubmenus = submenus.filter( ":not(.ui-menu)" )
5273                         .hide()
5274                         .attr( {
5275                                 role: this.options.role,
5276                                 "aria-hidden": "true",
5277                                 "aria-expanded": "false"
5278                         } )
5279                         .each( function() {
5280                                 var menu = $( this ),
5281                                         item = menu.prev(),
5282                                         submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
5284                                 that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
5285                                 item
5286                                         .attr( "aria-haspopup", "true" )
5287                                         .prepend( submenuCaret );
5288                                 menu.attr( "aria-labelledby", item.attr( "id" ) );
5289                         } );
5291                 this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
5293                 menus = submenus.add( this.element );
5294                 items = menus.find( this.options.items );
5296                 // Initialize menu-items containing spaces and/or dashes only as dividers
5297                 items.not( ".ui-menu-item" ).each( function() {
5298                         var item = $( this );
5299                         if ( that._isDivider( item ) ) {
5300                                 that._addClass( item, "ui-menu-divider", "ui-widget-content" );
5301                         }
5302                 } );
5304                 // Don't refresh list items that are already adapted
5305                 newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
5306                 newWrappers = newItems.children()
5307                         .not( ".ui-menu" )
5308                                 .uniqueId()
5309                                 .attr( {
5310                                         tabIndex: -1,
5311                                         role: this._itemRole()
5312                                 } );
5313                 this._addClass( newItems, "ui-menu-item" )
5314                         ._addClass( newWrappers, "ui-menu-item-wrapper" );
5316                 // Add aria-disabled attribute to any disabled menu item
5317                 items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
5319                 // If the active item has been removed, blur the menu
5320                 if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5321                         this.blur();
5322                 }
5323         },
5325         _itemRole: function() {
5326                 return {
5327                         menu: "menuitem",
5328                         listbox: "option"
5329                 }[ this.options.role ];
5330         },
5332         _setOption: function( key, value ) {
5333                 if ( key === "icons" ) {
5334                         var icons = this.element.find( ".ui-menu-icon" );
5335                         this._removeClass( icons, null, this.options.icons.submenu )
5336                                 ._addClass( icons, null, value.submenu );
5337                 }
5338                 this._super( key, value );
5339         },
5341         _setOptionDisabled: function( value ) {
5342                 this._super( value );
5344                 this.element.attr( "aria-disabled", String( value ) );
5345                 this._toggleClass( null, "ui-state-disabled", !!value );
5346         },
5348         focus: function( event, item ) {
5349                 var nested, focused, activeParent;
5350                 this.blur( event, event && event.type === "focus" );
5352                 this._scrollIntoView( item );
5354                 this.active = item.first();
5356                 focused = this.active.children( ".ui-menu-item-wrapper" );
5357                 this._addClass( focused, null, "ui-state-active" );
5359                 // Only update aria-activedescendant if there's a role
5360                 // otherwise we assume focus is managed elsewhere
5361                 if ( this.options.role ) {
5362                         this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
5363                 }
5365                 // Highlight active parent menu item, if any
5366                 activeParent = this.active
5367                         .parent()
5368                                 .closest( ".ui-menu-item" )
5369                                         .children( ".ui-menu-item-wrapper" );
5370                 this._addClass( activeParent, null, "ui-state-active" );
5372                 if ( event && event.type === "keydown" ) {
5373                         this._close();
5374                 } else {
5375                         this.timer = this._delay( function() {
5376                                 this._close();
5377                         }, this.delay );
5378                 }
5380                 nested = item.children( ".ui-menu" );
5381                 if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
5382                         this._startOpening( nested );
5383                 }
5384                 this.activeMenu = item.parent();
5386                 this._trigger( "focus", event, { item: item } );
5387         },
5389         _scrollIntoView: function( item ) {
5390                 var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
5391                 if ( this._hasScroll() ) {
5392                         borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
5393                         paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
5394                         offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
5395                         scroll = this.activeMenu.scrollTop();
5396                         elementHeight = this.activeMenu.height();
5397                         itemHeight = item.outerHeight();
5399                         if ( offset < 0 ) {
5400                                 this.activeMenu.scrollTop( scroll + offset );
5401                         } else if ( offset + itemHeight > elementHeight ) {
5402                                 this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
5403                         }
5404                 }
5405         },
5407         blur: function( event, fromFocus ) {
5408                 if ( !fromFocus ) {
5409                         clearTimeout( this.timer );
5410                 }
5412                 if ( !this.active ) {
5413                         return;
5414                 }
5416                 this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
5417                         null, "ui-state-active" );
5419                 this._trigger( "blur", event, { item: this.active } );
5420                 this.active = null;
5421         },
5423         _startOpening: function( submenu ) {
5424                 clearTimeout( this.timer );
5426                 // Don't open if already open fixes a Firefox bug that caused a .5 pixel
5427                 // shift in the submenu position when mousing over the caret icon
5428                 if ( submenu.attr( "aria-hidden" ) !== "true" ) {
5429                         return;
5430                 }
5432                 this.timer = this._delay( function() {
5433                         this._close();
5434                         this._open( submenu );
5435                 }, this.delay );
5436         },
5438         _open: function( submenu ) {
5439                 var position = $.extend( {
5440                         of: this.active
5441                 }, this.options.position );
5443                 clearTimeout( this.timer );
5444                 this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
5445                         .hide()
5446                         .attr( "aria-hidden", "true" );
5448                 submenu
5449                         .show()
5450                         .removeAttr( "aria-hidden" )
5451                         .attr( "aria-expanded", "true" )
5452                         .position( position );
5453         },
5455         collapseAll: function( event, all ) {
5456                 clearTimeout( this.timer );
5457                 this.timer = this._delay( function() {
5459                         // If we were passed an event, look for the submenu that contains the event
5460                         var currentMenu = all ? this.element :
5461                                 $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
5463                         // If we found no valid submenu ancestor, use the main menu to close all
5464                         // sub menus anyway
5465                         if ( !currentMenu.length ) {
5466                                 currentMenu = this.element;
5467                         }
5469                         this._close( currentMenu );
5471                         this.blur( event );
5473                         // Work around active item staying active after menu is blurred
5474                         this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
5476                         this.activeMenu = currentMenu;
5477                 }, all ? 0 : this.delay );
5478         },
5480         // With no arguments, closes the currently active menu - if nothing is active
5481         // it closes all menus.  If passed an argument, it will search for menus BELOW
5482         _close: function( startMenu ) {
5483                 if ( !startMenu ) {
5484                         startMenu = this.active ? this.active.parent() : this.element;
5485                 }
5487                 startMenu.find( ".ui-menu" )
5488                         .hide()
5489                         .attr( "aria-hidden", "true" )
5490                         .attr( "aria-expanded", "false" );
5491         },
5493         _closeOnDocumentClick: function( event ) {
5494                 return !$( event.target ).closest( ".ui-menu" ).length;
5495         },
5497         _isDivider: function( item ) {
5499                 // Match hyphen, em dash, en dash
5500                 return !/[^\-\u2014\u2013\s]/.test( item.text() );
5501         },
5503         collapse: function( event ) {
5504                 var newItem = this.active &&
5505                         this.active.parent().closest( ".ui-menu-item", this.element );
5506                 if ( newItem && newItem.length ) {
5507                         this._close();
5508                         this.focus( event, newItem );
5509                 }
5510         },
5512         expand: function( event ) {
5513                 var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
5515                 if ( newItem && newItem.length ) {
5516                         this._open( newItem.parent() );
5518                         // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
5519                         this._delay( function() {
5520                                 this.focus( event, newItem );
5521                         } );
5522                 }
5523         },
5525         next: function( event ) {
5526                 this._move( "next", "first", event );
5527         },
5529         previous: function( event ) {
5530                 this._move( "prev", "last", event );
5531         },
5533         isFirstItem: function() {
5534                 return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
5535         },
5537         isLastItem: function() {
5538                 return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
5539         },
5541         _menuItems: function( menu ) {
5542                 return ( menu || this.element )
5543                         .find( this.options.items )
5544                         .filter( ".ui-menu-item" );
5545         },
5547         _move: function( direction, filter, event ) {
5548                 var next;
5549                 if ( this.active ) {
5550                         if ( direction === "first" || direction === "last" ) {
5551                                 next = this.active
5552                                         [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
5553                                         .last();
5554                         } else {
5555                                 next = this.active
5556                                         [ direction + "All" ]( ".ui-menu-item" )
5557                                         .first();
5558                         }
5559                 }
5560                 if ( !next || !next.length || !this.active ) {
5561                         next = this._menuItems( this.activeMenu )[ filter ]();
5562                 }
5564                 this.focus( event, next );
5565         },
5567         nextPage: function( event ) {
5568                 var item, base, height;
5570                 if ( !this.active ) {
5571                         this.next( event );
5572                         return;
5573                 }
5574                 if ( this.isLastItem() ) {
5575                         return;
5576                 }
5577                 if ( this._hasScroll() ) {
5578                         base = this.active.offset().top;
5579                         height = this.element.innerHeight();
5581                         // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5582                         if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5583                                 height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5584                         }
5586                         this.active.nextAll( ".ui-menu-item" ).each( function() {
5587                                 item = $( this );
5588                                 return item.offset().top - base - height < 0;
5589                         } );
5591                         this.focus( event, item );
5592                 } else {
5593                         this.focus( event, this._menuItems( this.activeMenu )
5594                                 [ !this.active ? "first" : "last" ]() );
5595                 }
5596         },
5598         previousPage: function( event ) {
5599                 var item, base, height;
5600                 if ( !this.active ) {
5601                         this.next( event );
5602                         return;
5603                 }
5604                 if ( this.isFirstItem() ) {
5605                         return;
5606                 }
5607                 if ( this._hasScroll() ) {
5608                         base = this.active.offset().top;
5609                         height = this.element.innerHeight();
5611                         // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5612                         if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5613                                 height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5614                         }
5616                         this.active.prevAll( ".ui-menu-item" ).each( function() {
5617                                 item = $( this );
5618                                 return item.offset().top - base + height > 0;
5619                         } );
5621                         this.focus( event, item );
5622                 } else {
5623                         this.focus( event, this._menuItems( this.activeMenu ).first() );
5624                 }
5625         },
5627         _hasScroll: function() {
5628                 return this.element.outerHeight() < this.element.prop( "scrollHeight" );
5629         },
5631         select: function( event ) {
5633                 // TODO: It should never be possible to not have an active item at this
5634                 // point, but the tests don't trigger mouseenter before click.
5635                 this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
5636                 var ui = { item: this.active };
5637                 if ( !this.active.has( ".ui-menu" ).length ) {
5638                         this.collapseAll( event, true );
5639                 }
5640                 this._trigger( "select", event, ui );
5641         },
5643         _filterMenuItems: function( character ) {
5644                 var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
5645                         regex = new RegExp( "^" + escapedCharacter, "i" );
5647                 return this.activeMenu
5648                         .find( this.options.items )
5650                                 // Only match on items, not dividers or other content (#10571)
5651                                 .filter( ".ui-menu-item" )
5652                                         .filter( function() {
5653                                                 return regex.test(
5654                                                         String.prototype.trim.call(
5655                                                                 $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
5656                                         } );
5657         }
5658 } );
5662  * jQuery UI Autocomplete 1.13.0
5663  * http://jqueryui.com
5665  * Copyright jQuery Foundation and other contributors
5666  * Released under the MIT license.
5667  * http://jquery.org/license
5668  */
5670 //>>label: Autocomplete
5671 //>>group: Widgets
5672 //>>description: Lists suggested words as the user is typing.
5673 //>>docs: http://api.jqueryui.com/autocomplete/
5674 //>>demos: http://jqueryui.com/autocomplete/
5675 //>>css.structure: ../../themes/base/core.css
5676 //>>css.structure: ../../themes/base/autocomplete.css
5677 //>>css.theme: ../../themes/base/theme.css
5680 $.widget( "ui.autocomplete", {
5681         version: "1.13.0",
5682         defaultElement: "<input>",
5683         options: {
5684                 appendTo: null,
5685                 autoFocus: false,
5686                 delay: 300,
5687                 minLength: 1,
5688                 position: {
5689                         my: "left top",
5690                         at: "left bottom",
5691                         collision: "none"
5692                 },
5693                 source: null,
5695                 // Callbacks
5696                 change: null,
5697                 close: null,
5698                 focus: null,
5699                 open: null,
5700                 response: null,
5701                 search: null,
5702                 select: null
5703         },
5705         requestIndex: 0,
5706         pending: 0,
5708         _create: function() {
5710                 // Some browsers only repeat keydown events, not keypress events,
5711                 // so we use the suppressKeyPress flag to determine if we've already
5712                 // handled the keydown event. #7269
5713                 // Unfortunately the code for & in keypress is the same as the up arrow,
5714                 // so we use the suppressKeyPressRepeat flag to avoid handling keypress
5715                 // events when we know the keydown event was used to modify the
5716                 // search term. #7799
5717                 var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5718                         nodeName = this.element[ 0 ].nodeName.toLowerCase(),
5719                         isTextarea = nodeName === "textarea",
5720                         isInput = nodeName === "input";
5722                 // Textareas are always multi-line
5723                 // Inputs are always single-line, even if inside a contentEditable element
5724                 // IE also treats inputs as contentEditable
5725                 // All other element types are determined by whether or not they're contentEditable
5726                 this.isMultiLine = isTextarea || !isInput && this._isContentEditable( this.element );
5728                 this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5729                 this.isNewMenu = true;
5731                 this._addClass( "ui-autocomplete-input" );
5732                 this.element.attr( "autocomplete", "off" );
5734                 this._on( this.element, {
5735                         keydown: function( event ) {
5736                                 if ( this.element.prop( "readOnly" ) ) {
5737                                         suppressKeyPress = true;
5738                                         suppressInput = true;
5739                                         suppressKeyPressRepeat = true;
5740                                         return;
5741                                 }
5743                                 suppressKeyPress = false;
5744                                 suppressInput = false;
5745                                 suppressKeyPressRepeat = false;
5746                                 var keyCode = $.ui.keyCode;
5747                                 switch ( event.keyCode ) {
5748                                 case keyCode.PAGE_UP:
5749                                         suppressKeyPress = true;
5750                                         this._move( "previousPage", event );
5751                                         break;
5752                                 case keyCode.PAGE_DOWN:
5753                                         suppressKeyPress = true;
5754                                         this._move( "nextPage", event );
5755                                         break;
5756                                 case keyCode.UP:
5757                                         suppressKeyPress = true;
5758                                         this._keyEvent( "previous", event );
5759                                         break;
5760                                 case keyCode.DOWN:
5761                                         suppressKeyPress = true;
5762                                         this._keyEvent( "next", event );
5763                                         break;
5764                                 case keyCode.ENTER:
5766                                         // when menu is open and has focus
5767                                         if ( this.menu.active ) {
5769                                                 // #6055 - Opera still allows the keypress to occur
5770                                                 // which causes forms to submit
5771                                                 suppressKeyPress = true;
5772                                                 event.preventDefault();
5773                                                 this.menu.select( event );
5774                                         }
5775                                         break;
5776                                 case keyCode.TAB:
5777                                         if ( this.menu.active ) {
5778                                                 this.menu.select( event );
5779                                         }
5780                                         break;
5781                                 case keyCode.ESCAPE:
5782                                         if ( this.menu.element.is( ":visible" ) ) {
5783                                                 if ( !this.isMultiLine ) {
5784                                                         this._value( this.term );
5785                                                 }
5786                                                 this.close( event );
5788                                                 // Different browsers have different default behavior for escape
5789                                                 // Single press can mean undo or clear
5790                                                 // Double press in IE means clear the whole form
5791                                                 event.preventDefault();
5792                                         }
5793                                         break;
5794                                 default:
5795                                         suppressKeyPressRepeat = true;
5797                                         // search timeout should be triggered before the input value is changed
5798                                         this._searchTimeout( event );
5799                                         break;
5800                                 }
5801                         },
5802                         keypress: function( event ) {
5803                                 if ( suppressKeyPress ) {
5804                                         suppressKeyPress = false;
5805                                         if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5806                                                 event.preventDefault();
5807                                         }
5808                                         return;
5809                                 }
5810                                 if ( suppressKeyPressRepeat ) {
5811                                         return;
5812                                 }
5814                                 // Replicate some key handlers to allow them to repeat in Firefox and Opera
5815                                 var keyCode = $.ui.keyCode;
5816                                 switch ( event.keyCode ) {
5817                                 case keyCode.PAGE_UP:
5818                                         this._move( "previousPage", event );
5819                                         break;
5820                                 case keyCode.PAGE_DOWN:
5821                                         this._move( "nextPage", event );
5822                                         break;
5823                                 case keyCode.UP:
5824                                         this._keyEvent( "previous", event );
5825                                         break;
5826                                 case keyCode.DOWN:
5827                                         this._keyEvent( "next", event );
5828                                         break;
5829                                 }
5830                         },
5831                         input: function( event ) {
5832                                 if ( suppressInput ) {
5833                                         suppressInput = false;
5834                                         event.preventDefault();
5835                                         return;
5836                                 }
5837                                 this._searchTimeout( event );
5838                         },
5839                         focus: function() {
5840                                 this.selectedItem = null;
5841                                 this.previous = this._value();
5842                         },
5843                         blur: function( event ) {
5844                                 clearTimeout( this.searching );
5845                                 this.close( event );
5846                                 this._change( event );
5847                         }
5848                 } );
5850                 this._initSource();
5851                 this.menu = $( "<ul>" )
5852                         .appendTo( this._appendTo() )
5853                         .menu( {
5855                                 // disable ARIA support, the live region takes care of that
5856                                 role: null
5857                         } )
5858                         .hide()
5860                         // Support: IE 11 only, Edge <= 14
5861                         // For other browsers, we preventDefault() on the mousedown event
5862                         // to keep the dropdown from taking focus from the input. This doesn't
5863                         // work for IE/Edge, causing problems with selection and scrolling (#9638)
5864                         // Happily, IE and Edge support an "unselectable" attribute that
5865                         // prevents an element from receiving focus, exactly what we want here.
5866                         .attr( {
5867                                 "unselectable": "on"
5868                         } )
5869                         .menu( "instance" );
5871                 this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
5872                 this._on( this.menu.element, {
5873                         mousedown: function( event ) {
5875                                 // Prevent moving focus out of the text field
5876                                 event.preventDefault();
5877                         },
5878                         menufocus: function( event, ui ) {
5879                                 var label, item;
5881                                 // support: Firefox
5882                                 // Prevent accidental activation of menu items in Firefox (#7024 #9118)
5883                                 if ( this.isNewMenu ) {
5884                                         this.isNewMenu = false;
5885                                         if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
5886                                                 this.menu.blur();
5888                                                 this.document.one( "mousemove", function() {
5889                                                         $( event.target ).trigger( event.originalEvent );
5890                                                 } );
5892                                                 return;
5893                                         }
5894                                 }
5896                                 item = ui.item.data( "ui-autocomplete-item" );
5897                                 if ( false !== this._trigger( "focus", event, { item: item } ) ) {
5899                                         // use value to match what will end up in the input, if it was a key event
5900                                         if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
5901                                                 this._value( item.value );
5902                                         }
5903                                 }
5905                                 // Announce the value in the liveRegion
5906                                 label = ui.item.attr( "aria-label" ) || item.value;
5907                                 if ( label && String.prototype.trim.call( label ).length ) {
5908                                         this.liveRegion.children().hide();
5909                                         $( "<div>" ).text( label ).appendTo( this.liveRegion );
5910                                 }
5911                         },
5912                         menuselect: function( event, ui ) {
5913                                 var item = ui.item.data( "ui-autocomplete-item" ),
5914                                         previous = this.previous;
5916                                 // Only trigger when focus was lost (click on menu)
5917                                 if ( this.element[ 0 ] !== $.ui.safeActiveElement( this.document[ 0 ] ) ) {
5918                                         this.element.trigger( "focus" );
5919                                         this.previous = previous;
5921                                         // #6109 - IE triggers two focus events and the second
5922                                         // is asynchronous, so we need to reset the previous
5923                                         // term synchronously and asynchronously :-(
5924                                         this._delay( function() {
5925                                                 this.previous = previous;
5926                                                 this.selectedItem = item;
5927                                         } );
5928                                 }
5930                                 if ( false !== this._trigger( "select", event, { item: item } ) ) {
5931                                         this._value( item.value );
5932                                 }
5934                                 // reset the term after the select event
5935                                 // this allows custom select handling to work properly
5936                                 this.term = this._value();
5938                                 this.close( event );
5939                                 this.selectedItem = item;
5940                         }
5941                 } );
5943                 this.liveRegion = $( "<div>", {
5944                         role: "status",
5945                         "aria-live": "assertive",
5946                         "aria-relevant": "additions"
5947                 } )
5948                         .appendTo( this.document[ 0 ].body );
5950                 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
5952                 // Turning off autocomplete prevents the browser from remembering the
5953                 // value when navigating through history, so we re-enable autocomplete
5954                 // if the page is unloaded before the widget is destroyed. #7790
5955                 this._on( this.window, {
5956                         beforeunload: function() {
5957                                 this.element.removeAttr( "autocomplete" );
5958                         }
5959                 } );
5960         },
5962         _destroy: function() {
5963                 clearTimeout( this.searching );
5964                 this.element.removeAttr( "autocomplete" );
5965                 this.menu.element.remove();
5966                 this.liveRegion.remove();
5967         },
5969         _setOption: function( key, value ) {
5970                 this._super( key, value );
5971                 if ( key === "source" ) {
5972                         this._initSource();
5973                 }
5974                 if ( key === "appendTo" ) {
5975                         this.menu.element.appendTo( this._appendTo() );
5976                 }
5977                 if ( key === "disabled" && value && this.xhr ) {
5978                         this.xhr.abort();
5979                 }
5980         },
5982         _isEventTargetInWidget: function( event ) {
5983                 var menuElement = this.menu.element[ 0 ];
5985                 return event.target === this.element[ 0 ] ||
5986                         event.target === menuElement ||
5987                         $.contains( menuElement, event.target );
5988         },
5990         _closeOnClickOutside: function( event ) {
5991                 if ( !this._isEventTargetInWidget( event ) ) {
5992                         this.close();
5993                 }
5994         },
5996         _appendTo: function() {
5997                 var element = this.options.appendTo;
5999                 if ( element ) {
6000                         element = element.jquery || element.nodeType ?
6001                                 $( element ) :
6002                                 this.document.find( element ).eq( 0 );
6003                 }
6005                 if ( !element || !element[ 0 ] ) {
6006                         element = this.element.closest( ".ui-front, dialog" );
6007                 }
6009                 if ( !element.length ) {
6010                         element = this.document[ 0 ].body;
6011                 }
6013                 return element;
6014         },
6016         _initSource: function() {
6017                 var array, url,
6018                         that = this;
6019                 if ( Array.isArray( this.options.source ) ) {
6020                         array = this.options.source;
6021                         this.source = function( request, response ) {
6022                                 response( $.ui.autocomplete.filter( array, request.term ) );
6023                         };
6024                 } else if ( typeof this.options.source === "string" ) {
6025                         url = this.options.source;
6026                         this.source = function( request, response ) {
6027                                 if ( that.xhr ) {
6028                                         that.xhr.abort();
6029                                 }
6030                                 that.xhr = $.ajax( {
6031                                         url: url,
6032                                         data: request,
6033                                         dataType: "json",
6034                                         success: function( data ) {
6035                                                 response( data );
6036                                         },
6037                                         error: function() {
6038                                                 response( [] );
6039                                         }
6040                                 } );
6041                         };
6042                 } else {
6043                         this.source = this.options.source;
6044                 }
6045         },
6047         _searchTimeout: function( event ) {
6048                 clearTimeout( this.searching );
6049                 this.searching = this._delay( function() {
6051                         // Search if the value has changed, or if the user retypes the same value (see #7434)
6052                         var equalValues = this.term === this._value(),
6053                                 menuVisible = this.menu.element.is( ":visible" ),
6054                                 modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
6056                         if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
6057                                 this.selectedItem = null;
6058                                 this.search( null, event );
6059                         }
6060                 }, this.options.delay );
6061         },
6063         search: function( value, event ) {
6064                 value = value != null ? value : this._value();
6066                 // Always save the actual value, not the one passed as an argument
6067                 this.term = this._value();
6069                 if ( value.length < this.options.minLength ) {
6070                         return this.close( event );
6071                 }
6073                 if ( this._trigger( "search", event ) === false ) {
6074                         return;
6075                 }
6077                 return this._search( value );
6078         },
6080         _search: function( value ) {
6081                 this.pending++;
6082                 this._addClass( "ui-autocomplete-loading" );
6083                 this.cancelSearch = false;
6085                 this.source( { term: value }, this._response() );
6086         },
6088         _response: function() {
6089                 var index = ++this.requestIndex;
6091                 return function( content ) {
6092                         if ( index === this.requestIndex ) {
6093                                 this.__response( content );
6094                         }
6096                         this.pending--;
6097                         if ( !this.pending ) {
6098                                 this._removeClass( "ui-autocomplete-loading" );
6099                         }
6100                 }.bind( this );
6101         },
6103         __response: function( content ) {
6104                 if ( content ) {
6105                         content = this._normalize( content );
6106                 }
6107                 this._trigger( "response", null, { content: content } );
6108                 if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
6109                         this._suggest( content );
6110                         this._trigger( "open" );
6111                 } else {
6113                         // use ._close() instead of .close() so we don't cancel future searches
6114                         this._close();
6115                 }
6116         },
6118         close: function( event ) {
6119                 this.cancelSearch = true;
6120                 this._close( event );
6121         },
6123         _close: function( event ) {
6125                 // Remove the handler that closes the menu on outside clicks
6126                 this._off( this.document, "mousedown" );
6128                 if ( this.menu.element.is( ":visible" ) ) {
6129                         this.menu.element.hide();
6130                         this.menu.blur();
6131                         this.isNewMenu = true;
6132                         this._trigger( "close", event );
6133                 }
6134         },
6136         _change: function( event ) {
6137                 if ( this.previous !== this._value() ) {
6138                         this._trigger( "change", event, { item: this.selectedItem } );
6139                 }
6140         },
6142         _normalize: function( items ) {
6144                 // assume all items have the right format when the first item is complete
6145                 if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
6146                         return items;
6147                 }
6148                 return $.map( items, function( item ) {
6149                         if ( typeof item === "string" ) {
6150                                 return {
6151                                         label: item,
6152                                         value: item
6153                                 };
6154                         }
6155                         return $.extend( {}, item, {
6156                                 label: item.label || item.value,
6157                                 value: item.value || item.label
6158                         } );
6159                 } );
6160         },
6162         _suggest: function( items ) {
6163                 var ul = this.menu.element.empty();
6164                 this._renderMenu( ul, items );
6165                 this.isNewMenu = true;
6166                 this.menu.refresh();
6168                 // Size and position menu
6169                 ul.show();
6170                 this._resizeMenu();
6171                 ul.position( $.extend( {
6172                         of: this.element
6173                 }, this.options.position ) );
6175                 if ( this.options.autoFocus ) {
6176                         this.menu.next();
6177                 }
6179                 // Listen for interactions outside of the widget (#6642)
6180                 this._on( this.document, {
6181                         mousedown: "_closeOnClickOutside"
6182                 } );
6183         },
6185         _resizeMenu: function() {
6186                 var ul = this.menu.element;
6187                 ul.outerWidth( Math.max(
6189                         // Firefox wraps long text (possibly a rounding bug)
6190                         // so we add 1px to avoid the wrapping (#7513)
6191                         ul.width( "" ).outerWidth() + 1,
6192                         this.element.outerWidth()
6193                 ) );
6194         },
6196         _renderMenu: function( ul, items ) {
6197                 var that = this;
6198                 $.each( items, function( index, item ) {
6199                         that._renderItemData( ul, item );
6200                 } );
6201         },
6203         _renderItemData: function( ul, item ) {
6204                 return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6205         },
6207         _renderItem: function( ul, item ) {
6208                 return $( "<li>" )
6209                         .append( $( "<div>" ).text( item.label ) )
6210                         .appendTo( ul );
6211         },
6213         _move: function( direction, event ) {
6214                 if ( !this.menu.element.is( ":visible" ) ) {
6215                         this.search( null, event );
6216                         return;
6217                 }
6218                 if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6219                                 this.menu.isLastItem() && /^next/.test( direction ) ) {
6221                         if ( !this.isMultiLine ) {
6222                                 this._value( this.term );
6223                         }
6225                         this.menu.blur();
6226                         return;
6227                 }
6228                 this.menu[ direction ]( event );
6229         },
6231         widget: function() {
6232                 return this.menu.element;
6233         },
6235         _value: function() {
6236                 return this.valueMethod.apply( this.element, arguments );
6237         },
6239         _keyEvent: function( keyEvent, event ) {
6240                 if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6241                         this._move( keyEvent, event );
6243                         // Prevents moving cursor to beginning/end of the text field in some browsers
6244                         event.preventDefault();
6245                 }
6246         },
6248         // Support: Chrome <=50
6249         // We should be able to just use this.element.prop( "isContentEditable" )
6250         // but hidden elements always report false in Chrome.
6251         // https://code.google.com/p/chromium/issues/detail?id=313082
6252         _isContentEditable: function( element ) {
6253                 if ( !element.length ) {
6254                         return false;
6255                 }
6257                 var editable = element.prop( "contentEditable" );
6259                 if ( editable === "inherit" ) {
6260                         return this._isContentEditable( element.parent() );
6261                 }
6263                 return editable === "true";
6264         }
6265 } );
6267 $.extend( $.ui.autocomplete, {
6268         escapeRegex: function( value ) {
6269                 return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
6270         },
6271         filter: function( array, term ) {
6272                 var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
6273                 return $.grep( array, function( value ) {
6274                         return matcher.test( value.label || value.value || value );
6275                 } );
6276         }
6277 } );
6279 // Live region extension, adding a `messages` option
6280 // NOTE: This is an experimental API. We are still investigating
6281 // a full solution for string manipulation and internationalization.
6282 $.widget( "ui.autocomplete", $.ui.autocomplete, {
6283         options: {
6284                 messages: {
6285                         noResults: "No search results.",
6286                         results: function( amount ) {
6287                                 return amount + ( amount > 1 ? " results are" : " result is" ) +
6288                                         " available, use up and down arrow keys to navigate.";
6289                         }
6290                 }
6291         },
6293         __response: function( content ) {
6294                 var message;
6295                 this._superApply( arguments );
6296                 if ( this.options.disabled || this.cancelSearch ) {
6297                         return;
6298                 }
6299                 if ( content && content.length ) {
6300                         message = this.options.messages.results( content.length );
6301                 } else {
6302                         message = this.options.messages.noResults;
6303                 }
6304                 this.liveRegion.children().hide();
6305                 $( "<div>" ).text( message ).appendTo( this.liveRegion );
6306         }
6307 } );
6309 var widgetsAutocomplete = $.ui.autocomplete;
6313  * jQuery UI Controlgroup 1.13.0
6314  * http://jqueryui.com
6316  * Copyright jQuery Foundation and other contributors
6317  * Released under the MIT license.
6318  * http://jquery.org/license
6319  */
6321 //>>label: Controlgroup
6322 //>>group: Widgets
6323 //>>description: Visually groups form control widgets
6324 //>>docs: http://api.jqueryui.com/controlgroup/
6325 //>>demos: http://jqueryui.com/controlgroup/
6326 //>>css.structure: ../../themes/base/core.css
6327 //>>css.structure: ../../themes/base/controlgroup.css
6328 //>>css.theme: ../../themes/base/theme.css
6331 var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
6333 var widgetsControlgroup = $.widget( "ui.controlgroup", {
6334         version: "1.13.0",
6335         defaultElement: "<div>",
6336         options: {
6337                 direction: "horizontal",
6338                 disabled: null,
6339                 onlyVisible: true,
6340                 items: {
6341                         "button": "input[type=button], input[type=submit], input[type=reset], button, a",
6342                         "controlgroupLabel": ".ui-controlgroup-label",
6343                         "checkboxradio": "input[type='checkbox'], input[type='radio']",
6344                         "selectmenu": "select",
6345                         "spinner": ".ui-spinner-input"
6346                 }
6347         },
6349         _create: function() {
6350                 this._enhance();
6351         },
6353         // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
6354         _enhance: function() {
6355                 this.element.attr( "role", "toolbar" );
6356                 this.refresh();
6357         },
6359         _destroy: function() {
6360                 this._callChildMethod( "destroy" );
6361                 this.childWidgets.removeData( "ui-controlgroup-data" );
6362                 this.element.removeAttr( "role" );
6363                 if ( this.options.items.controlgroupLabel ) {
6364                         this.element
6365                                 .find( this.options.items.controlgroupLabel )
6366                                 .find( ".ui-controlgroup-label-contents" )
6367                                 .contents().unwrap();
6368                 }
6369         },
6371         _initWidgets: function() {
6372                 var that = this,
6373                         childWidgets = [];
6375                 // First we iterate over each of the items options
6376                 $.each( this.options.items, function( widget, selector ) {
6377                         var labels;
6378                         var options = {};
6380                         // Make sure the widget has a selector set
6381                         if ( !selector ) {
6382                                 return;
6383                         }
6385                         if ( widget === "controlgroupLabel" ) {
6386                                 labels = that.element.find( selector );
6387                                 labels.each( function() {
6388                                         var element = $( this );
6390                                         if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
6391                                                 return;
6392                                         }
6393                                         element.contents()
6394                                                 .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
6395                                 } );
6396                                 that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
6397                                 childWidgets = childWidgets.concat( labels.get() );
6398                                 return;
6399                         }
6401                         // Make sure the widget actually exists
6402                         if ( !$.fn[ widget ] ) {
6403                                 return;
6404                         }
6406                         // We assume everything is in the middle to start because we can't determine
6407                         // first / last elements until all enhancments are done.
6408                         if ( that[ "_" + widget + "Options" ] ) {
6409                                 options = that[ "_" + widget + "Options" ]( "middle" );
6410                         } else {
6411                                 options = { classes: {} };
6412                         }
6414                         // Find instances of this widget inside controlgroup and init them
6415                         that.element
6416                                 .find( selector )
6417                                 .each( function() {
6418                                         var element = $( this );
6419                                         var instance = element[ widget ]( "instance" );
6421                                         // We need to clone the default options for this type of widget to avoid
6422                                         // polluting the variable options which has a wider scope than a single widget.
6423                                         var instanceOptions = $.widget.extend( {}, options );
6425                                         // If the button is the child of a spinner ignore it
6426                                         // TODO: Find a more generic solution
6427                                         if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
6428                                                 return;
6429                                         }
6431                                         // Create the widget if it doesn't exist
6432                                         if ( !instance ) {
6433                                                 instance = element[ widget ]()[ widget ]( "instance" );
6434                                         }
6435                                         if ( instance ) {
6436                                                 instanceOptions.classes =
6437                                                         that._resolveClassesValues( instanceOptions.classes, instance );
6438                                         }
6439                                         element[ widget ]( instanceOptions );
6441                                         // Store an instance of the controlgroup to be able to reference
6442                                         // from the outermost element for changing options and refresh
6443                                         var widgetElement = element[ widget ]( "widget" );
6444                                         $.data( widgetElement[ 0 ], "ui-controlgroup-data",
6445                                                 instance ? instance : element[ widget ]( "instance" ) );
6447                                         childWidgets.push( widgetElement[ 0 ] );
6448                                 } );
6449                 } );
6451                 this.childWidgets = $( $.uniqueSort( childWidgets ) );
6452                 this._addClass( this.childWidgets, "ui-controlgroup-item" );
6453         },
6455         _callChildMethod: function( method ) {
6456                 this.childWidgets.each( function() {
6457                         var element = $( this ),
6458                                 data = element.data( "ui-controlgroup-data" );
6459                         if ( data && data[ method ] ) {
6460                                 data[ method ]();
6461                         }
6462                 } );
6463         },
6465         _updateCornerClass: function( element, position ) {
6466                 var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
6467                 var add = this._buildSimpleOptions( position, "label" ).classes.label;
6469                 this._removeClass( element, null, remove );
6470                 this._addClass( element, null, add );
6471         },
6473         _buildSimpleOptions: function( position, key ) {
6474                 var direction = this.options.direction === "vertical";
6475                 var result = {
6476                         classes: {}
6477                 };
6478                 result.classes[ key ] = {
6479                         "middle": "",
6480                         "first": "ui-corner-" + ( direction ? "top" : "left" ),
6481                         "last": "ui-corner-" + ( direction ? "bottom" : "right" ),
6482                         "only": "ui-corner-all"
6483                 }[ position ];
6485                 return result;
6486         },
6488         _spinnerOptions: function( position ) {
6489                 var options = this._buildSimpleOptions( position, "ui-spinner" );
6491                 options.classes[ "ui-spinner-up" ] = "";
6492                 options.classes[ "ui-spinner-down" ] = "";
6494                 return options;
6495         },
6497         _buttonOptions: function( position ) {
6498                 return this._buildSimpleOptions( position, "ui-button" );
6499         },
6501         _checkboxradioOptions: function( position ) {
6502                 return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
6503         },
6505         _selectmenuOptions: function( position ) {
6506                 var direction = this.options.direction === "vertical";
6507                 return {
6508                         width: direction ? "auto" : false,
6509                         classes: {
6510                                 middle: {
6511                                         "ui-selectmenu-button-open": "",
6512                                         "ui-selectmenu-button-closed": ""
6513                                 },
6514                                 first: {
6515                                         "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
6516                                         "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
6517                                 },
6518                                 last: {
6519                                         "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
6520                                         "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
6521                                 },
6522                                 only: {
6523                                         "ui-selectmenu-button-open": "ui-corner-top",
6524                                         "ui-selectmenu-button-closed": "ui-corner-all"
6525                                 }
6527                         }[ position ]
6528                 };
6529         },
6531         _resolveClassesValues: function( classes, instance ) {
6532                 var result = {};
6533                 $.each( classes, function( key ) {
6534                         var current = instance.options.classes[ key ] || "";
6535                         current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) );
6536                         result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
6537                 } );
6538                 return result;
6539         },
6541         _setOption: function( key, value ) {
6542                 if ( key === "direction" ) {
6543                         this._removeClass( "ui-controlgroup-" + this.options.direction );
6544                 }
6546                 this._super( key, value );
6547                 if ( key === "disabled" ) {
6548                         this._callChildMethod( value ? "disable" : "enable" );
6549                         return;
6550                 }
6552                 this.refresh();
6553         },
6555         refresh: function() {
6556                 var children,
6557                         that = this;
6559                 this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
6561                 if ( this.options.direction === "horizontal" ) {
6562                         this._addClass( null, "ui-helper-clearfix" );
6563                 }
6564                 this._initWidgets();
6566                 children = this.childWidgets;
6568                 // We filter here because we need to track all childWidgets not just the visible ones
6569                 if ( this.options.onlyVisible ) {
6570                         children = children.filter( ":visible" );
6571                 }
6573                 if ( children.length ) {
6575                         // We do this last because we need to make sure all enhancment is done
6576                         // before determining first and last
6577                         $.each( [ "first", "last" ], function( index, value ) {
6578                                 var instance = children[ value ]().data( "ui-controlgroup-data" );
6580                                 if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
6581                                         var options = that[ "_" + instance.widgetName + "Options" ](
6582                                                 children.length === 1 ? "only" : value
6583                                         );
6584                                         options.classes = that._resolveClassesValues( options.classes, instance );
6585                                         instance.element[ instance.widgetName ]( options );
6586                                 } else {
6587                                         that._updateCornerClass( children[ value ](), value );
6588                                 }
6589                         } );
6591                         // Finally call the refresh method on each of the child widgets.
6592                         this._callChildMethod( "refresh" );
6593                 }
6594         }
6595 } );
6598  * jQuery UI Checkboxradio 1.13.0
6599  * http://jqueryui.com
6601  * Copyright jQuery Foundation and other contributors
6602  * Released under the MIT license.
6603  * http://jquery.org/license
6604  */
6606 //>>label: Checkboxradio
6607 //>>group: Widgets
6608 //>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
6609 //>>docs: http://api.jqueryui.com/checkboxradio/
6610 //>>demos: http://jqueryui.com/checkboxradio/
6611 //>>css.structure: ../../themes/base/core.css
6612 //>>css.structure: ../../themes/base/button.css
6613 //>>css.structure: ../../themes/base/checkboxradio.css
6614 //>>css.theme: ../../themes/base/theme.css
6617 $.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
6618         version: "1.13.0",
6619         options: {
6620                 disabled: null,
6621                 label: null,
6622                 icon: true,
6623                 classes: {
6624                         "ui-checkboxradio-label": "ui-corner-all",
6625                         "ui-checkboxradio-icon": "ui-corner-all"
6626                 }
6627         },
6629         _getCreateOptions: function() {
6630                 var disabled, labels;
6631                 var that = this;
6632                 var options = this._super() || {};
6634                 // We read the type here, because it makes more sense to throw a element type error first,
6635                 // rather then the error for lack of a label. Often if its the wrong type, it
6636                 // won't have a label (e.g. calling on a div, btn, etc)
6637                 this._readType();
6639                 labels = this.element.labels();
6641                 // If there are multiple labels, use the last one
6642                 this.label = $( labels[ labels.length - 1 ] );
6643                 if ( !this.label.length ) {
6644                         $.error( "No label found for checkboxradio widget" );
6645                 }
6647                 this.originalLabel = "";
6649                 // We need to get the label text but this may also need to make sure it does not contain the
6650                 // input itself.
6651                 this.label.contents().not( this.element[ 0 ] ).each( function() {
6653                         // The label contents could be text, html, or a mix. We concat each element to get a
6654                         // string representation of the label, without the input as part of it.
6655                         that.originalLabel += this.nodeType === 3 ? $( this ).text() : this.outerHTML;
6656                 } );
6658                 // Set the label option if we found label text
6659                 if ( this.originalLabel ) {
6660                         options.label = this.originalLabel;
6661                 }
6663                 disabled = this.element[ 0 ].disabled;
6664                 if ( disabled != null ) {
6665                         options.disabled = disabled;
6666                 }
6667                 return options;
6668         },
6670         _create: function() {
6671                 var checked = this.element[ 0 ].checked;
6673                 this._bindFormResetHandler();
6675                 if ( this.options.disabled == null ) {
6676                         this.options.disabled = this.element[ 0 ].disabled;
6677                 }
6679                 this._setOption( "disabled", this.options.disabled );
6680                 this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
6681                 this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
6683                 if ( this.type === "radio" ) {
6684                         this._addClass( this.label, "ui-checkboxradio-radio-label" );
6685                 }
6687                 if ( this.options.label && this.options.label !== this.originalLabel ) {
6688                         this._updateLabel();
6689                 } else if ( this.originalLabel ) {
6690                         this.options.label = this.originalLabel;
6691                 }
6693                 this._enhance();
6695                 if ( checked ) {
6696                         this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
6697                 }
6699                 this._on( {
6700                         change: "_toggleClasses",
6701                         focus: function() {
6702                                 this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
6703                         },
6704                         blur: function() {
6705                                 this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
6706                         }
6707                 } );
6708         },
6710         _readType: function() {
6711                 var nodeName = this.element[ 0 ].nodeName.toLowerCase();
6712                 this.type = this.element[ 0 ].type;
6713                 if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
6714                         $.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
6715                                 " and element.type=" + this.type );
6716                 }
6717         },
6719         // Support jQuery Mobile enhanced option
6720         _enhance: function() {
6721                 this._updateIcon( this.element[ 0 ].checked );
6722         },
6724         widget: function() {
6725                 return this.label;
6726         },
6728         _getRadioGroup: function() {
6729                 var group;
6730                 var name = this.element[ 0 ].name;
6731                 var nameSelector = "input[name='" + $.escapeSelector( name ) + "']";
6733                 if ( !name ) {
6734                         return $( [] );
6735                 }
6737                 if ( this.form.length ) {
6738                         group = $( this.form[ 0 ].elements ).filter( nameSelector );
6739                 } else {
6741                         // Not inside a form, check all inputs that also are not inside a form
6742                         group = $( nameSelector ).filter( function() {
6743                                 return $( this )._form().length === 0;
6744                         } );
6745                 }
6747                 return group.not( this.element );
6748         },
6750         _toggleClasses: function() {
6751                 var checked = this.element[ 0 ].checked;
6752                 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6754                 if ( this.options.icon && this.type === "checkbox" ) {
6755                         this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
6756                                 ._toggleClass( this.icon, null, "ui-icon-blank", !checked );
6757                 }
6759                 if ( this.type === "radio" ) {
6760                         this._getRadioGroup()
6761                                 .each( function() {
6762                                         var instance = $( this ).checkboxradio( "instance" );
6764                                         if ( instance ) {
6765                                                 instance._removeClass( instance.label,
6766                                                         "ui-checkboxradio-checked", "ui-state-active" );
6767                                         }
6768                                 } );
6769                 }
6770         },
6772         _destroy: function() {
6773                 this._unbindFormResetHandler();
6775                 if ( this.icon ) {
6776                         this.icon.remove();
6777                         this.iconSpace.remove();
6778                 }
6779         },
6781         _setOption: function( key, value ) {
6783                 // We don't allow the value to be set to nothing
6784                 if ( key === "label" && !value ) {
6785                         return;
6786                 }
6788                 this._super( key, value );
6790                 if ( key === "disabled" ) {
6791                         this._toggleClass( this.label, null, "ui-state-disabled", value );
6792                         this.element[ 0 ].disabled = value;
6794                         // Don't refresh when setting disabled
6795                         return;
6796                 }
6797                 this.refresh();
6798         },
6800         _updateIcon: function( checked ) {
6801                 var toAdd = "ui-icon ui-icon-background ";
6803                 if ( this.options.icon ) {
6804                         if ( !this.icon ) {
6805                                 this.icon = $( "<span>" );
6806                                 this.iconSpace = $( "<span> </span>" );
6807                                 this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
6808                         }
6810                         if ( this.type === "checkbox" ) {
6811                                 toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
6812                                 this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
6813                         } else {
6814                                 toAdd += "ui-icon-blank";
6815                         }
6816                         this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
6817                         if ( !checked ) {
6818                                 this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
6819                         }
6820                         this.icon.prependTo( this.label ).after( this.iconSpace );
6821                 } else if ( this.icon !== undefined ) {
6822                         this.icon.remove();
6823                         this.iconSpace.remove();
6824                         delete this.icon;
6825                 }
6826         },
6828         _updateLabel: function() {
6830                 // Remove the contents of the label ( minus the icon, icon space, and input )
6831                 var contents = this.label.contents().not( this.element[ 0 ] );
6832                 if ( this.icon ) {
6833                         contents = contents.not( this.icon[ 0 ] );
6834                 }
6835                 if ( this.iconSpace ) {
6836                         contents = contents.not( this.iconSpace[ 0 ] );
6837                 }
6838                 contents.remove();
6840                 this.label.append( this.options.label );
6841         },
6843         refresh: function() {
6844                 var checked = this.element[ 0 ].checked,
6845                         isDisabled = this.element[ 0 ].disabled;
6847                 this._updateIcon( checked );
6848                 this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6849                 if ( this.options.label !== null ) {
6850                         this._updateLabel();
6851                 }
6853                 if ( isDisabled !== this.options.disabled ) {
6854                         this._setOptions( { "disabled": isDisabled } );
6855                 }
6856         }
6858 } ] );
6860 var widgetsCheckboxradio = $.ui.checkboxradio;
6864  * jQuery UI Button 1.13.0
6865  * http://jqueryui.com
6867  * Copyright jQuery Foundation and other contributors
6868  * Released under the MIT license.
6869  * http://jquery.org/license
6870  */
6872 //>>label: Button
6873 //>>group: Widgets
6874 //>>description: Enhances a form with themeable buttons.
6875 //>>docs: http://api.jqueryui.com/button/
6876 //>>demos: http://jqueryui.com/button/
6877 //>>css.structure: ../../themes/base/core.css
6878 //>>css.structure: ../../themes/base/button.css
6879 //>>css.theme: ../../themes/base/theme.css
6882 $.widget( "ui.button", {
6883         version: "1.13.0",
6884         defaultElement: "<button>",
6885         options: {
6886                 classes: {
6887                         "ui-button": "ui-corner-all"
6888                 },
6889                 disabled: null,
6890                 icon: null,
6891                 iconPosition: "beginning",
6892                 label: null,
6893                 showLabel: true
6894         },
6896         _getCreateOptions: function() {
6897                 var disabled,
6899                         // This is to support cases like in jQuery Mobile where the base widget does have
6900                         // an implementation of _getCreateOptions
6901                         options = this._super() || {};
6903                 this.isInput = this.element.is( "input" );
6905                 disabled = this.element[ 0 ].disabled;
6906                 if ( disabled != null ) {
6907                         options.disabled = disabled;
6908                 }
6910                 this.originalLabel = this.isInput ? this.element.val() : this.element.html();
6911                 if ( this.originalLabel ) {
6912                         options.label = this.originalLabel;
6913                 }
6915                 return options;
6916         },
6918         _create: function() {
6919                 if ( !this.option.showLabel & !this.options.icon ) {
6920                         this.options.showLabel = true;
6921                 }
6923                 // We have to check the option again here even though we did in _getCreateOptions,
6924                 // because null may have been passed on init which would override what was set in
6925                 // _getCreateOptions
6926                 if ( this.options.disabled == null ) {
6927                         this.options.disabled = this.element[ 0 ].disabled || false;
6928                 }
6930                 this.hasTitle = !!this.element.attr( "title" );
6932                 // Check to see if the label needs to be set or if its already correct
6933                 if ( this.options.label && this.options.label !== this.originalLabel ) {
6934                         if ( this.isInput ) {
6935                                 this.element.val( this.options.label );
6936                         } else {
6937                                 this.element.html( this.options.label );
6938                         }
6939                 }
6940                 this._addClass( "ui-button", "ui-widget" );
6941                 this._setOption( "disabled", this.options.disabled );
6942                 this._enhance();
6944                 if ( this.element.is( "a" ) ) {
6945                         this._on( {
6946                                 "keyup": function( event ) {
6947                                         if ( event.keyCode === $.ui.keyCode.SPACE ) {
6948                                                 event.preventDefault();
6950                                                 // Support: PhantomJS <= 1.9, IE 8 Only
6951                                                 // If a native click is available use it so we actually cause navigation
6952                                                 // otherwise just trigger a click event
6953                                                 if ( this.element[ 0 ].click ) {
6954                                                         this.element[ 0 ].click();
6955                                                 } else {
6956                                                         this.element.trigger( "click" );
6957                                                 }
6958                                         }
6959                                 }
6960                         } );
6961                 }
6962         },
6964         _enhance: function() {
6965                 if ( !this.element.is( "button" ) ) {
6966                         this.element.attr( "role", "button" );
6967                 }
6969                 if ( this.options.icon ) {
6970                         this._updateIcon( "icon", this.options.icon );
6971                         this._updateTooltip();
6972                 }
6973         },
6975         _updateTooltip: function() {
6976                 this.title = this.element.attr( "title" );
6978                 if ( !this.options.showLabel && !this.title ) {
6979                         this.element.attr( "title", this.options.label );
6980                 }
6981         },
6983         _updateIcon: function( option, value ) {
6984                 var icon = option !== "iconPosition",
6985                         position = icon ? this.options.iconPosition : value,
6986                         displayBlock = position === "top" || position === "bottom";
6988                 // Create icon
6989                 if ( !this.icon ) {
6990                         this.icon = $( "<span>" );
6992                         this._addClass( this.icon, "ui-button-icon", "ui-icon" );
6994                         if ( !this.options.showLabel ) {
6995                                 this._addClass( "ui-button-icon-only" );
6996                         }
6997                 } else if ( icon ) {
6999                         // If we are updating the icon remove the old icon class
7000                         this._removeClass( this.icon, null, this.options.icon );
7001                 }
7003                 // If we are updating the icon add the new icon class
7004                 if ( icon ) {
7005                         this._addClass( this.icon, null, value );
7006                 }
7008                 this._attachIcon( position );
7010                 // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
7011                 // the iconSpace if there is one.
7012                 if ( displayBlock ) {
7013                         this._addClass( this.icon, null, "ui-widget-icon-block" );
7014                         if ( this.iconSpace ) {
7015                                 this.iconSpace.remove();
7016                         }
7017                 } else {
7019                         // Position is beginning or end so remove the ui-widget-icon-block class and add the
7020                         // space if it does not exist
7021                         if ( !this.iconSpace ) {
7022                                 this.iconSpace = $( "<span> </span>" );
7023                                 this._addClass( this.iconSpace, "ui-button-icon-space" );
7024                         }
7025                         this._removeClass( this.icon, null, "ui-wiget-icon-block" );
7026                         this._attachIconSpace( position );
7027                 }
7028         },
7030         _destroy: function() {
7031                 this.element.removeAttr( "role" );
7033                 if ( this.icon ) {
7034                         this.icon.remove();
7035                 }
7036                 if ( this.iconSpace ) {
7037                         this.iconSpace.remove();
7038                 }
7039                 if ( !this.hasTitle ) {
7040                         this.element.removeAttr( "title" );
7041                 }
7042         },
7044         _attachIconSpace: function( iconPosition ) {
7045                 this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
7046         },
7048         _attachIcon: function( iconPosition ) {
7049                 this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
7050         },
7052         _setOptions: function( options ) {
7053                 var newShowLabel = options.showLabel === undefined ?
7054                                 this.options.showLabel :
7055                                 options.showLabel,
7056                         newIcon = options.icon === undefined ? this.options.icon : options.icon;
7058                 if ( !newShowLabel && !newIcon ) {
7059                         options.showLabel = true;
7060                 }
7061                 this._super( options );
7062         },
7064         _setOption: function( key, value ) {
7065                 if ( key === "icon" ) {
7066                         if ( value ) {
7067                                 this._updateIcon( key, value );
7068                         } else if ( this.icon ) {
7069                                 this.icon.remove();
7070                                 if ( this.iconSpace ) {
7071                                         this.iconSpace.remove();
7072                                 }
7073                         }
7074                 }
7076                 if ( key === "iconPosition" ) {
7077                         this._updateIcon( key, value );
7078                 }
7080                 // Make sure we can't end up with a button that has neither text nor icon
7081                 if ( key === "showLabel" ) {
7082                                 this._toggleClass( "ui-button-icon-only", null, !value );
7083                                 this._updateTooltip();
7084                 }
7086                 if ( key === "label" ) {
7087                         if ( this.isInput ) {
7088                                 this.element.val( value );
7089                         } else {
7091                                 // If there is an icon, append it, else nothing then append the value
7092                                 // this avoids removal of the icon when setting label text
7093                                 this.element.html( value );
7094                                 if ( this.icon ) {
7095                                         this._attachIcon( this.options.iconPosition );
7096                                         this._attachIconSpace( this.options.iconPosition );
7097                                 }
7098                         }
7099                 }
7101                 this._super( key, value );
7103                 if ( key === "disabled" ) {
7104                         this._toggleClass( null, "ui-state-disabled", value );
7105                         this.element[ 0 ].disabled = value;
7106                         if ( value ) {
7107                                 this.element.trigger( "blur" );
7108                         }
7109                 }
7110         },
7112         refresh: function() {
7114                 // Make sure to only check disabled if its an element that supports this otherwise
7115                 // check for the disabled class to determine state
7116                 var isDisabled = this.element.is( "input, button" ) ?
7117                         this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
7119                 if ( isDisabled !== this.options.disabled ) {
7120                         this._setOptions( { disabled: isDisabled } );
7121                 }
7123                 this._updateTooltip();
7124         }
7125 } );
7127 // DEPRECATED
7128 if ( $.uiBackCompat !== false ) {
7130         // Text and Icons options
7131         $.widget( "ui.button", $.ui.button, {
7132                 options: {
7133                         text: true,
7134                         icons: {
7135                                 primary: null,
7136                                 secondary: null
7137                         }
7138                 },
7140                 _create: function() {
7141                         if ( this.options.showLabel && !this.options.text ) {
7142                                 this.options.showLabel = this.options.text;
7143                         }
7144                         if ( !this.options.showLabel && this.options.text ) {
7145                                 this.options.text = this.options.showLabel;
7146                         }
7147                         if ( !this.options.icon && ( this.options.icons.primary ||
7148                                         this.options.icons.secondary ) ) {
7149                                 if ( this.options.icons.primary ) {
7150                                         this.options.icon = this.options.icons.primary;
7151                                 } else {
7152                                         this.options.icon = this.options.icons.secondary;
7153                                         this.options.iconPosition = "end";
7154                                 }
7155                         } else if ( this.options.icon ) {
7156                                 this.options.icons.primary = this.options.icon;
7157                         }
7158                         this._super();
7159                 },
7161                 _setOption: function( key, value ) {
7162                         if ( key === "text" ) {
7163                                 this._super( "showLabel", value );
7164                                 return;
7165                         }
7166                         if ( key === "showLabel" ) {
7167                                 this.options.text = value;
7168                         }
7169                         if ( key === "icon" ) {
7170                                 this.options.icons.primary = value;
7171                         }
7172                         if ( key === "icons" ) {
7173                                 if ( value.primary ) {
7174                                         this._super( "icon", value.primary );
7175                                         this._super( "iconPosition", "beginning" );
7176                                 } else if ( value.secondary ) {
7177                                         this._super( "icon", value.secondary );
7178                                         this._super( "iconPosition", "end" );
7179                                 }
7180                         }
7181                         this._superApply( arguments );
7182                 }
7183         } );
7185         $.fn.button = ( function( orig ) {
7186                 return function( options ) {
7187                         var isMethodCall = typeof options === "string";
7188                         var args = Array.prototype.slice.call( arguments, 1 );
7189                         var returnValue = this;
7191                         if ( isMethodCall ) {
7193                                 // If this is an empty collection, we need to have the instance method
7194                                 // return undefined instead of the jQuery instance
7195                                 if ( !this.length && options === "instance" ) {
7196                                         returnValue = undefined;
7197                                 } else {
7198                                         this.each( function() {
7199                                                 var methodValue;
7200                                                 var type = $( this ).attr( "type" );
7201                                                 var name = type !== "checkbox" && type !== "radio" ?
7202                                                         "button" :
7203                                                         "checkboxradio";
7204                                                 var instance = $.data( this, "ui-" + name );
7206                                                 if ( options === "instance" ) {
7207                                                         returnValue = instance;
7208                                                         return false;
7209                                                 }
7211                                                 if ( !instance ) {
7212                                                         return $.error( "cannot call methods on button" +
7213                                                                 " prior to initialization; " +
7214                                                                 "attempted to call method '" + options + "'" );
7215                                                 }
7217                                                 if ( typeof instance[ options ] !== "function" ||
7218                                                         options.charAt( 0 ) === "_" ) {
7219                                                         return $.error( "no such method '" + options + "' for button" +
7220                                                                 " widget instance" );
7221                                                 }
7223                                                 methodValue = instance[ options ].apply( instance, args );
7225                                                 if ( methodValue !== instance && methodValue !== undefined ) {
7226                                                         returnValue = methodValue && methodValue.jquery ?
7227                                                                 returnValue.pushStack( methodValue.get() ) :
7228                                                                 methodValue;
7229                                                         return false;
7230                                                 }
7231                                         } );
7232                                 }
7233                         } else {
7235                                 // Allow multiple hashes to be passed on init
7236                                 if ( args.length ) {
7237                                         options = $.widget.extend.apply( null, [ options ].concat( args ) );
7238                                 }
7240                                 this.each( function() {
7241                                         var type = $( this ).attr( "type" );
7242                                         var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
7243                                         var instance = $.data( this, "ui-" + name );
7245                                         if ( instance ) {
7246                                                 instance.option( options || {} );
7247                                                 if ( instance._init ) {
7248                                                         instance._init();
7249                                                 }
7250                                         } else {
7251                                                 if ( name === "button" ) {
7252                                                         orig.call( $( this ), options );
7253                                                         return;
7254                                                 }
7256                                                 $( this ).checkboxradio( $.extend( { icon: false }, options ) );
7257                                         }
7258                                 } );
7259                         }
7261                         return returnValue;
7262                 };
7263         } )( $.fn.button );
7265         $.fn.buttonset = function() {
7266                 if ( !$.ui.controlgroup ) {
7267                         $.error( "Controlgroup widget missing" );
7268                 }
7269                 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
7270                         return this.controlgroup.apply( this,
7271                                 [ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
7272                 }
7273                 if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
7274                         return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
7275                 }
7276                 if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
7277                         arguments[ 0 ].items = {
7278                                 button: arguments[ 0 ].items
7279                         };
7280                 }
7281                 return this.controlgroup.apply( this, arguments );
7282         };
7285 var widgetsButton = $.ui.button;
7288 /* eslint-disable max-len, camelcase */
7290  * jQuery UI Datepicker 1.13.0
7291  * http://jqueryui.com
7293  * Copyright jQuery Foundation and other contributors
7294  * Released under the MIT license.
7295  * http://jquery.org/license
7296  */
7298 //>>label: Datepicker
7299 //>>group: Widgets
7300 //>>description: Displays a calendar from an input or inline for selecting dates.
7301 //>>docs: http://api.jqueryui.com/datepicker/
7302 //>>demos: http://jqueryui.com/datepicker/
7303 //>>css.structure: ../../themes/base/core.css
7304 //>>css.structure: ../../themes/base/datepicker.css
7305 //>>css.theme: ../../themes/base/theme.css
7308 $.extend( $.ui, { datepicker: { version: "1.13.0" } } );
7310 var datepicker_instActive;
7312 function datepicker_getZindex( elem ) {
7313         var position, value;
7314         while ( elem.length && elem[ 0 ] !== document ) {
7316                 // Ignore z-index if position is set to a value where z-index is ignored by the browser
7317                 // This makes behavior of this function consistent across browsers
7318                 // WebKit always returns auto if the element is positioned
7319                 position = elem.css( "position" );
7320                 if ( position === "absolute" || position === "relative" || position === "fixed" ) {
7322                         // IE returns 0 when zIndex is not specified
7323                         // other browsers return a string
7324                         // we ignore the case of nested elements with an explicit value of 0
7325                         // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
7326                         value = parseInt( elem.css( "zIndex" ), 10 );
7327                         if ( !isNaN( value ) && value !== 0 ) {
7328                                 return value;
7329                         }
7330                 }
7331                 elem = elem.parent();
7332         }
7334         return 0;
7337 /* Date picker manager.
7338    Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7339    Settings for (groups of) date pickers are maintained in an instance object,
7340    allowing multiple different settings on the same page. */
7342 function Datepicker() {
7343         this._curInst = null; // The current instance in use
7344         this._keyEvent = false; // If the last event was a key event
7345         this._disabledInputs = []; // List of date picker inputs that have been disabled
7346         this._datepickerShowing = false; // True if the popup picker is showing , false if not
7347         this._inDialog = false; // True if showing within a "dialog", false if not
7348         this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7349         this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7350         this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7351         this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7352         this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7353         this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7354         this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7355         this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7356         this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7357         this.regional = []; // Available regional settings, indexed by language code
7358         this.regional[ "" ] = { // Default regional settings
7359                 closeText: "Done", // Display text for close link
7360                 prevText: "Prev", // Display text for previous month link
7361                 nextText: "Next", // Display text for next month link
7362                 currentText: "Today", // Display text for current month link
7363                 monthNames: [ "January", "February", "March", "April", "May", "June",
7364                         "July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting
7365                 monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
7366                 dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
7367                 dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
7368                 dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday
7369                 weekHeader: "Wk", // Column header for week of the year
7370                 dateFormat: "mm/dd/yy", // See format options on parseDate
7371                 firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7372                 isRTL: false, // True if right-to-left language, false if left-to-right
7373                 showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7374                 yearSuffix: "", // Additional text to append to the year in the month headers,
7375                 selectMonthLabel: "Select month", // Invisible label for month selector
7376                 selectYearLabel: "Select year" // Invisible label for year selector
7377         };
7378         this._defaults = { // Global defaults for all the date picker instances
7379                 showOn: "focus", // "focus" for popup on focus,
7380                         // "button" for trigger button, or "both" for either
7381                 showAnim: "fadeIn", // Name of jQuery animation for popup
7382                 showOptions: {}, // Options for enhanced animations
7383                 defaultDate: null, // Used when field is blank: actual date,
7384                         // +/-number for offset from today, null for today
7385                 appendText: "", // Display text following the input box, e.g. showing the format
7386                 buttonText: "...", // Text for trigger button
7387                 buttonImage: "", // URL for trigger button image
7388                 buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7389                 hideIfNoPrevNext: false, // True to hide next/previous month links
7390                         // if not applicable, false to just disable them
7391                 navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7392                 gotoCurrent: false, // True if today link goes back to current selection instead
7393                 changeMonth: false, // True if month can be selected directly, false if only prev/next
7394                 changeYear: false, // True if year can be selected directly, false if only prev/next
7395                 yearRange: "c-10:c+10", // Range of years to display in drop-down,
7396                         // either relative to today's year (-nn:+nn), relative to currently displayed year
7397                         // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7398                 showOtherMonths: false, // True to show dates in other months, false to leave blank
7399                 selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7400                 showWeek: false, // True to show week of the year, false to not show it
7401                 calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7402                         // takes a Date and returns the number of the week for it
7403                 shortYearCutoff: "+10", // Short year values < this are in the current century,
7404                         // > this are in the previous century,
7405                         // string value starting with "+" for current year + value
7406                 minDate: null, // The earliest selectable date, or null for no limit
7407                 maxDate: null, // The latest selectable date, or null for no limit
7408                 duration: "fast", // Duration of display/closure
7409                 beforeShowDay: null, // Function that takes a date and returns an array with
7410                         // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7411                         // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7412                 beforeShow: null, // Function that takes an input field and
7413                         // returns a set of custom settings for the date picker
7414                 onSelect: null, // Define a callback function when a date is selected
7415                 onChangeMonthYear: null, // Define a callback function when the month or year is changed
7416                 onClose: null, // Define a callback function when the datepicker is closed
7417                 onUpdateDatepicker: null, // Define a callback function when the datepicker is updated
7418                 numberOfMonths: 1, // Number of months to show at a time
7419                 showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7420                 stepMonths: 1, // Number of months to step back/forward
7421                 stepBigMonths: 12, // Number of months to step back/forward for the big links
7422                 altField: "", // Selector for an alternate field to store selected dates into
7423                 altFormat: "", // The date format to use for the alternate field
7424                 constrainInput: true, // The input is constrained by the current date format
7425                 showButtonPanel: false, // True to show button panel, false to not show it
7426                 autoSize: false, // True to size the input for the date format, false to leave as is
7427                 disabled: false // The initial disabled state
7428         };
7429         $.extend( this._defaults, this.regional[ "" ] );
7430         this.regional.en = $.extend( true, {}, this.regional[ "" ] );
7431         this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
7432         this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
7435 $.extend( Datepicker.prototype, {
7437         /* Class name added to elements to indicate already configured with a date picker. */
7438         markerClassName: "hasDatepicker",
7440         //Keep track of the maximum number of rows displayed (see #7043)
7441         maxRows: 4,
7443         // TODO rename to "widget" when switching to widget factory
7444         _widgetDatepicker: function() {
7445                 return this.dpDiv;
7446         },
7448         /* Override the default settings for all instances of the date picker.
7449          * @param  settings  object - the new settings to use as defaults (anonymous object)
7450          * @return the manager object
7451          */
7452         setDefaults: function( settings ) {
7453                 datepicker_extendRemove( this._defaults, settings || {} );
7454                 return this;
7455         },
7457         /* Attach the date picker to a jQuery selection.
7458          * @param  target       element - the target input field or division or span
7459          * @param  settings  object - the new settings to use for this date picker instance (anonymous)
7460          */
7461         _attachDatepicker: function( target, settings ) {
7462                 var nodeName, inline, inst;
7463                 nodeName = target.nodeName.toLowerCase();
7464                 inline = ( nodeName === "div" || nodeName === "span" );
7465                 if ( !target.id ) {
7466                         this.uuid += 1;
7467                         target.id = "dp" + this.uuid;
7468                 }
7469                 inst = this._newInst( $( target ), inline );
7470                 inst.settings = $.extend( {}, settings || {} );
7471                 if ( nodeName === "input" ) {
7472                         this._connectDatepicker( target, inst );
7473                 } else if ( inline ) {
7474                         this._inlineDatepicker( target, inst );
7475                 }
7476         },
7478         /* Create a new instance object. */
7479         _newInst: function( target, inline ) {
7480                 var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
7481                 return { id: id, input: target, // associated target
7482                         selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7483                         drawMonth: 0, drawYear: 0, // month being drawn
7484                         inline: inline, // is datepicker inline or not
7485                         dpDiv: ( !inline ? this.dpDiv : // presentation div
7486                         datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
7487         },
7489         /* Attach the date picker to an input field. */
7490         _connectDatepicker: function( target, inst ) {
7491                 var input = $( target );
7492                 inst.append = $( [] );
7493                 inst.trigger = $( [] );
7494                 if ( input.hasClass( this.markerClassName ) ) {
7495                         return;
7496                 }
7497                 this._attachments( input, inst );
7498                 input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
7499                         on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
7500                 this._autoSize( inst );
7501                 $.data( target, "datepicker", inst );
7503                 //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7504                 if ( inst.settings.disabled ) {
7505                         this._disableDatepicker( target );
7506                 }
7507         },
7509         /* Make attachments based on settings. */
7510         _attachments: function( input, inst ) {
7511                 var showOn, buttonText, buttonImage,
7512                         appendText = this._get( inst, "appendText" ),
7513                         isRTL = this._get( inst, "isRTL" );
7515                 if ( inst.append ) {
7516                         inst.append.remove();
7517                 }
7518                 if ( appendText ) {
7519                         inst.append = $( "<span>" )
7520                                 .addClass( this._appendClass )
7521                                 .text( appendText );
7522                         input[ isRTL ? "before" : "after" ]( inst.append );
7523                 }
7525                 input.off( "focus", this._showDatepicker );
7527                 if ( inst.trigger ) {
7528                         inst.trigger.remove();
7529                 }
7531                 showOn = this._get( inst, "showOn" );
7532                 if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
7533                         input.on( "focus", this._showDatepicker );
7534                 }
7535                 if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
7536                         buttonText = this._get( inst, "buttonText" );
7537                         buttonImage = this._get( inst, "buttonImage" );
7539                         if ( this._get( inst, "buttonImageOnly" ) ) {
7540                                 inst.trigger = $( "<img>" )
7541                                         .addClass( this._triggerClass )
7542                                         .attr( {
7543                                                 src: buttonImage,
7544                                                 alt: buttonText,
7545                                                 title: buttonText
7546                                         } );
7547                         } else {
7548                                 inst.trigger = $( "<button type='button'>" )
7549                                         .addClass( this._triggerClass );
7550                                 if ( buttonImage ) {
7551                                         inst.trigger.html(
7552                                                 $( "<img>" )
7553                                                         .attr( {
7554                                                                 src: buttonImage,
7555                                                                 alt: buttonText,
7556                                                                 title: buttonText
7557                                                         } )
7558                                         );
7559                                 } else {
7560                                         inst.trigger.text( buttonText );
7561                                 }
7562                         }
7564                         input[ isRTL ? "before" : "after" ]( inst.trigger );
7565                         inst.trigger.on( "click", function() {
7566                                 if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
7567                                         $.datepicker._hideDatepicker();
7568                                 } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
7569                                         $.datepicker._hideDatepicker();
7570                                         $.datepicker._showDatepicker( input[ 0 ] );
7571                                 } else {
7572                                         $.datepicker._showDatepicker( input[ 0 ] );
7573                                 }
7574                                 return false;
7575                         } );
7576                 }
7577         },
7579         /* Apply the maximum length for the date format. */
7580         _autoSize: function( inst ) {
7581                 if ( this._get( inst, "autoSize" ) && !inst.inline ) {
7582                         var findMax, max, maxI, i,
7583                                 date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
7584                                 dateFormat = this._get( inst, "dateFormat" );
7586                         if ( dateFormat.match( /[DM]/ ) ) {
7587                                 findMax = function( names ) {
7588                                         max = 0;
7589                                         maxI = 0;
7590                                         for ( i = 0; i < names.length; i++ ) {
7591                                                 if ( names[ i ].length > max ) {
7592                                                         max = names[ i ].length;
7593                                                         maxI = i;
7594                                                 }
7595                                         }
7596                                         return maxI;
7597                                 };
7598                                 date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
7599                                         "monthNames" : "monthNamesShort" ) ) ) );
7600                                 date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
7601                                         "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
7602                         }
7603                         inst.input.attr( "size", this._formatDate( inst, date ).length );
7604                 }
7605         },
7607         /* Attach an inline date picker to a div. */
7608         _inlineDatepicker: function( target, inst ) {
7609                 var divSpan = $( target );
7610                 if ( divSpan.hasClass( this.markerClassName ) ) {
7611                         return;
7612                 }
7613                 divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
7614                 $.data( target, "datepicker", inst );
7615                 this._setDate( inst, this._getDefaultDate( inst ), true );
7616                 this._updateDatepicker( inst );
7617                 this._updateAlternate( inst );
7619                 //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7620                 if ( inst.settings.disabled ) {
7621                         this._disableDatepicker( target );
7622                 }
7624                 // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7625                 // http://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7626                 inst.dpDiv.css( "display", "block" );
7627         },
7629         /* Pop-up the date picker in a "dialog" box.
7630          * @param  input element - ignored
7631          * @param  date string or Date - the initial date to display
7632          * @param  onSelect  function - the function to call when a date is selected
7633          * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7634          * @param  pos int[2] - coordinates for the dialog's position within the screen or
7635          *                                      event - with x/y coordinates or
7636          *                                      leave empty for default (screen centre)
7637          * @return the manager object
7638          */
7639         _dialogDatepicker: function( input, date, onSelect, settings, pos ) {
7640                 var id, browserWidth, browserHeight, scrollX, scrollY,
7641                         inst = this._dialogInst; // internal instance
7643                 if ( !inst ) {
7644                         this.uuid += 1;
7645                         id = "dp" + this.uuid;
7646                         this._dialogInput = $( "<input type='text' id='" + id +
7647                                 "' style='position: absolute; top: -100px; width: 0px;'/>" );
7648                         this._dialogInput.on( "keydown", this._doKeyDown );
7649                         $( "body" ).append( this._dialogInput );
7650                         inst = this._dialogInst = this._newInst( this._dialogInput, false );
7651                         inst.settings = {};
7652                         $.data( this._dialogInput[ 0 ], "datepicker", inst );
7653                 }
7654                 datepicker_extendRemove( inst.settings, settings || {} );
7655                 date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
7656                 this._dialogInput.val( date );
7658                 this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
7659                 if ( !this._pos ) {
7660                         browserWidth = document.documentElement.clientWidth;
7661                         browserHeight = document.documentElement.clientHeight;
7662                         scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7663                         scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7664                         this._pos = // should use actual width/height below
7665                                 [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
7666                 }
7668                 // Move input on screen for focus, but hidden behind dialog
7669                 this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
7670                 inst.settings.onSelect = onSelect;
7671                 this._inDialog = true;
7672                 this.dpDiv.addClass( this._dialogClass );
7673                 this._showDatepicker( this._dialogInput[ 0 ] );
7674                 if ( $.blockUI ) {
7675                         $.blockUI( this.dpDiv );
7676                 }
7677                 $.data( this._dialogInput[ 0 ], "datepicker", inst );
7678                 return this;
7679         },
7681         /* Detach a datepicker from its control.
7682          * @param  target       element - the target input field or division or span
7683          */
7684         _destroyDatepicker: function( target ) {
7685                 var nodeName,
7686                         $target = $( target ),
7687                         inst = $.data( target, "datepicker" );
7689                 if ( !$target.hasClass( this.markerClassName ) ) {
7690                         return;
7691                 }
7693                 nodeName = target.nodeName.toLowerCase();
7694                 $.removeData( target, "datepicker" );
7695                 if ( nodeName === "input" ) {
7696                         inst.append.remove();
7697                         inst.trigger.remove();
7698                         $target.removeClass( this.markerClassName ).
7699                                 off( "focus", this._showDatepicker ).
7700                                 off( "keydown", this._doKeyDown ).
7701                                 off( "keypress", this._doKeyPress ).
7702                                 off( "keyup", this._doKeyUp );
7703                 } else if ( nodeName === "div" || nodeName === "span" ) {
7704                         $target.removeClass( this.markerClassName ).empty();
7705                 }
7707                 if ( datepicker_instActive === inst ) {
7708                         datepicker_instActive = null;
7709                         this._curInst = null;
7710                 }
7711         },
7713         /* Enable the date picker to a jQuery selection.
7714          * @param  target       element - the target input field or division or span
7715          */
7716         _enableDatepicker: function( target ) {
7717                 var nodeName, inline,
7718                         $target = $( target ),
7719                         inst = $.data( target, "datepicker" );
7721                 if ( !$target.hasClass( this.markerClassName ) ) {
7722                         return;
7723                 }
7725                 nodeName = target.nodeName.toLowerCase();
7726                 if ( nodeName === "input" ) {
7727                         target.disabled = false;
7728                         inst.trigger.filter( "button" ).
7729                                 each( function() {
7730                                         this.disabled = false;
7731                                 } ).end().
7732                                 filter( "img" ).css( { opacity: "1.0", cursor: "" } );
7733                 } else if ( nodeName === "div" || nodeName === "span" ) {
7734                         inline = $target.children( "." + this._inlineClass );
7735                         inline.children().removeClass( "ui-state-disabled" );
7736                         inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7737                                 prop( "disabled", false );
7738                 }
7739                 this._disabledInputs = $.map( this._disabledInputs,
7741                         // Delete entry
7742                         function( value ) {
7743                                 return ( value === target ? null : value );
7744                         } );
7745         },
7747         /* Disable the date picker to a jQuery selection.
7748          * @param  target       element - the target input field or division or span
7749          */
7750         _disableDatepicker: function( target ) {
7751                 var nodeName, inline,
7752                         $target = $( target ),
7753                         inst = $.data( target, "datepicker" );
7755                 if ( !$target.hasClass( this.markerClassName ) ) {
7756                         return;
7757                 }
7759                 nodeName = target.nodeName.toLowerCase();
7760                 if ( nodeName === "input" ) {
7761                         target.disabled = true;
7762                         inst.trigger.filter( "button" ).
7763                                 each( function() {
7764                                         this.disabled = true;
7765                                 } ).end().
7766                                 filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
7767                 } else if ( nodeName === "div" || nodeName === "span" ) {
7768                         inline = $target.children( "." + this._inlineClass );
7769                         inline.children().addClass( "ui-state-disabled" );
7770                         inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7771                                 prop( "disabled", true );
7772                 }
7773                 this._disabledInputs = $.map( this._disabledInputs,
7775                         // Delete entry
7776                         function( value ) {
7777                                 return ( value === target ? null : value );
7778                         } );
7779                 this._disabledInputs[ this._disabledInputs.length ] = target;
7780         },
7782         /* Is the first field in a jQuery collection disabled as a datepicker?
7783          * @param  target       element - the target input field or division or span
7784          * @return boolean - true if disabled, false if enabled
7785          */
7786         _isDisabledDatepicker: function( target ) {
7787                 if ( !target ) {
7788                         return false;
7789                 }
7790                 for ( var i = 0; i < this._disabledInputs.length; i++ ) {
7791                         if ( this._disabledInputs[ i ] === target ) {
7792                                 return true;
7793                         }
7794                 }
7795                 return false;
7796         },
7798         /* Retrieve the instance data for the target control.
7799          * @param  target  element - the target input field or division or span
7800          * @return  object - the associated instance data
7801          * @throws  error if a jQuery problem getting data
7802          */
7803         _getInst: function( target ) {
7804                 try {
7805                         return $.data( target, "datepicker" );
7806                 } catch ( err ) {
7807                         throw "Missing instance data for this datepicker";
7808                 }
7809         },
7811         /* Update or retrieve the settings for a date picker attached to an input field or division.
7812          * @param  target  element - the target input field or division or span
7813          * @param  name object - the new settings to update or
7814          *                              string - the name of the setting to change or retrieve,
7815          *                              when retrieving also "all" for all instance settings or
7816          *                              "defaults" for all global defaults
7817          * @param  value   any - the new value for the setting
7818          *                              (omit if above is an object or to retrieve a value)
7819          */
7820         _optionDatepicker: function( target, name, value ) {
7821                 var settings, date, minDate, maxDate,
7822                         inst = this._getInst( target );
7824                 if ( arguments.length === 2 && typeof name === "string" ) {
7825                         return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
7826                                 ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
7827                                 this._get( inst, name ) ) : null ) );
7828                 }
7830                 settings = name || {};
7831                 if ( typeof name === "string" ) {
7832                         settings = {};
7833                         settings[ name ] = value;
7834                 }
7836                 if ( inst ) {
7837                         if ( this._curInst === inst ) {
7838                                 this._hideDatepicker();
7839                         }
7841                         date = this._getDateDatepicker( target, true );
7842                         minDate = this._getMinMaxDate( inst, "min" );
7843                         maxDate = this._getMinMaxDate( inst, "max" );
7844                         datepicker_extendRemove( inst.settings, settings );
7846                         // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7847                         if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
7848                                 inst.settings.minDate = this._formatDate( inst, minDate );
7849                         }
7850                         if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
7851                                 inst.settings.maxDate = this._formatDate( inst, maxDate );
7852                         }
7853                         if ( "disabled" in settings ) {
7854                                 if ( settings.disabled ) {
7855                                         this._disableDatepicker( target );
7856                                 } else {
7857                                         this._enableDatepicker( target );
7858                                 }
7859                         }
7860                         this._attachments( $( target ), inst );
7861                         this._autoSize( inst );
7862                         this._setDate( inst, date );
7863                         this._updateAlternate( inst );
7864                         this._updateDatepicker( inst );
7865                 }
7866         },
7868         // Change method deprecated
7869         _changeDatepicker: function( target, name, value ) {
7870                 this._optionDatepicker( target, name, value );
7871         },
7873         /* Redraw the date picker attached to an input field or division.
7874          * @param  target  element - the target input field or division or span
7875          */
7876         _refreshDatepicker: function( target ) {
7877                 var inst = this._getInst( target );
7878                 if ( inst ) {
7879                         this._updateDatepicker( inst );
7880                 }
7881         },
7883         /* Set the dates for a jQuery selection.
7884          * @param  target element - the target input field or division or span
7885          * @param  date Date - the new date
7886          */
7887         _setDateDatepicker: function( target, date ) {
7888                 var inst = this._getInst( target );
7889                 if ( inst ) {
7890                         this._setDate( inst, date );
7891                         this._updateDatepicker( inst );
7892                         this._updateAlternate( inst );
7893                 }
7894         },
7896         /* Get the date(s) for the first entry in a jQuery selection.
7897          * @param  target element - the target input field or division or span
7898          * @param  noDefault boolean - true if no default date is to be used
7899          * @return Date - the current date
7900          */
7901         _getDateDatepicker: function( target, noDefault ) {
7902                 var inst = this._getInst( target );
7903                 if ( inst && !inst.inline ) {
7904                         this._setDateFromField( inst, noDefault );
7905                 }
7906                 return ( inst ? this._getDate( inst ) : null );
7907         },
7909         /* Handle keystrokes. */
7910         _doKeyDown: function( event ) {
7911                 var onSelect, dateStr, sel,
7912                         inst = $.datepicker._getInst( event.target ),
7913                         handled = true,
7914                         isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
7916                 inst._keyEvent = true;
7917                 if ( $.datepicker._datepickerShowing ) {
7918                         switch ( event.keyCode ) {
7919                                 case 9: $.datepicker._hideDatepicker();
7920                                                 handled = false;
7921                                                 break; // hide on tab out
7922                                 case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
7923                                                                         $.datepicker._currentClass + ")", inst.dpDiv );
7924                                                 if ( sel[ 0 ] ) {
7925                                                         $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
7926                                                 }
7928                                                 onSelect = $.datepicker._get( inst, "onSelect" );
7929                                                 if ( onSelect ) {
7930                                                         dateStr = $.datepicker._formatDate( inst );
7932                                                         // Trigger custom callback
7933                                                         onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
7934                                                 } else {
7935                                                         $.datepicker._hideDatepicker();
7936                                                 }
7938                                                 return false; // don't submit the form
7939                                 case 27: $.datepicker._hideDatepicker();
7940                                                 break; // hide on escape
7941                                 case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7942                                                         -$.datepicker._get( inst, "stepBigMonths" ) :
7943                                                         -$.datepicker._get( inst, "stepMonths" ) ), "M" );
7944                                                 break; // previous month/year on page up/+ ctrl
7945                                 case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7946                                                         +$.datepicker._get( inst, "stepBigMonths" ) :
7947                                                         +$.datepicker._get( inst, "stepMonths" ) ), "M" );
7948                                                 break; // next month/year on page down/+ ctrl
7949                                 case 35: if ( event.ctrlKey || event.metaKey ) {
7950                                                         $.datepicker._clearDate( event.target );
7951                                                 }
7952                                                 handled = event.ctrlKey || event.metaKey;
7953                                                 break; // clear on ctrl or command +end
7954                                 case 36: if ( event.ctrlKey || event.metaKey ) {
7955                                                         $.datepicker._gotoToday( event.target );
7956                                                 }
7957                                                 handled = event.ctrlKey || event.metaKey;
7958                                                 break; // current on ctrl or command +home
7959                                 case 37: if ( event.ctrlKey || event.metaKey ) {
7960                                                         $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
7961                                                 }
7962                                                 handled = event.ctrlKey || event.metaKey;
7964                                                 // -1 day on ctrl or command +left
7965                                                 if ( event.originalEvent.altKey ) {
7966                                                         $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7967                                                                 -$.datepicker._get( inst, "stepBigMonths" ) :
7968                                                                 -$.datepicker._get( inst, "stepMonths" ) ), "M" );
7969                                                 }
7971                                                 // next month/year on alt +left on Mac
7972                                                 break;
7973                                 case 38: if ( event.ctrlKey || event.metaKey ) {
7974                                                         $.datepicker._adjustDate( event.target, -7, "D" );
7975                                                 }
7976                                                 handled = event.ctrlKey || event.metaKey;
7977                                                 break; // -1 week on ctrl or command +up
7978                                 case 39: if ( event.ctrlKey || event.metaKey ) {
7979                                                         $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
7980                                                 }
7981                                                 handled = event.ctrlKey || event.metaKey;
7983                                                 // +1 day on ctrl or command +right
7984                                                 if ( event.originalEvent.altKey ) {
7985                                                         $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7986                                                                 +$.datepicker._get( inst, "stepBigMonths" ) :
7987                                                                 +$.datepicker._get( inst, "stepMonths" ) ), "M" );
7988                                                 }
7990                                                 // next month/year on alt +right
7991                                                 break;
7992                                 case 40: if ( event.ctrlKey || event.metaKey ) {
7993                                                         $.datepicker._adjustDate( event.target, +7, "D" );
7994                                                 }
7995                                                 handled = event.ctrlKey || event.metaKey;
7996                                                 break; // +1 week on ctrl or command +down
7997                                 default: handled = false;
7998                         }
7999                 } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
8000                         $.datepicker._showDatepicker( this );
8001                 } else {
8002                         handled = false;
8003                 }
8005                 if ( handled ) {
8006                         event.preventDefault();
8007                         event.stopPropagation();
8008                 }
8009         },
8011         /* Filter entered characters - based on date format. */
8012         _doKeyPress: function( event ) {
8013                 var chars, chr,
8014                         inst = $.datepicker._getInst( event.target );
8016                 if ( $.datepicker._get( inst, "constrainInput" ) ) {
8017                         chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
8018                         chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
8019                         return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
8020                 }
8021         },
8023         /* Synchronise manual entry and field/alternate field. */
8024         _doKeyUp: function( event ) {
8025                 var date,
8026                         inst = $.datepicker._getInst( event.target );
8028                 if ( inst.input.val() !== inst.lastVal ) {
8029                         try {
8030                                 date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8031                                         ( inst.input ? inst.input.val() : null ),
8032                                         $.datepicker._getFormatConfig( inst ) );
8034                                 if ( date ) { // only if valid
8035                                         $.datepicker._setDateFromField( inst );
8036                                         $.datepicker._updateAlternate( inst );
8037                                         $.datepicker._updateDatepicker( inst );
8038                                 }
8039                         } catch ( err ) {
8040                         }
8041                 }
8042                 return true;
8043         },
8045         /* Pop-up the date picker for a given input field.
8046          * If false returned from beforeShow event handler do not show.
8047          * @param  input  element - the input field attached to the date picker or
8048          *                                      event - if triggered by focus
8049          */
8050         _showDatepicker: function( input ) {
8051                 input = input.target || input;
8052                 if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
8053                         input = $( "input", input.parentNode )[ 0 ];
8054                 }
8056                 if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
8057                         return;
8058                 }
8060                 var inst, beforeShow, beforeShowSettings, isFixed,
8061                         offset, showAnim, duration;
8063                 inst = $.datepicker._getInst( input );
8064                 if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
8065                         $.datepicker._curInst.dpDiv.stop( true, true );
8066                         if ( inst && $.datepicker._datepickerShowing ) {
8067                                 $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
8068                         }
8069                 }
8071                 beforeShow = $.datepicker._get( inst, "beforeShow" );
8072                 beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
8073                 if ( beforeShowSettings === false ) {
8074                         return;
8075                 }
8076                 datepicker_extendRemove( inst.settings, beforeShowSettings );
8078                 inst.lastVal = null;
8079                 $.datepicker._lastInput = input;
8080                 $.datepicker._setDateFromField( inst );
8082                 if ( $.datepicker._inDialog ) { // hide cursor
8083                         input.value = "";
8084                 }
8085                 if ( !$.datepicker._pos ) { // position below input
8086                         $.datepicker._pos = $.datepicker._findPos( input );
8087                         $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
8088                 }
8090                 isFixed = false;
8091                 $( input ).parents().each( function() {
8092                         isFixed |= $( this ).css( "position" ) === "fixed";
8093                         return !isFixed;
8094                 } );
8096                 offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
8097                 $.datepicker._pos = null;
8099                 //to avoid flashes on Firefox
8100                 inst.dpDiv.empty();
8102                 // determine sizing offscreen
8103                 inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
8104                 $.datepicker._updateDatepicker( inst );
8106                 // fix width for dynamic number of date pickers
8107                 // and adjust position before showing
8108                 offset = $.datepicker._checkOffset( inst, offset, isFixed );
8109                 inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
8110                         "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
8111                         left: offset.left + "px", top: offset.top + "px" } );
8113                 if ( !inst.inline ) {
8114                         showAnim = $.datepicker._get( inst, "showAnim" );
8115                         duration = $.datepicker._get( inst, "duration" );
8116                         inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
8117                         $.datepicker._datepickerShowing = true;
8119                         if ( $.effects && $.effects.effect[ showAnim ] ) {
8120                                 inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
8121                         } else {
8122                                 inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
8123                         }
8125                         if ( $.datepicker._shouldFocusInput( inst ) ) {
8126                                 inst.input.trigger( "focus" );
8127                         }
8129                         $.datepicker._curInst = inst;
8130                 }
8131         },
8133         /* Generate the date picker content. */
8134         _updateDatepicker: function( inst ) {
8135                 this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
8136                 datepicker_instActive = inst; // for delegate hover events
8137                 inst.dpDiv.empty().append( this._generateHTML( inst ) );
8138                 this._attachHandlers( inst );
8140                 var origyearshtml,
8141                         numMonths = this._getNumberOfMonths( inst ),
8142                         cols = numMonths[ 1 ],
8143                         width = 17,
8144                         activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
8145                         onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
8147                 if ( activeCell.length > 0 ) {
8148                         datepicker_handleMouseover.apply( activeCell.get( 0 ) );
8149                 }
8151                 inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
8152                 if ( cols > 1 ) {
8153                         inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
8154                 }
8155                 inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
8156                         "Class" ]( "ui-datepicker-multi" );
8157                 inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
8158                         "Class" ]( "ui-datepicker-rtl" );
8160                 if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
8161                         inst.input.trigger( "focus" );
8162                 }
8164                 // Deffered render of the years select (to avoid flashes on Firefox)
8165                 if ( inst.yearshtml ) {
8166                         origyearshtml = inst.yearshtml;
8167                         setTimeout( function() {
8169                                 //assure that inst.yearshtml didn't change.
8170                                 if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
8171                                         inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
8172                                 }
8173                                 origyearshtml = inst.yearshtml = null;
8174                         }, 0 );
8175                 }
8177                 if ( onUpdateDatepicker ) {
8178                         onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
8179                 }
8180         },
8182         // #6694 - don't focus the input if it's already focused
8183         // this breaks the change event in IE
8184         // Support: IE and jQuery <1.9
8185         _shouldFocusInput: function( inst ) {
8186                 return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" ) && !inst.input.is( ":focus" );
8187         },
8189         /* Check positioning to remain on screen. */
8190         _checkOffset: function( inst, offset, isFixed ) {
8191                 var dpWidth = inst.dpDiv.outerWidth(),
8192                         dpHeight = inst.dpDiv.outerHeight(),
8193                         inputWidth = inst.input ? inst.input.outerWidth() : 0,
8194                         inputHeight = inst.input ? inst.input.outerHeight() : 0,
8195                         viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
8196                         viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
8198                 offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
8199                 offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
8200                 offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
8202                 // Now check if datepicker is showing outside window viewport - move to a better place if so.
8203                 offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
8204                         Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
8205                 offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
8206                         Math.abs( dpHeight + inputHeight ) : 0 );
8208                 return offset;
8209         },
8211         /* Find an object's position on the screen. */
8212         _findPos: function( obj ) {
8213                 var position,
8214                         inst = this._getInst( obj ),
8215                         isRTL = this._get( inst, "isRTL" );
8217                 while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
8218                         obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
8219                 }
8221                 position = $( obj ).offset();
8222                 return [ position.left, position.top ];
8223         },
8225         /* Hide the date picker from view.
8226          * @param  input  element - the input field attached to the date picker
8227          */
8228         _hideDatepicker: function( input ) {
8229                 var showAnim, duration, postProcess, onClose,
8230                         inst = this._curInst;
8232                 if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
8233                         return;
8234                 }
8236                 if ( this._datepickerShowing ) {
8237                         showAnim = this._get( inst, "showAnim" );
8238                         duration = this._get( inst, "duration" );
8239                         postProcess = function() {
8240                                 $.datepicker._tidyDialog( inst );
8241                         };
8243                         // DEPRECATED: after BC for 1.8.x $.effects[ showAnim ] is not needed
8244                         if ( $.effects && ( $.effects.effect[ showAnim ] || $.effects[ showAnim ] ) ) {
8245                                 inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
8246                         } else {
8247                                 inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
8248                                         ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
8249                         }
8251                         if ( !showAnim ) {
8252                                 postProcess();
8253                         }
8254                         this._datepickerShowing = false;
8256                         onClose = this._get( inst, "onClose" );
8257                         if ( onClose ) {
8258                                 onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
8259                         }
8261                         this._lastInput = null;
8262                         if ( this._inDialog ) {
8263                                 this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
8264                                 if ( $.blockUI ) {
8265                                         $.unblockUI();
8266                                         $( "body" ).append( this.dpDiv );
8267                                 }
8268                         }
8269                         this._inDialog = false;
8270                 }
8271         },
8273         /* Tidy up after a dialog display. */
8274         _tidyDialog: function( inst ) {
8275                 inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
8276         },
8278         /* Close date picker if clicked elsewhere. */
8279         _checkExternalClick: function( event ) {
8280                 if ( !$.datepicker._curInst ) {
8281                         return;
8282                 }
8284                 var $target = $( event.target ),
8285                         inst = $.datepicker._getInst( $target[ 0 ] );
8287                 if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
8288                                 $target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
8289                                 !$target.hasClass( $.datepicker.markerClassName ) &&
8290                                 !$target.closest( "." + $.datepicker._triggerClass ).length &&
8291                                 $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
8292                         ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
8293                                 $.datepicker._hideDatepicker();
8294                 }
8295         },
8297         /* Adjust one of the date sub-fields. */
8298         _adjustDate: function( id, offset, period ) {
8299                 var target = $( id ),
8300                         inst = this._getInst( target[ 0 ] );
8302                 if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
8303                         return;
8304                 }
8305                 this._adjustInstDate( inst, offset, period );
8306                 this._updateDatepicker( inst );
8307         },
8309         /* Action for current link. */
8310         _gotoToday: function( id ) {
8311                 var date,
8312                         target = $( id ),
8313                         inst = this._getInst( target[ 0 ] );
8315                 if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
8316                         inst.selectedDay = inst.currentDay;
8317                         inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8318                         inst.drawYear = inst.selectedYear = inst.currentYear;
8319                 } else {
8320                         date = new Date();
8321                         inst.selectedDay = date.getDate();
8322                         inst.drawMonth = inst.selectedMonth = date.getMonth();
8323                         inst.drawYear = inst.selectedYear = date.getFullYear();
8324                 }
8325                 this._notifyChange( inst );
8326                 this._adjustDate( target );
8327         },
8329         /* Action for selecting a new month/year. */
8330         _selectMonthYear: function( id, select, period ) {
8331                 var target = $( id ),
8332                         inst = this._getInst( target[ 0 ] );
8334                 inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
8335                 inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
8336                         parseInt( select.options[ select.selectedIndex ].value, 10 );
8338                 this._notifyChange( inst );
8339                 this._adjustDate( target );
8340         },
8342         /* Action for selecting a day. */
8343         _selectDay: function( id, month, year, td ) {
8344                 var inst,
8345                         target = $( id );
8347                 if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
8348                         return;
8349                 }
8351                 inst = this._getInst( target[ 0 ] );
8352                 inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
8353                 inst.selectedMonth = inst.currentMonth = month;
8354                 inst.selectedYear = inst.currentYear = year;
8355                 this._selectDate( id, this._formatDate( inst,
8356                         inst.currentDay, inst.currentMonth, inst.currentYear ) );
8357         },
8359         /* Erase the input field and hide the date picker. */
8360         _clearDate: function( id ) {
8361                 var target = $( id );
8362                 this._selectDate( target, "" );
8363         },
8365         /* Update the input field with the selected date. */
8366         _selectDate: function( id, dateStr ) {
8367                 var onSelect,
8368                         target = $( id ),
8369                         inst = this._getInst( target[ 0 ] );
8371                 dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
8372                 if ( inst.input ) {
8373                         inst.input.val( dateStr );
8374                 }
8375                 this._updateAlternate( inst );
8377                 onSelect = this._get( inst, "onSelect" );
8378                 if ( onSelect ) {
8379                         onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
8380                 } else if ( inst.input ) {
8381                         inst.input.trigger( "change" ); // fire the change event
8382                 }
8384                 if ( inst.inline ) {
8385                         this._updateDatepicker( inst );
8386                 } else {
8387                         this._hideDatepicker();
8388                         this._lastInput = inst.input[ 0 ];
8389                         if ( typeof( inst.input[ 0 ] ) !== "object" ) {
8390                                 inst.input.trigger( "focus" ); // restore focus
8391                         }
8392                         this._lastInput = null;
8393                 }
8394         },
8396         /* Update any alternate field to synchronise with the main field. */
8397         _updateAlternate: function( inst ) {
8398                 var altFormat, date, dateStr,
8399                         altField = this._get( inst, "altField" );
8401                 if ( altField ) { // update alternate field too
8402                         altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
8403                         date = this._getDate( inst );
8404                         dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
8405                         $( document ).find( altField ).val( dateStr );
8406                 }
8407         },
8409         /* Set as beforeShowDay function to prevent selection of weekends.
8410          * @param  date  Date - the date to customise
8411          * @return [boolean, string] - is this date selectable?, what is its CSS class?
8412          */
8413         noWeekends: function( date ) {
8414                 var day = date.getDay();
8415                 return [ ( day > 0 && day < 6 ), "" ];
8416         },
8418         /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8419          * @param  date  Date - the date to get the week for
8420          * @return  number - the number of the week within the year that contains this date
8421          */
8422         iso8601Week: function( date ) {
8423                 var time,
8424                         checkDate = new Date( date.getTime() );
8426                 // Find Thursday of this week starting on Monday
8427                 checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
8429                 time = checkDate.getTime();
8430                 checkDate.setMonth( 0 ); // Compare with Jan 1
8431                 checkDate.setDate( 1 );
8432                 return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
8433         },
8435         /* Parse a string value into a date object.
8436          * See formatDate below for the possible formats.
8437          *
8438          * @param  format string - the expected format of the date
8439          * @param  value string - the date in the above format
8440          * @param  settings Object - attributes include:
8441          *                                      shortYearCutoff  number - the cutoff year for determining the century (optional)
8442          *                                      dayNamesShort   string[7] - abbreviated names of the days from Sunday (optional)
8443          *                                      dayNames                string[7] - names of the days from Sunday (optional)
8444          *                                      monthNamesShort string[12] - abbreviated names of the months (optional)
8445          *                                      monthNames              string[12] - names of the months (optional)
8446          * @return  Date - the extracted date value or null if value is blank
8447          */
8448         parseDate: function( format, value, settings ) {
8449                 if ( format == null || value == null ) {
8450                         throw "Invalid arguments";
8451                 }
8453                 value = ( typeof value === "object" ? value.toString() : value + "" );
8454                 if ( value === "" ) {
8455                         return null;
8456                 }
8458                 var iFormat, dim, extra,
8459                         iValue = 0,
8460                         shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
8461                         shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8462                                 new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
8463                         dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8464                         dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8465                         monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8466                         monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8467                         year = -1,
8468                         month = -1,
8469                         day = -1,
8470                         doy = -1,
8471                         literal = false,
8472                         date,
8474                         // Check whether a format character is doubled
8475                         lookAhead = function( match ) {
8476                                 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8477                                 if ( matches ) {
8478                                         iFormat++;
8479                                 }
8480                                 return matches;
8481                         },
8483                         // Extract a number from the string value
8484                         getNumber = function( match ) {
8485                                 var isDoubled = lookAhead( match ),
8486                                         size = ( match === "@" ? 14 : ( match === "!" ? 20 :
8487                                         ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
8488                                         minSize = ( match === "y" ? size : 1 ),
8489                                         digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
8490                                         num = value.substring( iValue ).match( digits );
8491                                 if ( !num ) {
8492                                         throw "Missing number at position " + iValue;
8493                                 }
8494                                 iValue += num[ 0 ].length;
8495                                 return parseInt( num[ 0 ], 10 );
8496                         },
8498                         // Extract a name from the string value and convert to an index
8499                         getName = function( match, shortNames, longNames ) {
8500                                 var index = -1,
8501                                         names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
8502                                                 return [ [ k, v ] ];
8503                                         } ).sort( function( a, b ) {
8504                                                 return -( a[ 1 ].length - b[ 1 ].length );
8505                                         } );
8507                                 $.each( names, function( i, pair ) {
8508                                         var name = pair[ 1 ];
8509                                         if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
8510                                                 index = pair[ 0 ];
8511                                                 iValue += name.length;
8512                                                 return false;
8513                                         }
8514                                 } );
8515                                 if ( index !== -1 ) {
8516                                         return index + 1;
8517                                 } else {
8518                                         throw "Unknown name at position " + iValue;
8519                                 }
8520                         },
8522                         // Confirm that a literal character matches the string value
8523                         checkLiteral = function() {
8524                                 if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
8525                                         throw "Unexpected literal at position " + iValue;
8526                                 }
8527                                 iValue++;
8528                         };
8530                 for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8531                         if ( literal ) {
8532                                 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8533                                         literal = false;
8534                                 } else {
8535                                         checkLiteral();
8536                                 }
8537                         } else {
8538                                 switch ( format.charAt( iFormat ) ) {
8539                                         case "d":
8540                                                 day = getNumber( "d" );
8541                                                 break;
8542                                         case "D":
8543                                                 getName( "D", dayNamesShort, dayNames );
8544                                                 break;
8545                                         case "o":
8546                                                 doy = getNumber( "o" );
8547                                                 break;
8548                                         case "m":
8549                                                 month = getNumber( "m" );
8550                                                 break;
8551                                         case "M":
8552                                                 month = getName( "M", monthNamesShort, monthNames );
8553                                                 break;
8554                                         case "y":
8555                                                 year = getNumber( "y" );
8556                                                 break;
8557                                         case "@":
8558                                                 date = new Date( getNumber( "@" ) );
8559                                                 year = date.getFullYear();
8560                                                 month = date.getMonth() + 1;
8561                                                 day = date.getDate();
8562                                                 break;
8563                                         case "!":
8564                                                 date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
8565                                                 year = date.getFullYear();
8566                                                 month = date.getMonth() + 1;
8567                                                 day = date.getDate();
8568                                                 break;
8569                                         case "'":
8570                                                 if ( lookAhead( "'" ) ) {
8571                                                         checkLiteral();
8572                                                 } else {
8573                                                         literal = true;
8574                                                 }
8575                                                 break;
8576                                         default:
8577                                                 checkLiteral();
8578                                 }
8579                         }
8580                 }
8582                 if ( iValue < value.length ) {
8583                         extra = value.substr( iValue );
8584                         if ( !/^\s+/.test( extra ) ) {
8585                                 throw "Extra/unparsed characters found in date: " + extra;
8586                         }
8587                 }
8589                 if ( year === -1 ) {
8590                         year = new Date().getFullYear();
8591                 } else if ( year < 100 ) {
8592                         year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8593                                 ( year <= shortYearCutoff ? 0 : -100 );
8594                 }
8596                 if ( doy > -1 ) {
8597                         month = 1;
8598                         day = doy;
8599                         do {
8600                                 dim = this._getDaysInMonth( year, month - 1 );
8601                                 if ( day <= dim ) {
8602                                         break;
8603                                 }
8604                                 month++;
8605                                 day -= dim;
8606                         } while ( true );
8607                 }
8609                 date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
8610                 if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
8611                         throw "Invalid date"; // E.g. 31/02/00
8612                 }
8613                 return date;
8614         },
8616         /* Standard date formats. */
8617         ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8618         COOKIE: "D, dd M yy",
8619         ISO_8601: "yy-mm-dd",
8620         RFC_822: "D, d M y",
8621         RFC_850: "DD, dd-M-y",
8622         RFC_1036: "D, d M y",
8623         RFC_1123: "D, d M yy",
8624         RFC_2822: "D, d M yy",
8625         RSS: "D, d M y", // RFC 822
8626         TICKS: "!",
8627         TIMESTAMP: "@",
8628         W3C: "yy-mm-dd", // ISO 8601
8630         _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
8631                 Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
8633         /* Format a date object into a string value.
8634          * The format can be combinations of the following:
8635          * d  - day of month (no leading zero)
8636          * dd - day of month (two digit)
8637          * o  - day of year (no leading zeros)
8638          * oo - day of year (three digit)
8639          * D  - day name short
8640          * DD - day name long
8641          * m  - month of year (no leading zero)
8642          * mm - month of year (two digit)
8643          * M  - month name short
8644          * MM - month name long
8645          * y  - year (two digit)
8646          * yy - year (four digit)
8647          * @ - Unix timestamp (ms since 01/01/1970)
8648          * ! - Windows ticks (100ns since 01/01/0001)
8649          * "..." - literal text
8650          * '' - single quote
8651          *
8652          * @param  format string - the desired format of the date
8653          * @param  date Date - the date value to format
8654          * @param  settings Object - attributes include:
8655          *                                      dayNamesShort   string[7] - abbreviated names of the days from Sunday (optional)
8656          *                                      dayNames                string[7] - names of the days from Sunday (optional)
8657          *                                      monthNamesShort string[12] - abbreviated names of the months (optional)
8658          *                                      monthNames              string[12] - names of the months (optional)
8659          * @return  string - the date in the above format
8660          */
8661         formatDate: function( format, date, settings ) {
8662                 if ( !date ) {
8663                         return "";
8664                 }
8666                 var iFormat,
8667                         dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8668                         dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8669                         monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8670                         monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8672                         // Check whether a format character is doubled
8673                         lookAhead = function( match ) {
8674                                 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8675                                 if ( matches ) {
8676                                         iFormat++;
8677                                 }
8678                                 return matches;
8679                         },
8681                         // Format a number, with leading zero if necessary
8682                         formatNumber = function( match, value, len ) {
8683                                 var num = "" + value;
8684                                 if ( lookAhead( match ) ) {
8685                                         while ( num.length < len ) {
8686                                                 num = "0" + num;
8687                                         }
8688                                 }
8689                                 return num;
8690                         },
8692                         // Format a name, short or long as requested
8693                         formatName = function( match, value, shortNames, longNames ) {
8694                                 return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
8695                         },
8696                         output = "",
8697                         literal = false;
8699                 if ( date ) {
8700                         for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8701                                 if ( literal ) {
8702                                         if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8703                                                 literal = false;
8704                                         } else {
8705                                                 output += format.charAt( iFormat );
8706                                         }
8707                                 } else {
8708                                         switch ( format.charAt( iFormat ) ) {
8709                                                 case "d":
8710                                                         output += formatNumber( "d", date.getDate(), 2 );
8711                                                         break;
8712                                                 case "D":
8713                                                         output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
8714                                                         break;
8715                                                 case "o":
8716                                                         output += formatNumber( "o",
8717                                                                 Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
8718                                                         break;
8719                                                 case "m":
8720                                                         output += formatNumber( "m", date.getMonth() + 1, 2 );
8721                                                         break;
8722                                                 case "M":
8723                                                         output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
8724                                                         break;
8725                                                 case "y":
8726                                                         output += ( lookAhead( "y" ) ? date.getFullYear() :
8727                                                                 ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
8728                                                         break;
8729                                                 case "@":
8730                                                         output += date.getTime();
8731                                                         break;
8732                                                 case "!":
8733                                                         output += date.getTime() * 10000 + this._ticksTo1970;
8734                                                         break;
8735                                                 case "'":
8736                                                         if ( lookAhead( "'" ) ) {
8737                                                                 output += "'";
8738                                                         } else {
8739                                                                 literal = true;
8740                                                         }
8741                                                         break;
8742                                                 default:
8743                                                         output += format.charAt( iFormat );
8744                                         }
8745                                 }
8746                         }
8747                 }
8748                 return output;
8749         },
8751         /* Extract all possible characters from the date format. */
8752         _possibleChars: function( format ) {
8753                 var iFormat,
8754                         chars = "",
8755                         literal = false,
8757                         // Check whether a format character is doubled
8758                         lookAhead = function( match ) {
8759                                 var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8760                                 if ( matches ) {
8761                                         iFormat++;
8762                                 }
8763                                 return matches;
8764                         };
8766                 for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8767                         if ( literal ) {
8768                                 if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8769                                         literal = false;
8770                                 } else {
8771                                         chars += format.charAt( iFormat );
8772                                 }
8773                         } else {
8774                                 switch ( format.charAt( iFormat ) ) {
8775                                         case "d": case "m": case "y": case "@":
8776                                                 chars += "0123456789";
8777                                                 break;
8778                                         case "D": case "M":
8779                                                 return null; // Accept anything
8780                                         case "'":
8781                                                 if ( lookAhead( "'" ) ) {
8782                                                         chars += "'";
8783                                                 } else {
8784                                                         literal = true;
8785                                                 }
8786                                                 break;
8787                                         default:
8788                                                 chars += format.charAt( iFormat );
8789                                 }
8790                         }
8791                 }
8792                 return chars;
8793         },
8795         /* Get a setting value, defaulting if necessary. */
8796         _get: function( inst, name ) {
8797                 return inst.settings[ name ] !== undefined ?
8798                         inst.settings[ name ] : this._defaults[ name ];
8799         },
8801         /* Parse existing date and initialise date picker. */
8802         _setDateFromField: function( inst, noDefault ) {
8803                 if ( inst.input.val() === inst.lastVal ) {
8804                         return;
8805                 }
8807                 var dateFormat = this._get( inst, "dateFormat" ),
8808                         dates = inst.lastVal = inst.input ? inst.input.val() : null,
8809                         defaultDate = this._getDefaultDate( inst ),
8810                         date = defaultDate,
8811                         settings = this._getFormatConfig( inst );
8813                 try {
8814                         date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
8815                 } catch ( event ) {
8816                         dates = ( noDefault ? "" : dates );
8817                 }
8818                 inst.selectedDay = date.getDate();
8819                 inst.drawMonth = inst.selectedMonth = date.getMonth();
8820                 inst.drawYear = inst.selectedYear = date.getFullYear();
8821                 inst.currentDay = ( dates ? date.getDate() : 0 );
8822                 inst.currentMonth = ( dates ? date.getMonth() : 0 );
8823                 inst.currentYear = ( dates ? date.getFullYear() : 0 );
8824                 this._adjustInstDate( inst );
8825         },
8827         /* Retrieve the default date shown on opening. */
8828         _getDefaultDate: function( inst ) {
8829                 return this._restrictMinMax( inst,
8830                         this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
8831         },
8833         /* A date may be specified as an exact value or a relative one. */
8834         _determineDate: function( inst, date, defaultDate ) {
8835                 var offsetNumeric = function( offset ) {
8836                                 var date = new Date();
8837                                 date.setDate( date.getDate() + offset );
8838                                 return date;
8839                         },
8840                         offsetString = function( offset ) {
8841                                 try {
8842                                         return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8843                                                 offset, $.datepicker._getFormatConfig( inst ) );
8844                                 } catch ( e ) {
8846                                         // Ignore
8847                                 }
8849                                 var date = ( offset.toLowerCase().match( /^c/ ) ?
8850                                         $.datepicker._getDate( inst ) : null ) || new Date(),
8851                                         year = date.getFullYear(),
8852                                         month = date.getMonth(),
8853                                         day = date.getDate(),
8854                                         pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8855                                         matches = pattern.exec( offset );
8857                                 while ( matches ) {
8858                                         switch ( matches[ 2 ] || "d" ) {
8859                                                 case "d" : case "D" :
8860                                                         day += parseInt( matches[ 1 ], 10 ); break;
8861                                                 case "w" : case "W" :
8862                                                         day += parseInt( matches[ 1 ], 10 ) * 7; break;
8863                                                 case "m" : case "M" :
8864                                                         month += parseInt( matches[ 1 ], 10 );
8865                                                         day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8866                                                         break;
8867                                                 case "y": case "Y" :
8868                                                         year += parseInt( matches[ 1 ], 10 );
8869                                                         day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8870                                                         break;
8871                                         }
8872                                         matches = pattern.exec( offset );
8873                                 }
8874                                 return new Date( year, month, day );
8875                         },
8876                         newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
8877                                 ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
8879                 newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
8880                 if ( newDate ) {
8881                         newDate.setHours( 0 );
8882                         newDate.setMinutes( 0 );
8883                         newDate.setSeconds( 0 );
8884                         newDate.setMilliseconds( 0 );
8885                 }
8886                 return this._daylightSavingAdjust( newDate );
8887         },
8889         /* Handle switch to/from daylight saving.
8890          * Hours may be non-zero on daylight saving cut-over:
8891          * > 12 when midnight changeover, but then cannot generate
8892          * midnight datetime, so jump to 1AM, otherwise reset.
8893          * @param  date  (Date) the date to check
8894          * @return  (Date) the corrected date
8895          */
8896         _daylightSavingAdjust: function( date ) {
8897                 if ( !date ) {
8898                         return null;
8899                 }
8900                 date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
8901                 return date;
8902         },
8904         /* Set the date(s) directly. */
8905         _setDate: function( inst, date, noChange ) {
8906                 var clear = !date,
8907                         origMonth = inst.selectedMonth,
8908                         origYear = inst.selectedYear,
8909                         newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
8911                 inst.selectedDay = inst.currentDay = newDate.getDate();
8912                 inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8913                 inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8914                 if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
8915                         this._notifyChange( inst );
8916                 }
8917                 this._adjustInstDate( inst );
8918                 if ( inst.input ) {
8919                         inst.input.val( clear ? "" : this._formatDate( inst ) );
8920                 }
8921         },
8923         /* Retrieve the date(s) directly. */
8924         _getDate: function( inst ) {
8925                 var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
8926                         this._daylightSavingAdjust( new Date(
8927                         inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
8928                         return startDate;
8929         },
8931         /* Attach the onxxx handlers.  These are declared statically so
8932          * they work with static code transformers like Caja.
8933          */
8934         _attachHandlers: function( inst ) {
8935                 var stepMonths = this._get( inst, "stepMonths" ),
8936                         id = "#" + inst.id.replace( /\\\\/g, "\\" );
8937                 inst.dpDiv.find( "[data-handler]" ).map( function() {
8938                         var handler = {
8939                                 prev: function() {
8940                                         $.datepicker._adjustDate( id, -stepMonths, "M" );
8941                                 },
8942                                 next: function() {
8943                                         $.datepicker._adjustDate( id, +stepMonths, "M" );
8944                                 },
8945                                 hide: function() {
8946                                         $.datepicker._hideDatepicker();
8947                                 },
8948                                 today: function() {
8949                                         $.datepicker._gotoToday( id );
8950                                 },
8951                                 selectDay: function() {
8952                                         $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
8953                                         return false;
8954                                 },
8955                                 selectMonth: function() {
8956                                         $.datepicker._selectMonthYear( id, this, "M" );
8957                                         return false;
8958                                 },
8959                                 selectYear: function() {
8960                                         $.datepicker._selectMonthYear( id, this, "Y" );
8961                                         return false;
8962                                 }
8963                         };
8964                         $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
8965                 } );
8966         },
8968         /* Generate the HTML for the current state of the date picker. */
8969         _generateHTML: function( inst ) {
8970                 var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8971                         controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8972                         monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
8973                         selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8974                         cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8975                         printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8976                         tempDate = new Date(),
8977                         today = this._daylightSavingAdjust(
8978                                 new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
8979                         isRTL = this._get( inst, "isRTL" ),
8980                         showButtonPanel = this._get( inst, "showButtonPanel" ),
8981                         hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
8982                         navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
8983                         numMonths = this._getNumberOfMonths( inst ),
8984                         showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
8985                         stepMonths = this._get( inst, "stepMonths" ),
8986                         isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
8987                         currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
8988                                 new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
8989                         minDate = this._getMinMaxDate( inst, "min" ),
8990                         maxDate = this._getMinMaxDate( inst, "max" ),
8991                         drawMonth = inst.drawMonth - showCurrentAtPos,
8992                         drawYear = inst.drawYear;
8994                 if ( drawMonth < 0 ) {
8995                         drawMonth += 12;
8996                         drawYear--;
8997                 }
8998                 if ( maxDate ) {
8999                         maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
9000                                 maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
9001                         maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
9002                         while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
9003                                 drawMonth--;
9004                                 if ( drawMonth < 0 ) {
9005                                         drawMonth = 11;
9006                                         drawYear--;
9007                                 }
9008                         }
9009                 }
9010                 inst.drawMonth = drawMonth;
9011                 inst.drawYear = drawYear;
9013                 prevText = this._get( inst, "prevText" );
9014                 prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
9015                         this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
9016                         this._getFormatConfig( inst ) ) );
9018                 if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
9019                         prev = $( "<a>" )
9020                                 .attr( {
9021                                         "class": "ui-datepicker-prev ui-corner-all",
9022                                         "data-handler": "prev",
9023                                         "data-event": "click",
9024                                         title: prevText
9025                                 } )
9026                                 .append(
9027                                         $( "<span>" )
9028                                                 .addClass( "ui-icon ui-icon-circle-triangle-" +
9029                                                         ( isRTL ? "e" : "w" ) )
9030                                                 .text( prevText )
9031                                 )[ 0 ].outerHTML;
9032                 } else if ( hideIfNoPrevNext ) {
9033                         prev = "";
9034                 } else {
9035                         prev = $( "<a>" )
9036                                 .attr( {
9037                                         "class": "ui-datepicker-prev ui-corner-all ui-state-disabled",
9038                                         title: prevText
9039                                 } )
9040                                 .append(
9041                                         $( "<span>" )
9042                                                 .addClass( "ui-icon ui-icon-circle-triangle-" +
9043                                                         ( isRTL ? "e" : "w" ) )
9044                                                 .text( prevText )
9045                                 )[ 0 ].outerHTML;
9046                 }
9048                 nextText = this._get( inst, "nextText" );
9049                 nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
9050                         this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
9051                         this._getFormatConfig( inst ) ) );
9053                 if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) {
9054                         next = $( "<a>" )
9055                                 .attr( {
9056                                         "class": "ui-datepicker-next ui-corner-all",
9057                                         "data-handler": "next",
9058                                         "data-event": "click",
9059                                         title: nextText
9060                                 } )
9061                                 .append(
9062                                         $( "<span>" )
9063                                                 .addClass( "ui-icon ui-icon-circle-triangle-" +
9064                                                         ( isRTL ? "w" : "e" ) )
9065                                                 .text( nextText )
9066                                 )[ 0 ].outerHTML;
9067                 } else if ( hideIfNoPrevNext ) {
9068                         next = "";
9069                 } else {
9070                         next = $( "<a>" )
9071                                 .attr( {
9072                                         "class": "ui-datepicker-next ui-corner-all ui-state-disabled",
9073                                         title: nextText
9074                                 } )
9075                                 .append(
9076                                         $( "<span>" )
9077                                                 .attr( "class", "ui-icon ui-icon-circle-triangle-" +
9078                                                         ( isRTL ? "w" : "e" ) )
9079                                                 .text( nextText )
9080                                 )[ 0 ].outerHTML;
9081                 }
9083                 currentText = this._get( inst, "currentText" );
9084                 gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
9085                 currentText = ( !navigationAsDateFormat ? currentText :
9086                         this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
9088                 controls = "";
9089                 if ( !inst.inline ) {
9090                         controls = $( "<button>" )
9091                                 .attr( {
9092                                         type: "button",
9093                                         "class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
9094                                         "data-handler": "hide",
9095                                         "data-event": "click"
9096                                 } )
9097                                 .text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
9098                 }
9100                 buttonPanel = "";
9101                 if ( showButtonPanel ) {
9102                         buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
9103                                 .append( isRTL ? controls : "" )
9104                                 .append( this._isInRange( inst, gotoDate ) ?
9105                                         $( "<button>" )
9106                                                 .attr( {
9107                                                         type: "button",
9108                                                         "class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
9109                                                         "data-handler": "today",
9110                                                         "data-event": "click"
9111                                                 } )
9112                                                 .text( currentText ) :
9113                                         "" )
9114                                 .append( isRTL ? "" : controls )[ 0 ].outerHTML;
9115                 }
9117                 firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
9118                 firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
9120                 showWeek = this._get( inst, "showWeek" );
9121                 dayNames = this._get( inst, "dayNames" );
9122                 dayNamesMin = this._get( inst, "dayNamesMin" );
9123                 monthNames = this._get( inst, "monthNames" );
9124                 monthNamesShort = this._get( inst, "monthNamesShort" );
9125                 beforeShowDay = this._get( inst, "beforeShowDay" );
9126                 showOtherMonths = this._get( inst, "showOtherMonths" );
9127                 selectOtherMonths = this._get( inst, "selectOtherMonths" );
9128                 defaultDate = this._getDefaultDate( inst );
9129                 html = "";
9131                 for ( row = 0; row < numMonths[ 0 ]; row++ ) {
9132                         group = "";
9133                         this.maxRows = 4;
9134                         for ( col = 0; col < numMonths[ 1 ]; col++ ) {
9135                                 selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
9136                                 cornerClass = " ui-corner-all";
9137                                 calender = "";
9138                                 if ( isMultiMonth ) {
9139                                         calender += "<div class='ui-datepicker-group";
9140                                         if ( numMonths[ 1 ] > 1 ) {
9141                                                 switch ( col ) {
9142                                                         case 0: calender += " ui-datepicker-group-first";
9143                                                                 cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
9144                                                         case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
9145                                                                 cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
9146                                                         default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
9147                                                 }
9148                                         }
9149                                         calender += "'>";
9150                                 }
9151                                 calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
9152                                         ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
9153                                         ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
9154                                         this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
9155                                         row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
9156                                         "</div><table class='ui-datepicker-calendar'><thead>" +
9157                                         "<tr>";
9158                                 thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
9159                                 for ( dow = 0; dow < 7; dow++ ) { // days of the week
9160                                         day = ( dow + firstDay ) % 7;
9161                                         thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
9162                                                 "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
9163                                 }
9164                                 calender += thead + "</tr></thead><tbody>";
9165                                 daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
9166                                 if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
9167                                         inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
9168                                 }
9169                                 leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
9170                                 curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
9171                                 numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
9172                                 this.maxRows = numRows;
9173                                 printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
9174                                 for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
9175                                         calender += "<tr>";
9176                                         tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9177                                                 this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
9178                                         for ( dow = 0; dow < 7; dow++ ) { // create date picker days
9179                                                 daySettings = ( beforeShowDay ?
9180                                                         beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
9181                                                 otherMonth = ( printDate.getMonth() !== drawMonth );
9182                                                 unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
9183                                                         ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
9184                                                 tbody += "<td class='" +
9185                                                         ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
9186                                                         ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
9187                                                         ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
9188                                                         ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
9190                                                         // or defaultDate is current printedDate and defaultDate is selectedDate
9191                                                         " " + this._dayOverClass : "" ) + // highlight selected day
9192                                                         ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
9193                                                         ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
9194                                                         ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
9195                                                         ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
9196                                                         ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
9197                                                         ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
9198                                                         ( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
9199                                                         ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9200                                                         ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
9201                                                         ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
9202                                                         ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
9203                                                         "' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
9204                                                         "' data-date='" + printDate.getDate() + // store date as data
9205                                                         "'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
9206                                                 printDate.setDate( printDate.getDate() + 1 );
9207                                                 printDate = this._daylightSavingAdjust( printDate );
9208                                         }
9209                                         calender += tbody + "</tr>";
9210                                 }
9211                                 drawMonth++;
9212                                 if ( drawMonth > 11 ) {
9213                                         drawMonth = 0;
9214                                         drawYear++;
9215                                 }
9216                                 calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
9217                                                         ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
9218                                 group += calender;
9219                         }
9220                         html += group;
9221                 }
9222                 html += buttonPanel;
9223                 inst._keyEvent = false;
9224                 return html;
9225         },
9227         /* Generate the month and year header. */
9228         _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
9229                         secondary, monthNames, monthNamesShort ) {
9231                 var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9232                         changeMonth = this._get( inst, "changeMonth" ),
9233                         changeYear = this._get( inst, "changeYear" ),
9234                         showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
9235                         selectMonthLabel = this._get( inst, "selectMonthLabel" ),
9236                         selectYearLabel = this._get( inst, "selectYearLabel" ),
9237                         html = "<div class='ui-datepicker-title'>",
9238                         monthHtml = "";
9240                 // Month selection
9241                 if ( secondary || !changeMonth ) {
9242                         monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
9243                 } else {
9244                         inMinYear = ( minDate && minDate.getFullYear() === drawYear );
9245                         inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
9246                         monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
9247                         for ( month = 0; month < 12; month++ ) {
9248                                 if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
9249                                         monthHtml += "<option value='" + month + "'" +
9250                                                 ( month === drawMonth ? " selected='selected'" : "" ) +
9251                                                 ">" + monthNamesShort[ month ] + "</option>";
9252                                 }
9253                         }
9254                         monthHtml += "</select>";
9255                 }
9257                 if ( !showMonthAfterYear ) {
9258                         html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
9259                 }
9261                 // Year selection
9262                 if ( !inst.yearshtml ) {
9263                         inst.yearshtml = "";
9264                         if ( secondary || !changeYear ) {
9265                                 html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9266                         } else {
9268                                 // determine range of years to display
9269                                 years = this._get( inst, "yearRange" ).split( ":" );
9270                                 thisYear = new Date().getFullYear();
9271                                 determineYear = function( value ) {
9272                                         var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
9273                                                 ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
9274                                                 parseInt( value, 10 ) ) );
9275                                         return ( isNaN( year ) ? thisYear : year );
9276                                 };
9277                                 year = determineYear( years[ 0 ] );
9278                                 endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
9279                                 year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
9280                                 endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
9281                                 inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
9282                                 for ( ; year <= endYear; year++ ) {
9283                                         inst.yearshtml += "<option value='" + year + "'" +
9284                                                 ( year === drawYear ? " selected='selected'" : "" ) +
9285                                                 ">" + year + "</option>";
9286                                 }
9287                                 inst.yearshtml += "</select>";
9289                                 html += inst.yearshtml;
9290                                 inst.yearshtml = null;
9291                         }
9292                 }
9294                 html += this._get( inst, "yearSuffix" );
9295                 if ( showMonthAfterYear ) {
9296                         html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
9297                 }
9298                 html += "</div>"; // Close datepicker_header
9299                 return html;
9300         },
9302         /* Adjust one of the date sub-fields. */
9303         _adjustInstDate: function( inst, offset, period ) {
9304                 var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
9305                         month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
9306                         day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
9307                         date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
9309                 inst.selectedDay = date.getDate();
9310                 inst.drawMonth = inst.selectedMonth = date.getMonth();
9311                 inst.drawYear = inst.selectedYear = date.getFullYear();
9312                 if ( period === "M" || period === "Y" ) {
9313                         this._notifyChange( inst );
9314                 }
9315         },
9317         /* Ensure a date is within any min/max bounds. */
9318         _restrictMinMax: function( inst, date ) {
9319                 var minDate = this._getMinMaxDate( inst, "min" ),
9320                         maxDate = this._getMinMaxDate( inst, "max" ),
9321                         newDate = ( minDate && date < minDate ? minDate : date );
9322                 return ( maxDate && newDate > maxDate ? maxDate : newDate );
9323         },
9325         /* Notify change of month/year. */
9326         _notifyChange: function( inst ) {
9327                 var onChange = this._get( inst, "onChangeMonthYear" );
9328                 if ( onChange ) {
9329                         onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
9330                                 [ inst.selectedYear, inst.selectedMonth + 1, inst ] );
9331                 }
9332         },
9334         /* Determine the number of months to show. */
9335         _getNumberOfMonths: function( inst ) {
9336                 var numMonths = this._get( inst, "numberOfMonths" );
9337                 return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
9338         },
9340         /* Determine the current maximum date - ensure no time components are set. */
9341         _getMinMaxDate: function( inst, minMax ) {
9342                 return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
9343         },
9345         /* Find the number of days in a given month. */
9346         _getDaysInMonth: function( year, month ) {
9347                 return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
9348         },
9350         /* Find the day of the week of the first of a month. */
9351         _getFirstDayOfMonth: function( year, month ) {
9352                 return new Date( year, month, 1 ).getDay();
9353         },
9355         /* Determines if we should allow a "next/prev" month display change. */
9356         _canAdjustMonth: function( inst, offset, curYear, curMonth ) {
9357                 var numMonths = this._getNumberOfMonths( inst ),
9358                         date = this._daylightSavingAdjust( new Date( curYear,
9359                         curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
9361                 if ( offset < 0 ) {
9362                         date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
9363                 }
9364                 return this._isInRange( inst, date );
9365         },
9367         /* Is the given date in the accepted range? */
9368         _isInRange: function( inst, date ) {
9369                 var yearSplit, currentYear,
9370                         minDate = this._getMinMaxDate( inst, "min" ),
9371                         maxDate = this._getMinMaxDate( inst, "max" ),
9372                         minYear = null,
9373                         maxYear = null,
9374                         years = this._get( inst, "yearRange" );
9375                         if ( years ) {
9376                                 yearSplit = years.split( ":" );
9377                                 currentYear = new Date().getFullYear();
9378                                 minYear = parseInt( yearSplit[ 0 ], 10 );
9379                                 maxYear = parseInt( yearSplit[ 1 ], 10 );
9380                                 if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
9381                                         minYear += currentYear;
9382                                 }
9383                                 if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
9384                                         maxYear += currentYear;
9385                                 }
9386                         }
9388                 return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
9389                         ( !maxDate || date.getTime() <= maxDate.getTime() ) &&
9390                         ( !minYear || date.getFullYear() >= minYear ) &&
9391                         ( !maxYear || date.getFullYear() <= maxYear ) );
9392         },
9394         /* Provide the configuration settings for formatting/parsing. */
9395         _getFormatConfig: function( inst ) {
9396                 var shortYearCutoff = this._get( inst, "shortYearCutoff" );
9397                 shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
9398                         new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
9399                 return { shortYearCutoff: shortYearCutoff,
9400                         dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
9401                         monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
9402         },
9404         /* Format the given date for display. */
9405         _formatDate: function( inst, day, month, year ) {
9406                 if ( !day ) {
9407                         inst.currentDay = inst.selectedDay;
9408                         inst.currentMonth = inst.selectedMonth;
9409                         inst.currentYear = inst.selectedYear;
9410                 }
9411                 var date = ( day ? ( typeof day === "object" ? day :
9412                         this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
9413                         this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
9414                 return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
9415         }
9416 } );
9419  * Bind hover events for datepicker elements.
9420  * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9421  * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9422  */
9423 function datepicker_bindHover( dpDiv ) {
9424         var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9425         return dpDiv.on( "mouseout", selector, function() {
9426                         $( this ).removeClass( "ui-state-hover" );
9427                         if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9428                                 $( this ).removeClass( "ui-datepicker-prev-hover" );
9429                         }
9430                         if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9431                                 $( this ).removeClass( "ui-datepicker-next-hover" );
9432                         }
9433                 } )
9434                 .on( "mouseover", selector, datepicker_handleMouseover );
9437 function datepicker_handleMouseover() {
9438         if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
9439                 $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
9440                 $( this ).addClass( "ui-state-hover" );
9441                 if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9442                         $( this ).addClass( "ui-datepicker-prev-hover" );
9443                 }
9444                 if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9445                         $( this ).addClass( "ui-datepicker-next-hover" );
9446                 }
9447         }
9450 /* jQuery extend now ignores nulls! */
9451 function datepicker_extendRemove( target, props ) {
9452         $.extend( target, props );
9453         for ( var name in props ) {
9454                 if ( props[ name ] == null ) {
9455                         target[ name ] = props[ name ];
9456                 }
9457         }
9458         return target;
9461 /* Invoke the datepicker functionality.
9462    @param  options  string - a command, optionally followed by additional parameters or
9463                                         Object - settings for attaching new datepicker functionality
9464    @return  jQuery object */
9465 $.fn.datepicker = function( options ) {
9467         /* Verify an empty collection wasn't passed - Fixes #6976 */
9468         if ( !this.length ) {
9469                 return this;
9470         }
9472         /* Initialise the date picker. */
9473         if ( !$.datepicker.initialized ) {
9474                 $( document ).on( "mousedown", $.datepicker._checkExternalClick );
9475                 $.datepicker.initialized = true;
9476         }
9478         /* Append datepicker main container to body if not exist. */
9479         if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
9480                 $( "body" ).append( $.datepicker.dpDiv );
9481         }
9483         var otherArgs = Array.prototype.slice.call( arguments, 1 );
9484         if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
9485                 return $.datepicker[ "_" + options + "Datepicker" ].
9486                         apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9487         }
9488         if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
9489                 return $.datepicker[ "_" + options + "Datepicker" ].
9490                         apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9491         }
9492         return this.each( function() {
9493                 if ( typeof options === "string" ) {
9494                         $.datepicker[ "_" + options + "Datepicker" ]
9495                                 .apply( $.datepicker, [ this ].concat( otherArgs ) );
9496                 } else {
9497                         $.datepicker._attachDatepicker( this, options );
9498                 }
9499         } );
9502 $.datepicker = new Datepicker(); // singleton instance
9503 $.datepicker.initialized = false;
9504 $.datepicker.uuid = new Date().getTime();
9505 $.datepicker.version = "1.13.0";
9507 var widgetsDatepicker = $.datepicker;
9511 // This file is deprecated
9512 var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );
9515  * jQuery UI Mouse 1.13.0
9516  * http://jqueryui.com
9518  * Copyright jQuery Foundation and other contributors
9519  * Released under the MIT license.
9520  * http://jquery.org/license
9521  */
9523 //>>label: Mouse
9524 //>>group: Widgets
9525 //>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
9526 //>>docs: http://api.jqueryui.com/mouse/
9529 var mouseHandled = false;
9530 $( document ).on( "mouseup", function() {
9531         mouseHandled = false;
9532 } );
9534 var widgetsMouse = $.widget( "ui.mouse", {
9535         version: "1.13.0",
9536         options: {
9537                 cancel: "input, textarea, button, select, option",
9538                 distance: 1,
9539                 delay: 0
9540         },
9541         _mouseInit: function() {
9542                 var that = this;
9544                 this.element
9545                         .on( "mousedown." + this.widgetName, function( event ) {
9546                                 return that._mouseDown( event );
9547                         } )
9548                         .on( "click." + this.widgetName, function( event ) {
9549                                 if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
9550                                         $.removeData( event.target, that.widgetName + ".preventClickEvent" );
9551                                         event.stopImmediatePropagation();
9552                                         return false;
9553                                 }
9554                         } );
9556                 this.started = false;
9557         },
9559         // TODO: make sure destroying one instance of mouse doesn't mess with
9560         // other instances of mouse
9561         _mouseDestroy: function() {
9562                 this.element.off( "." + this.widgetName );
9563                 if ( this._mouseMoveDelegate ) {
9564                         this.document
9565                                 .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9566                                 .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9567                 }
9568         },
9570         _mouseDown: function( event ) {
9572                 // don't let more than one widget handle mouseStart
9573                 if ( mouseHandled ) {
9574                         return;
9575                 }
9577                 this._mouseMoved = false;
9579                 // We may have missed mouseup (out of window)
9580                 if ( this._mouseStarted ) {
9581                         this._mouseUp( event );
9582                 }
9584                 this._mouseDownEvent = event;
9586                 var that = this,
9587                         btnIsLeft = ( event.which === 1 ),
9589                         // event.target.nodeName works around a bug in IE 8 with
9590                         // disabled inputs (#7620)
9591                         elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ?
9592                                 $( event.target ).closest( this.options.cancel ).length : false );
9593                 if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
9594                         return true;
9595                 }
9597                 this.mouseDelayMet = !this.options.delay;
9598                 if ( !this.mouseDelayMet ) {
9599                         this._mouseDelayTimer = setTimeout( function() {
9600                                 that.mouseDelayMet = true;
9601                         }, this.options.delay );
9602                 }
9604                 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9605                         this._mouseStarted = ( this._mouseStart( event ) !== false );
9606                         if ( !this._mouseStarted ) {
9607                                 event.preventDefault();
9608                                 return true;
9609                         }
9610                 }
9612                 // Click event may never have fired (Gecko & Opera)
9613                 if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
9614                         $.removeData( event.target, this.widgetName + ".preventClickEvent" );
9615                 }
9617                 // These delegates are required to keep context
9618                 this._mouseMoveDelegate = function( event ) {
9619                         return that._mouseMove( event );
9620                 };
9621                 this._mouseUpDelegate = function( event ) {
9622                         return that._mouseUp( event );
9623                 };
9625                 this.document
9626                         .on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9627                         .on( "mouseup." + this.widgetName, this._mouseUpDelegate );
9629                 event.preventDefault();
9631                 mouseHandled = true;
9632                 return true;
9633         },
9635         _mouseMove: function( event ) {
9637                 // Only check for mouseups outside the document if you've moved inside the document
9638                 // at least once. This prevents the firing of mouseup in the case of IE<9, which will
9639                 // fire a mousemove event if content is placed under the cursor. See #7778
9640                 // Support: IE <9
9641                 if ( this._mouseMoved ) {
9643                         // IE mouseup check - mouseup happened when mouse was out of window
9644                         if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&
9645                                         !event.button ) {
9646                                 return this._mouseUp( event );
9648                         // Iframe mouseup check - mouseup occurred in another document
9649                         } else if ( !event.which ) {
9651                                 // Support: Safari <=8 - 9
9652                                 // Safari sets which to 0 if you press any of the following keys
9653                                 // during a drag (#14461)
9654                                 if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
9655                                                 event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
9656                                         this.ignoreMissingWhich = true;
9657                                 } else if ( !this.ignoreMissingWhich ) {
9658                                         return this._mouseUp( event );
9659                                 }
9660                         }
9661                 }
9663                 if ( event.which || event.button ) {
9664                         this._mouseMoved = true;
9665                 }
9667                 if ( this._mouseStarted ) {
9668                         this._mouseDrag( event );
9669                         return event.preventDefault();
9670                 }
9672                 if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9673                         this._mouseStarted =
9674                                 ( this._mouseStart( this._mouseDownEvent, event ) !== false );
9675                         if ( this._mouseStarted ) {
9676                                 this._mouseDrag( event );
9677                         } else {
9678                                 this._mouseUp( event );
9679                         }
9680                 }
9682                 return !this._mouseStarted;
9683         },
9685         _mouseUp: function( event ) {
9686                 this.document
9687                         .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9688                         .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9690                 if ( this._mouseStarted ) {
9691                         this._mouseStarted = false;
9693                         if ( event.target === this._mouseDownEvent.target ) {
9694                                 $.data( event.target, this.widgetName + ".preventClickEvent", true );
9695                         }
9697                         this._mouseStop( event );
9698                 }
9700                 if ( this._mouseDelayTimer ) {
9701                         clearTimeout( this._mouseDelayTimer );
9702                         delete this._mouseDelayTimer;
9703                 }
9705                 this.ignoreMissingWhich = false;
9706                 mouseHandled = false;
9707                 event.preventDefault();
9708         },
9710         _mouseDistanceMet: function( event ) {
9711                 return ( Math.max(
9712                                 Math.abs( this._mouseDownEvent.pageX - event.pageX ),
9713                                 Math.abs( this._mouseDownEvent.pageY - event.pageY )
9714                         ) >= this.options.distance
9715                 );
9716         },
9718         _mouseDelayMet: function( /* event */ ) {
9719                 return this.mouseDelayMet;
9720         },
9722         // These are placeholder methods, to be overriden by extending plugin
9723         _mouseStart: function( /* event */ ) {},
9724         _mouseDrag: function( /* event */ ) {},
9725         _mouseStop: function( /* event */ ) {},
9726         _mouseCapture: function( /* event */ ) {
9727                 return true;
9728         }
9729 } );
9733 // $.ui.plugin is deprecated. Use $.widget() extensions instead.
9734 var plugin = $.ui.plugin = {
9735         add: function( module, option, set ) {
9736                 var i,
9737                         proto = $.ui[ module ].prototype;
9738                 for ( i in set ) {
9739                         proto.plugins[ i ] = proto.plugins[ i ] || [];
9740                         proto.plugins[ i ].push( [ option, set[ i ] ] );
9741                 }
9742         },
9743         call: function( instance, name, args, allowDisconnected ) {
9744                 var i,
9745                         set = instance.plugins[ name ];
9747                 if ( !set ) {
9748                         return;
9749                 }
9751                 if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
9752                                 instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
9753                         return;
9754                 }
9756                 for ( i = 0; i < set.length; i++ ) {
9757                         if ( instance.options[ set[ i ][ 0 ] ] ) {
9758                                 set[ i ][ 1 ].apply( instance.element, args );
9759                         }
9760                 }
9761         }
9766 var safeBlur = $.ui.safeBlur = function( element ) {
9768         // Support: IE9 - 10 only
9769         // If the <body> is blurred, IE will switch windows, see #9420
9770         if ( element && element.nodeName.toLowerCase() !== "body" ) {
9771                 $( element ).trigger( "blur" );
9772         }
9777  * jQuery UI Draggable 1.13.0
9778  * http://jqueryui.com
9780  * Copyright jQuery Foundation and other contributors
9781  * Released under the MIT license.
9782  * http://jquery.org/license
9783  */
9785 //>>label: Draggable
9786 //>>group: Interactions
9787 //>>description: Enables dragging functionality for any element.
9788 //>>docs: http://api.jqueryui.com/draggable/
9789 //>>demos: http://jqueryui.com/draggable/
9790 //>>css.structure: ../../themes/base/draggable.css
9793 $.widget( "ui.draggable", $.ui.mouse, {
9794         version: "1.13.0",
9795         widgetEventPrefix: "drag",
9796         options: {
9797                 addClasses: true,
9798                 appendTo: "parent",
9799                 axis: false,
9800                 connectToSortable: false,
9801                 containment: false,
9802                 cursor: "auto",
9803                 cursorAt: false,
9804                 grid: false,
9805                 handle: false,
9806                 helper: "original",
9807                 iframeFix: false,
9808                 opacity: false,
9809                 refreshPositions: false,
9810                 revert: false,
9811                 revertDuration: 500,
9812                 scope: "default",
9813                 scroll: true,
9814                 scrollSensitivity: 20,
9815                 scrollSpeed: 20,
9816                 snap: false,
9817                 snapMode: "both",
9818                 snapTolerance: 20,
9819                 stack: false,
9820                 zIndex: false,
9822                 // Callbacks
9823                 drag: null,
9824                 start: null,
9825                 stop: null
9826         },
9827         _create: function() {
9829                 if ( this.options.helper === "original" ) {
9830                         this._setPositionRelative();
9831                 }
9832                 if ( this.options.addClasses ) {
9833                         this._addClass( "ui-draggable" );
9834                 }
9835                 this._setHandleClassName();
9837                 this._mouseInit();
9838         },
9840         _setOption: function( key, value ) {
9841                 this._super( key, value );
9842                 if ( key === "handle" ) {
9843                         this._removeHandleClassName();
9844                         this._setHandleClassName();
9845                 }
9846         },
9848         _destroy: function() {
9849                 if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
9850                         this.destroyOnClear = true;
9851                         return;
9852                 }
9853                 this._removeHandleClassName();
9854                 this._mouseDestroy();
9855         },
9857         _mouseCapture: function( event ) {
9858                 var o = this.options;
9860                 // Among others, prevent a drag on a resizable-handle
9861                 if ( this.helper || o.disabled ||
9862                                 $( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
9863                         return false;
9864                 }
9866                 //Quit if we're not on a valid handle
9867                 this.handle = this._getHandle( event );
9868                 if ( !this.handle ) {
9869                         return false;
9870                 }
9872                 this._blurActiveElement( event );
9874                 this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
9876                 return true;
9878         },
9880         _blockFrames: function( selector ) {
9881                 this.iframeBlocks = this.document.find( selector ).map( function() {
9882                         var iframe = $( this );
9884                         return $( "<div>" )
9885                                 .css( "position", "absolute" )
9886                                 .appendTo( iframe.parent() )
9887                                 .outerWidth( iframe.outerWidth() )
9888                                 .outerHeight( iframe.outerHeight() )
9889                                 .offset( iframe.offset() )[ 0 ];
9890                 } );
9891         },
9893         _unblockFrames: function() {
9894                 if ( this.iframeBlocks ) {
9895                         this.iframeBlocks.remove();
9896                         delete this.iframeBlocks;
9897                 }
9898         },
9900         _blurActiveElement: function( event ) {
9901                 var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
9902                         target = $( event.target );
9904                 // Don't blur if the event occurred on an element that is within
9905                 // the currently focused element
9906                 // See #10527, #12472
9907                 if ( target.closest( activeElement ).length ) {
9908                         return;
9909                 }
9911                 // Blur any element that currently has focus, see #4261
9912                 $.ui.safeBlur( activeElement );
9913         },
9915         _mouseStart: function( event ) {
9917                 var o = this.options;
9919                 //Create and append the visible helper
9920                 this.helper = this._createHelper( event );
9922                 this._addClass( this.helper, "ui-draggable-dragging" );
9924                 //Cache the helper size
9925                 this._cacheHelperProportions();
9927                 //If ddmanager is used for droppables, set the global draggable
9928                 if ( $.ui.ddmanager ) {
9929                         $.ui.ddmanager.current = this;
9930                 }
9932                 /*
9933                  * - Position generation -
9934                  * This block generates everything position related - it's the core of draggables.
9935                  */
9937                 //Cache the margins of the original element
9938                 this._cacheMargins();
9940                 //Store the helper's css position
9941                 this.cssPosition = this.helper.css( "position" );
9942                 this.scrollParent = this.helper.scrollParent( true );
9943                 this.offsetParent = this.helper.offsetParent();
9944                 this.hasFixedAncestor = this.helper.parents().filter( function() {
9945                                 return $( this ).css( "position" ) === "fixed";
9946                         } ).length > 0;
9948                 //The element's absolute position on the page minus margins
9949                 this.positionAbs = this.element.offset();
9950                 this._refreshOffsets( event );
9952                 //Generate the original position
9953                 this.originalPosition = this.position = this._generatePosition( event, false );
9954                 this.originalPageX = event.pageX;
9955                 this.originalPageY = event.pageY;
9957                 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
9958                 if ( o.cursorAt ) {
9959                         this._adjustOffsetFromHelper( o.cursorAt );
9960                 }
9962                 //Set a containment if given in the options
9963                 this._setContainment();
9965                 //Trigger event + callbacks
9966                 if ( this._trigger( "start", event ) === false ) {
9967                         this._clear();
9968                         return false;
9969                 }
9971                 //Recache the helper size
9972                 this._cacheHelperProportions();
9974                 //Prepare the droppable offsets
9975                 if ( $.ui.ddmanager && !o.dropBehaviour ) {
9976                         $.ui.ddmanager.prepareOffsets( this, event );
9977                 }
9979                 // Execute the drag once - this causes the helper not to be visible before getting its
9980                 // correct position
9981                 this._mouseDrag( event, true );
9983                 // If the ddmanager is used for droppables, inform the manager that dragging has started
9984                 // (see #5003)
9985                 if ( $.ui.ddmanager ) {
9986                         $.ui.ddmanager.dragStart( this, event );
9987                 }
9989                 return true;
9990         },
9992         _refreshOffsets: function( event ) {
9993                 this.offset = {
9994                         top: this.positionAbs.top - this.margins.top,
9995                         left: this.positionAbs.left - this.margins.left,
9996                         scroll: false,
9997                         parent: this._getParentOffset(),
9998                         relative: this._getRelativeOffset()
9999                 };
10001                 this.offset.click = {
10002                         left: event.pageX - this.offset.left,
10003                         top: event.pageY - this.offset.top
10004                 };
10005         },
10007         _mouseDrag: function( event, noPropagation ) {
10009                 // reset any necessary cached properties (see #5009)
10010                 if ( this.hasFixedAncestor ) {
10011                         this.offset.parent = this._getParentOffset();
10012                 }
10014                 //Compute the helpers position
10015                 this.position = this._generatePosition( event, true );
10016                 this.positionAbs = this._convertPositionTo( "absolute" );
10018                 //Call plugins and callbacks and use the resulting position if something is returned
10019                 if ( !noPropagation ) {
10020                         var ui = this._uiHash();
10021                         if ( this._trigger( "drag", event, ui ) === false ) {
10022                                 this._mouseUp( new $.Event( "mouseup", event ) );
10023                                 return false;
10024                         }
10025                         this.position = ui.position;
10026                 }
10028                 this.helper[ 0 ].style.left = this.position.left + "px";
10029                 this.helper[ 0 ].style.top = this.position.top + "px";
10031                 if ( $.ui.ddmanager ) {
10032                         $.ui.ddmanager.drag( this, event );
10033                 }
10035                 return false;
10036         },
10038         _mouseStop: function( event ) {
10040                 //If we are using droppables, inform the manager about the drop
10041                 var that = this,
10042                         dropped = false;
10043                 if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
10044                         dropped = $.ui.ddmanager.drop( this, event );
10045                 }
10047                 //if a drop comes from outside (a sortable)
10048                 if ( this.dropped ) {
10049                         dropped = this.dropped;
10050                         this.dropped = false;
10051                 }
10053                 if ( ( this.options.revert === "invalid" && !dropped ) ||
10054                                 ( this.options.revert === "valid" && dropped ) ||
10055                                 this.options.revert === true || ( typeof this.options.revert === "function" &&
10056                                 this.options.revert.call( this.element, dropped ) )
10057                 ) {
10058                         $( this.helper ).animate(
10059                                 this.originalPosition,
10060                                 parseInt( this.options.revertDuration, 10 ),
10061                                 function() {
10062                                         if ( that._trigger( "stop", event ) !== false ) {
10063                                                 that._clear();
10064                                         }
10065                                 }
10066                         );
10067                 } else {
10068                         if ( this._trigger( "stop", event ) !== false ) {
10069                                 this._clear();
10070                         }
10071                 }
10073                 return false;
10074         },
10076         _mouseUp: function( event ) {
10077                 this._unblockFrames();
10079                 // If the ddmanager is used for droppables, inform the manager that dragging has stopped
10080                 // (see #5003)
10081                 if ( $.ui.ddmanager ) {
10082                         $.ui.ddmanager.dragStop( this, event );
10083                 }
10085                 // Only need to focus if the event occurred on the draggable itself, see #10527
10086                 if ( this.handleElement.is( event.target ) ) {
10088                         // The interaction is over; whether or not the click resulted in a drag,
10089                         // focus the element
10090                         this.element.trigger( "focus" );
10091                 }
10093                 return $.ui.mouse.prototype._mouseUp.call( this, event );
10094         },
10096         cancel: function() {
10098                 if ( this.helper.is( ".ui-draggable-dragging" ) ) {
10099                         this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
10100                 } else {
10101                         this._clear();
10102                 }
10104                 return this;
10106         },
10108         _getHandle: function( event ) {
10109                 return this.options.handle ?
10110                         !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
10111                         true;
10112         },
10114         _setHandleClassName: function() {
10115                 this.handleElement = this.options.handle ?
10116                         this.element.find( this.options.handle ) : this.element;
10117                 this._addClass( this.handleElement, "ui-draggable-handle" );
10118         },
10120         _removeHandleClassName: function() {
10121                 this._removeClass( this.handleElement, "ui-draggable-handle" );
10122         },
10124         _createHelper: function( event ) {
10126                 var o = this.options,
10127                         helperIsFunction = typeof o.helper === "function",
10128                         helper = helperIsFunction ?
10129                                 $( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
10130                                 ( o.helper === "clone" ?
10131                                         this.element.clone().removeAttr( "id" ) :
10132                                         this.element );
10134                 if ( !helper.parents( "body" ).length ) {
10135                         helper.appendTo( ( o.appendTo === "parent" ?
10136                                 this.element[ 0 ].parentNode :
10137                                 o.appendTo ) );
10138                 }
10140                 // Http://bugs.jqueryui.com/ticket/9446
10141                 // a helper function can return the original element
10142                 // which wouldn't have been set to relative in _create
10143                 if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
10144                         this._setPositionRelative();
10145                 }
10147                 if ( helper[ 0 ] !== this.element[ 0 ] &&
10148                                 !( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
10149                         helper.css( "position", "absolute" );
10150                 }
10152                 return helper;
10154         },
10156         _setPositionRelative: function() {
10157                 if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
10158                         this.element[ 0 ].style.position = "relative";
10159                 }
10160         },
10162         _adjustOffsetFromHelper: function( obj ) {
10163                 if ( typeof obj === "string" ) {
10164                         obj = obj.split( " " );
10165                 }
10166                 if ( Array.isArray( obj ) ) {
10167                         obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
10168                 }
10169                 if ( "left" in obj ) {
10170                         this.offset.click.left = obj.left + this.margins.left;
10171                 }
10172                 if ( "right" in obj ) {
10173                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
10174                 }
10175                 if ( "top" in obj ) {
10176                         this.offset.click.top = obj.top + this.margins.top;
10177                 }
10178                 if ( "bottom" in obj ) {
10179                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
10180                 }
10181         },
10183         _isRootNode: function( element ) {
10184                 return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
10185         },
10187         _getParentOffset: function() {
10189                 //Get the offsetParent and cache its position
10190                 var po = this.offsetParent.offset(),
10191                         document = this.document[ 0 ];
10193                 // This is a special case where we need to modify a offset calculated on start, since the
10194                 // following happened:
10195                 // 1. The position of the helper is absolute, so it's position is calculated based on the
10196                 // next positioned parent
10197                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
10198                 // the document, which means that the scroll is included in the initial calculation of the
10199                 // offset of the parent, and never recalculated upon drag
10200                 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
10201                                 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
10202                         po.left += this.scrollParent.scrollLeft();
10203                         po.top += this.scrollParent.scrollTop();
10204                 }
10206                 if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
10207                         po = { top: 0, left: 0 };
10208                 }
10210                 return {
10211                         top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
10212                         left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
10213                 };
10215         },
10217         _getRelativeOffset: function() {
10218                 if ( this.cssPosition !== "relative" ) {
10219                         return { top: 0, left: 0 };
10220                 }
10222                 var p = this.element.position(),
10223                         scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10225                 return {
10226                         top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
10227                                 ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
10228                         left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
10229                                 ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
10230                 };
10232         },
10234         _cacheMargins: function() {
10235                 this.margins = {
10236                         left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
10237                         top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
10238                         right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
10239                         bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
10240                 };
10241         },
10243         _cacheHelperProportions: function() {
10244                 this.helperProportions = {
10245                         width: this.helper.outerWidth(),
10246                         height: this.helper.outerHeight()
10247                 };
10248         },
10250         _setContainment: function() {
10252                 var isUserScrollable, c, ce,
10253                         o = this.options,
10254                         document = this.document[ 0 ];
10256                 this.relativeContainer = null;
10258                 if ( !o.containment ) {
10259                         this.containment = null;
10260                         return;
10261                 }
10263                 if ( o.containment === "window" ) {
10264                         this.containment = [
10265                                 $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
10266                                 $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
10267                                 $( window ).scrollLeft() + $( window ).width() -
10268                                         this.helperProportions.width - this.margins.left,
10269                                 $( window ).scrollTop() +
10270                                         ( $( window ).height() || document.body.parentNode.scrollHeight ) -
10271                                         this.helperProportions.height - this.margins.top
10272                         ];
10273                         return;
10274                 }
10276                 if ( o.containment === "document" ) {
10277                         this.containment = [
10278                                 0,
10279                                 0,
10280                                 $( document ).width() - this.helperProportions.width - this.margins.left,
10281                                 ( $( document ).height() || document.body.parentNode.scrollHeight ) -
10282                                         this.helperProportions.height - this.margins.top
10283                         ];
10284                         return;
10285                 }
10287                 if ( o.containment.constructor === Array ) {
10288                         this.containment = o.containment;
10289                         return;
10290                 }
10292                 if ( o.containment === "parent" ) {
10293                         o.containment = this.helper[ 0 ].parentNode;
10294                 }
10296                 c = $( o.containment );
10297                 ce = c[ 0 ];
10299                 if ( !ce ) {
10300                         return;
10301                 }
10303                 isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
10305                 this.containment = [
10306                         ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
10307                                 ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
10308                         ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
10309                                 ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
10310                         ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
10311                                 ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
10312                                 ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
10313                                 this.helperProportions.width -
10314                                 this.margins.left -
10315                                 this.margins.right,
10316                         ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
10317                                 ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
10318                                 ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
10319                                 this.helperProportions.height -
10320                                 this.margins.top -
10321                                 this.margins.bottom
10322                 ];
10323                 this.relativeContainer = c;
10324         },
10326         _convertPositionTo: function( d, pos ) {
10328                 if ( !pos ) {
10329                         pos = this.position;
10330                 }
10332                 var mod = d === "absolute" ? 1 : -1,
10333                         scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10335                 return {
10336                         top: (
10338                                 // The absolute mouse position
10339                                 pos.top +
10341                                 // Only for relative positioned nodes: Relative offset from element to offset parent
10342                                 this.offset.relative.top * mod +
10344                                 // The offsetParent's offset without borders (offset + border)
10345                                 this.offset.parent.top * mod -
10346                                 ( ( this.cssPosition === "fixed" ?
10347                                         -this.offset.scroll.top :
10348                                         ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
10349                         ),
10350                         left: (
10352                                 // The absolute mouse position
10353                                 pos.left +
10355                                 // Only for relative positioned nodes: Relative offset from element to offset parent
10356                                 this.offset.relative.left * mod +
10358                                 // The offsetParent's offset without borders (offset + border)
10359                                 this.offset.parent.left * mod   -
10360                                 ( ( this.cssPosition === "fixed" ?
10361                                         -this.offset.scroll.left :
10362                                         ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
10363                         )
10364                 };
10366         },
10368         _generatePosition: function( event, constrainPosition ) {
10370                 var containment, co, top, left,
10371                         o = this.options,
10372                         scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
10373                         pageX = event.pageX,
10374                         pageY = event.pageY;
10376                 // Cache the scroll
10377                 if ( !scrollIsRootNode || !this.offset.scroll ) {
10378                         this.offset.scroll = {
10379                                 top: this.scrollParent.scrollTop(),
10380                                 left: this.scrollParent.scrollLeft()
10381                         };
10382                 }
10384                 /*
10385                  * - Position constraining -
10386                  * Constrain the position to a mix of grid, containment.
10387                  */
10389                 // If we are not dragging yet, we won't check for options
10390                 if ( constrainPosition ) {
10391                         if ( this.containment ) {
10392                                 if ( this.relativeContainer ) {
10393                                         co = this.relativeContainer.offset();
10394                                         containment = [
10395                                                 this.containment[ 0 ] + co.left,
10396                                                 this.containment[ 1 ] + co.top,
10397                                                 this.containment[ 2 ] + co.left,
10398                                                 this.containment[ 3 ] + co.top
10399                                         ];
10400                                 } else {
10401                                         containment = this.containment;
10402                                 }
10404                                 if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
10405                                         pageX = containment[ 0 ] + this.offset.click.left;
10406                                 }
10407                                 if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
10408                                         pageY = containment[ 1 ] + this.offset.click.top;
10409                                 }
10410                                 if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
10411                                         pageX = containment[ 2 ] + this.offset.click.left;
10412                                 }
10413                                 if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
10414                                         pageY = containment[ 3 ] + this.offset.click.top;
10415                                 }
10416                         }
10418                         if ( o.grid ) {
10420                                 //Check for grid elements set to 0 to prevent divide by 0 error causing invalid
10421                                 // argument errors in IE (see ticket #6950)
10422                                 top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
10423                                         this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
10424                                 pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
10425                                         top - this.offset.click.top > containment[ 3 ] ) ?
10426                                                 top :
10427                                                 ( ( top - this.offset.click.top >= containment[ 1 ] ) ?
10428                                                         top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
10430                                 left = o.grid[ 0 ] ? this.originalPageX +
10431                                         Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
10432                                         this.originalPageX;
10433                                 pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
10434                                         left - this.offset.click.left > containment[ 2 ] ) ?
10435                                                 left :
10436                                                 ( ( left - this.offset.click.left >= containment[ 0 ] ) ?
10437                                                         left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
10438                         }
10440                         if ( o.axis === "y" ) {
10441                                 pageX = this.originalPageX;
10442                         }
10444                         if ( o.axis === "x" ) {
10445                                 pageY = this.originalPageY;
10446                         }
10447                 }
10449                 return {
10450                         top: (
10452                                 // The absolute mouse position
10453                                 pageY -
10455                                 // Click offset (relative to the element)
10456                                 this.offset.click.top -
10458                                 // Only for relative positioned nodes: Relative offset from element to offset parent
10459                                 this.offset.relative.top -
10461                                 // The offsetParent's offset without borders (offset + border)
10462                                 this.offset.parent.top +
10463                                 ( this.cssPosition === "fixed" ?
10464                                         -this.offset.scroll.top :
10465                                         ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
10466                         ),
10467                         left: (
10469                                 // The absolute mouse position
10470                                 pageX -
10472                                 // Click offset (relative to the element)
10473                                 this.offset.click.left -
10475                                 // Only for relative positioned nodes: Relative offset from element to offset parent
10476                                 this.offset.relative.left -
10478                                 // The offsetParent's offset without borders (offset + border)
10479                                 this.offset.parent.left +
10480                                 ( this.cssPosition === "fixed" ?
10481                                         -this.offset.scroll.left :
10482                                         ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
10483                         )
10484                 };
10486         },
10488         _clear: function() {
10489                 this._removeClass( this.helper, "ui-draggable-dragging" );
10490                 if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
10491                         this.helper.remove();
10492                 }
10493                 this.helper = null;
10494                 this.cancelHelperRemoval = false;
10495                 if ( this.destroyOnClear ) {
10496                         this.destroy();
10497                 }
10498         },
10500         // From now on bulk stuff - mainly helpers
10502         _trigger: function( type, event, ui ) {
10503                 ui = ui || this._uiHash();
10504                 $.ui.plugin.call( this, type, [ event, ui, this ], true );
10506                 // Absolute position and offset (see #6884 ) have to be recalculated after plugins
10507                 if ( /^(drag|start|stop)/.test( type ) ) {
10508                         this.positionAbs = this._convertPositionTo( "absolute" );
10509                         ui.offset = this.positionAbs;
10510                 }
10511                 return $.Widget.prototype._trigger.call( this, type, event, ui );
10512         },
10514         plugins: {},
10516         _uiHash: function() {
10517                 return {
10518                         helper: this.helper,
10519                         position: this.position,
10520                         originalPosition: this.originalPosition,
10521                         offset: this.positionAbs
10522                 };
10523         }
10525 } );
10527 $.ui.plugin.add( "draggable", "connectToSortable", {
10528         start: function( event, ui, draggable ) {
10529                 var uiSortable = $.extend( {}, ui, {
10530                         item: draggable.element
10531                 } );
10533                 draggable.sortables = [];
10534                 $( draggable.options.connectToSortable ).each( function() {
10535                         var sortable = $( this ).sortable( "instance" );
10537                         if ( sortable && !sortable.options.disabled ) {
10538                                 draggable.sortables.push( sortable );
10540                                 // RefreshPositions is called at drag start to refresh the containerCache
10541                                 // which is used in drag. This ensures it's initialized and synchronized
10542                                 // with any changes that might have happened on the page since initialization.
10543                                 sortable.refreshPositions();
10544                                 sortable._trigger( "activate", event, uiSortable );
10545                         }
10546                 } );
10547         },
10548         stop: function( event, ui, draggable ) {
10549                 var uiSortable = $.extend( {}, ui, {
10550                         item: draggable.element
10551                 } );
10553                 draggable.cancelHelperRemoval = false;
10555                 $.each( draggable.sortables, function() {
10556                         var sortable = this;
10558                         if ( sortable.isOver ) {
10559                                 sortable.isOver = 0;
10561                                 // Allow this sortable to handle removing the helper
10562                                 draggable.cancelHelperRemoval = true;
10563                                 sortable.cancelHelperRemoval = false;
10565                                 // Use _storedCSS To restore properties in the sortable,
10566                                 // as this also handles revert (#9675) since the draggable
10567                                 // may have modified them in unexpected ways (#8809)
10568                                 sortable._storedCSS = {
10569                                         position: sortable.placeholder.css( "position" ),
10570                                         top: sortable.placeholder.css( "top" ),
10571                                         left: sortable.placeholder.css( "left" )
10572                                 };
10574                                 sortable._mouseStop( event );
10576                                 // Once drag has ended, the sortable should return to using
10577                                 // its original helper, not the shared helper from draggable
10578                                 sortable.options.helper = sortable.options._helper;
10579                         } else {
10581                                 // Prevent this Sortable from removing the helper.
10582                                 // However, don't set the draggable to remove the helper
10583                                 // either as another connected Sortable may yet handle the removal.
10584                                 sortable.cancelHelperRemoval = true;
10586                                 sortable._trigger( "deactivate", event, uiSortable );
10587                         }
10588                 } );
10589         },
10590         drag: function( event, ui, draggable ) {
10591                 $.each( draggable.sortables, function() {
10592                         var innermostIntersecting = false,
10593                                 sortable = this;
10595                         // Copy over variables that sortable's _intersectsWith uses
10596                         sortable.positionAbs = draggable.positionAbs;
10597                         sortable.helperProportions = draggable.helperProportions;
10598                         sortable.offset.click = draggable.offset.click;
10600                         if ( sortable._intersectsWith( sortable.containerCache ) ) {
10601                                 innermostIntersecting = true;
10603                                 $.each( draggable.sortables, function() {
10605                                         // Copy over variables that sortable's _intersectsWith uses
10606                                         this.positionAbs = draggable.positionAbs;
10607                                         this.helperProportions = draggable.helperProportions;
10608                                         this.offset.click = draggable.offset.click;
10610                                         if ( this !== sortable &&
10611                                                         this._intersectsWith( this.containerCache ) &&
10612                                                         $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
10613                                                 innermostIntersecting = false;
10614                                         }
10616                                         return innermostIntersecting;
10617                                 } );
10618                         }
10620                         if ( innermostIntersecting ) {
10622                                 // If it intersects, we use a little isOver variable and set it once,
10623                                 // so that the move-in stuff gets fired only once.
10624                                 if ( !sortable.isOver ) {
10625                                         sortable.isOver = 1;
10627                                         // Store draggable's parent in case we need to reappend to it later.
10628                                         draggable._parent = ui.helper.parent();
10630                                         sortable.currentItem = ui.helper
10631                                                 .appendTo( sortable.element )
10632                                                 .data( "ui-sortable-item", true );
10634                                         // Store helper option to later restore it
10635                                         sortable.options._helper = sortable.options.helper;
10637                                         sortable.options.helper = function() {
10638                                                 return ui.helper[ 0 ];
10639                                         };
10641                                         // Fire the start events of the sortable with our passed browser event,
10642                                         // and our own helper (so it doesn't create a new one)
10643                                         event.target = sortable.currentItem[ 0 ];
10644                                         sortable._mouseCapture( event, true );
10645                                         sortable._mouseStart( event, true, true );
10647                                         // Because the browser event is way off the new appended portlet,
10648                                         // modify necessary variables to reflect the changes
10649                                         sortable.offset.click.top = draggable.offset.click.top;
10650                                         sortable.offset.click.left = draggable.offset.click.left;
10651                                         sortable.offset.parent.left -= draggable.offset.parent.left -
10652                                                 sortable.offset.parent.left;
10653                                         sortable.offset.parent.top -= draggable.offset.parent.top -
10654                                                 sortable.offset.parent.top;
10656                                         draggable._trigger( "toSortable", event );
10658                                         // Inform draggable that the helper is in a valid drop zone,
10659                                         // used solely in the revert option to handle "valid/invalid".
10660                                         draggable.dropped = sortable.element;
10662                                         // Need to refreshPositions of all sortables in the case that
10663                                         // adding to one sortable changes the location of the other sortables (#9675)
10664                                         $.each( draggable.sortables, function() {
10665                                                 this.refreshPositions();
10666                                         } );
10668                                         // Hack so receive/update callbacks work (mostly)
10669                                         draggable.currentItem = draggable.element;
10670                                         sortable.fromOutside = draggable;
10671                                 }
10673                                 if ( sortable.currentItem ) {
10674                                         sortable._mouseDrag( event );
10676                                         // Copy the sortable's position because the draggable's can potentially reflect
10677                                         // a relative position, while sortable is always absolute, which the dragged
10678                                         // element has now become. (#8809)
10679                                         ui.position = sortable.position;
10680                                 }
10681                         } else {
10683                                 // If it doesn't intersect with the sortable, and it intersected before,
10684                                 // we fake the drag stop of the sortable, but make sure it doesn't remove
10685                                 // the helper by using cancelHelperRemoval.
10686                                 if ( sortable.isOver ) {
10688                                         sortable.isOver = 0;
10689                                         sortable.cancelHelperRemoval = true;
10691                                         // Calling sortable's mouseStop would trigger a revert,
10692                                         // so revert must be temporarily false until after mouseStop is called.
10693                                         sortable.options._revert = sortable.options.revert;
10694                                         sortable.options.revert = false;
10696                                         sortable._trigger( "out", event, sortable._uiHash( sortable ) );
10697                                         sortable._mouseStop( event, true );
10699                                         // Restore sortable behaviors that were modfied
10700                                         // when the draggable entered the sortable area (#9481)
10701                                         sortable.options.revert = sortable.options._revert;
10702                                         sortable.options.helper = sortable.options._helper;
10704                                         if ( sortable.placeholder ) {
10705                                                 sortable.placeholder.remove();
10706                                         }
10708                                         // Restore and recalculate the draggable's offset considering the sortable
10709                                         // may have modified them in unexpected ways. (#8809, #10669)
10710                                         ui.helper.appendTo( draggable._parent );
10711                                         draggable._refreshOffsets( event );
10712                                         ui.position = draggable._generatePosition( event, true );
10714                                         draggable._trigger( "fromSortable", event );
10716                                         // Inform draggable that the helper is no longer in a valid drop zone
10717                                         draggable.dropped = false;
10719                                         // Need to refreshPositions of all sortables just in case removing
10720                                         // from one sortable changes the location of other sortables (#9675)
10721                                         $.each( draggable.sortables, function() {
10722                                                 this.refreshPositions();
10723                                         } );
10724                                 }
10725                         }
10726                 } );
10727         }
10728 } );
10730 $.ui.plugin.add( "draggable", "cursor", {
10731         start: function( event, ui, instance ) {
10732                 var t = $( "body" ),
10733                         o = instance.options;
10735                 if ( t.css( "cursor" ) ) {
10736                         o._cursor = t.css( "cursor" );
10737                 }
10738                 t.css( "cursor", o.cursor );
10739         },
10740         stop: function( event, ui, instance ) {
10741                 var o = instance.options;
10742                 if ( o._cursor ) {
10743                         $( "body" ).css( "cursor", o._cursor );
10744                 }
10745         }
10746 } );
10748 $.ui.plugin.add( "draggable", "opacity", {
10749         start: function( event, ui, instance ) {
10750                 var t = $( ui.helper ),
10751                         o = instance.options;
10752                 if ( t.css( "opacity" ) ) {
10753                         o._opacity = t.css( "opacity" );
10754                 }
10755                 t.css( "opacity", o.opacity );
10756         },
10757         stop: function( event, ui, instance ) {
10758                 var o = instance.options;
10759                 if ( o._opacity ) {
10760                         $( ui.helper ).css( "opacity", o._opacity );
10761                 }
10762         }
10763 } );
10765 $.ui.plugin.add( "draggable", "scroll", {
10766         start: function( event, ui, i ) {
10767                 if ( !i.scrollParentNotHidden ) {
10768                         i.scrollParentNotHidden = i.helper.scrollParent( false );
10769                 }
10771                 if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
10772                                 i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
10773                         i.overflowOffset = i.scrollParentNotHidden.offset();
10774                 }
10775         },
10776         drag: function( event, ui, i  ) {
10778                 var o = i.options,
10779                         scrolled = false,
10780                         scrollParent = i.scrollParentNotHidden[ 0 ],
10781                         document = i.document[ 0 ];
10783                 if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
10784                         if ( !o.axis || o.axis !== "x" ) {
10785                                 if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
10786                                                 o.scrollSensitivity ) {
10787                                         scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
10788                                 } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
10789                                         scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
10790                                 }
10791                         }
10793                         if ( !o.axis || o.axis !== "y" ) {
10794                                 if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
10795                                                 o.scrollSensitivity ) {
10796                                         scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
10797                                 } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
10798                                         scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
10799                                 }
10800                         }
10802                 } else {
10804                         if ( !o.axis || o.axis !== "x" ) {
10805                                 if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
10806                                         scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
10807                                 } else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
10808                                                 o.scrollSensitivity ) {
10809                                         scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
10810                                 }
10811                         }
10813                         if ( !o.axis || o.axis !== "y" ) {
10814                                 if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
10815                                         scrolled = $( document ).scrollLeft(
10816                                                 $( document ).scrollLeft() - o.scrollSpeed
10817                                         );
10818                                 } else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
10819                                                 o.scrollSensitivity ) {
10820                                         scrolled = $( document ).scrollLeft(
10821                                                 $( document ).scrollLeft() + o.scrollSpeed
10822                                         );
10823                                 }
10824                         }
10826                 }
10828                 if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
10829                         $.ui.ddmanager.prepareOffsets( i, event );
10830                 }
10832         }
10833 } );
10835 $.ui.plugin.add( "draggable", "snap", {
10836         start: function( event, ui, i ) {
10838                 var o = i.options;
10840                 i.snapElements = [];
10842                 $( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
10843                         .each( function() {
10844                                 var $t = $( this ),
10845                                         $o = $t.offset();
10846                                 if ( this !== i.element[ 0 ] ) {
10847                                         i.snapElements.push( {
10848                                                 item: this,
10849                                                 width: $t.outerWidth(), height: $t.outerHeight(),
10850                                                 top: $o.top, left: $o.left
10851                                         } );
10852                                 }
10853                         } );
10855         },
10856         drag: function( event, ui, inst ) {
10858                 var ts, bs, ls, rs, l, r, t, b, i, first,
10859                         o = inst.options,
10860                         d = o.snapTolerance,
10861                         x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
10862                         y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
10864                 for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
10866                         l = inst.snapElements[ i ].left - inst.margins.left;
10867                         r = l + inst.snapElements[ i ].width;
10868                         t = inst.snapElements[ i ].top - inst.margins.top;
10869                         b = t + inst.snapElements[ i ].height;
10871                         if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
10872                                         !$.contains( inst.snapElements[ i ].item.ownerDocument,
10873                                         inst.snapElements[ i ].item ) ) {
10874                                 if ( inst.snapElements[ i ].snapping ) {
10875                                         if ( inst.options.snap.release ) {
10876                                                 inst.options.snap.release.call(
10877                                                         inst.element,
10878                                                         event,
10879                                                         $.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
10880                                                 );
10881                                         }
10882                                 }
10883                                 inst.snapElements[ i ].snapping = false;
10884                                 continue;
10885                         }
10887                         if ( o.snapMode !== "inner" ) {
10888                                 ts = Math.abs( t - y2 ) <= d;
10889                                 bs = Math.abs( b - y1 ) <= d;
10890                                 ls = Math.abs( l - x2 ) <= d;
10891                                 rs = Math.abs( r - x1 ) <= d;
10892                                 if ( ts ) {
10893                                         ui.position.top = inst._convertPositionTo( "relative", {
10894                                                 top: t - inst.helperProportions.height,
10895                                                 left: 0
10896                                         } ).top;
10897                                 }
10898                                 if ( bs ) {
10899                                         ui.position.top = inst._convertPositionTo( "relative", {
10900                                                 top: b,
10901                                                 left: 0
10902                                         } ).top;
10903                                 }
10904                                 if ( ls ) {
10905                                         ui.position.left = inst._convertPositionTo( "relative", {
10906                                                 top: 0,
10907                                                 left: l - inst.helperProportions.width
10908                                         } ).left;
10909                                 }
10910                                 if ( rs ) {
10911                                         ui.position.left = inst._convertPositionTo( "relative", {
10912                                                 top: 0,
10913                                                 left: r
10914                                         } ).left;
10915                                 }
10916                         }
10918                         first = ( ts || bs || ls || rs );
10920                         if ( o.snapMode !== "outer" ) {
10921                                 ts = Math.abs( t - y1 ) <= d;
10922                                 bs = Math.abs( b - y2 ) <= d;
10923                                 ls = Math.abs( l - x1 ) <= d;
10924                                 rs = Math.abs( r - x2 ) <= d;
10925                                 if ( ts ) {
10926                                         ui.position.top = inst._convertPositionTo( "relative", {
10927                                                 top: t,
10928                                                 left: 0
10929                                         } ).top;
10930                                 }
10931                                 if ( bs ) {
10932                                         ui.position.top = inst._convertPositionTo( "relative", {
10933                                                 top: b - inst.helperProportions.height,
10934                                                 left: 0
10935                                         } ).top;
10936                                 }
10937                                 if ( ls ) {
10938                                         ui.position.left = inst._convertPositionTo( "relative", {
10939                                                 top: 0,
10940                                                 left: l
10941                                         } ).left;
10942                                 }
10943                                 if ( rs ) {
10944                                         ui.position.left = inst._convertPositionTo( "relative", {
10945                                                 top: 0,
10946                                                 left: r - inst.helperProportions.width
10947                                         } ).left;
10948                                 }
10949                         }
10951                         if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
10952                                 if ( inst.options.snap.snap ) {
10953                                         inst.options.snap.snap.call(
10954                                                 inst.element,
10955                                                 event,
10956                                                 $.extend( inst._uiHash(), {
10957                                                         snapItem: inst.snapElements[ i ].item
10958                                                 } ) );
10959                                 }
10960                         }
10961                         inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
10963                 }
10965         }
10966 } );
10968 $.ui.plugin.add( "draggable", "stack", {
10969         start: function( event, ui, instance ) {
10970                 var min,
10971                         o = instance.options,
10972                         group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
10973                                 return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
10974                                         ( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
10975                         } );
10977                 if ( !group.length ) {
10978                         return;
10979                 }
10981                 min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
10982                 $( group ).each( function( i ) {
10983                         $( this ).css( "zIndex", min + i );
10984                 } );
10985                 this.css( "zIndex", ( min + group.length ) );
10986         }
10987 } );
10989 $.ui.plugin.add( "draggable", "zIndex", {
10990         start: function( event, ui, instance ) {
10991                 var t = $( ui.helper ),
10992                         o = instance.options;
10994                 if ( t.css( "zIndex" ) ) {
10995                         o._zIndex = t.css( "zIndex" );
10996                 }
10997                 t.css( "zIndex", o.zIndex );
10998         },
10999         stop: function( event, ui, instance ) {
11000                 var o = instance.options;
11002                 if ( o._zIndex ) {
11003                         $( ui.helper ).css( "zIndex", o._zIndex );
11004                 }
11005         }
11006 } );
11008 var widgetsDraggable = $.ui.draggable;
11012  * jQuery UI Resizable 1.13.0
11013  * http://jqueryui.com
11015  * Copyright jQuery Foundation and other contributors
11016  * Released under the MIT license.
11017  * http://jquery.org/license
11018  */
11020 //>>label: Resizable
11021 //>>group: Interactions
11022 //>>description: Enables resize functionality for any element.
11023 //>>docs: http://api.jqueryui.com/resizable/
11024 //>>demos: http://jqueryui.com/resizable/
11025 //>>css.structure: ../../themes/base/core.css
11026 //>>css.structure: ../../themes/base/resizable.css
11027 //>>css.theme: ../../themes/base/theme.css
11030 $.widget( "ui.resizable", $.ui.mouse, {
11031         version: "1.13.0",
11032         widgetEventPrefix: "resize",
11033         options: {
11034                 alsoResize: false,
11035                 animate: false,
11036                 animateDuration: "slow",
11037                 animateEasing: "swing",
11038                 aspectRatio: false,
11039                 autoHide: false,
11040                 classes: {
11041                         "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
11042                 },
11043                 containment: false,
11044                 ghost: false,
11045                 grid: false,
11046                 handles: "e,s,se",
11047                 helper: false,
11048                 maxHeight: null,
11049                 maxWidth: null,
11050                 minHeight: 10,
11051                 minWidth: 10,
11053                 // See #7960
11054                 zIndex: 90,
11056                 // Callbacks
11057                 resize: null,
11058                 start: null,
11059                 stop: null
11060         },
11062         _num: function( value ) {
11063                 return parseFloat( value ) || 0;
11064         },
11066         _isNumber: function( value ) {
11067                 return !isNaN( parseFloat( value ) );
11068         },
11070         _hasScroll: function( el, a ) {
11072                 if ( $( el ).css( "overflow" ) === "hidden" ) {
11073                         return false;
11074                 }
11076                 var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
11077                         has = false;
11079                 if ( el[ scroll ] > 0 ) {
11080                         return true;
11081                 }
11083                 // TODO: determine which cases actually cause this to happen
11084                 // if the element doesn't have the scroll set, see if it's possible to
11085                 // set the scroll
11086                 try {
11087                         el[ scroll ] = 1;
11088                         has = ( el[ scroll ] > 0 );
11089                         el[ scroll ] = 0;
11090                 } catch ( e ) {
11092                         // `el` might be a string, then setting `scroll` will throw
11093                         // an error in strict mode; ignore it.
11094                 }
11095                 return has;
11096         },
11098         _create: function() {
11100                 var margins,
11101                         o = this.options,
11102                         that = this;
11103                 this._addClass( "ui-resizable" );
11105                 $.extend( this, {
11106                         _aspectRatio: !!( o.aspectRatio ),
11107                         aspectRatio: o.aspectRatio,
11108                         originalElement: this.element,
11109                         _proportionallyResizeElements: [],
11110                         _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
11111                 } );
11113                 // Wrap the element if it cannot hold child nodes
11114                 if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
11116                         this.element.wrap(
11117                                 $( "<div class='ui-wrapper'></div>" ).css( {
11118                                         overflow: "hidden",
11119                                         position: this.element.css( "position" ),
11120                                         width: this.element.outerWidth(),
11121                                         height: this.element.outerHeight(),
11122                                         top: this.element.css( "top" ),
11123                                         left: this.element.css( "left" )
11124                                 } )
11125                         );
11127                         this.element = this.element.parent().data(
11128                                 "ui-resizable", this.element.resizable( "instance" )
11129                         );
11131                         this.elementIsWrapper = true;
11133                         margins = {
11134                                 marginTop: this.originalElement.css( "marginTop" ),
11135                                 marginRight: this.originalElement.css( "marginRight" ),
11136                                 marginBottom: this.originalElement.css( "marginBottom" ),
11137                                 marginLeft: this.originalElement.css( "marginLeft" )
11138                         };
11140                         this.element.css( margins );
11141                         this.originalElement.css( "margin", 0 );
11143                         // support: Safari
11144                         // Prevent Safari textarea resize
11145                         this.originalResizeStyle = this.originalElement.css( "resize" );
11146                         this.originalElement.css( "resize", "none" );
11148                         this._proportionallyResizeElements.push( this.originalElement.css( {
11149                                 position: "static",
11150                                 zoom: 1,
11151                                 display: "block"
11152                         } ) );
11154                         // Support: IE9
11155                         // avoid IE jump (hard set the margin)
11156                         this.originalElement.css( margins );
11158                         this._proportionallyResize();
11159                 }
11161                 this._setupHandles();
11163                 if ( o.autoHide ) {
11164                         $( this.element )
11165                                 .on( "mouseenter", function() {
11166                                         if ( o.disabled ) {
11167                                                 return;
11168                                         }
11169                                         that._removeClass( "ui-resizable-autohide" );
11170                                         that._handles.show();
11171                                 } )
11172                                 .on( "mouseleave", function() {
11173                                         if ( o.disabled ) {
11174                                                 return;
11175                                         }
11176                                         if ( !that.resizing ) {
11177                                                 that._addClass( "ui-resizable-autohide" );
11178                                                 that._handles.hide();
11179                                         }
11180                                 } );
11181                 }
11183                 this._mouseInit();
11184         },
11186         _destroy: function() {
11188                 this._mouseDestroy();
11189                 this._addedHandles.remove();
11191                 var wrapper,
11192                         _destroy = function( exp ) {
11193                                 $( exp )
11194                                         .removeData( "resizable" )
11195                                         .removeData( "ui-resizable" )
11196                                         .off( ".resizable" );
11197                         };
11199                 // TODO: Unwrap at same DOM position
11200                 if ( this.elementIsWrapper ) {
11201                         _destroy( this.element );
11202                         wrapper = this.element;
11203                         this.originalElement.css( {
11204                                 position: wrapper.css( "position" ),
11205                                 width: wrapper.outerWidth(),
11206                                 height: wrapper.outerHeight(),
11207                                 top: wrapper.css( "top" ),
11208                                 left: wrapper.css( "left" )
11209                         } ).insertAfter( wrapper );
11210                         wrapper.remove();
11211                 }
11213                 this.originalElement.css( "resize", this.originalResizeStyle );
11214                 _destroy( this.originalElement );
11216                 return this;
11217         },
11219         _setOption: function( key, value ) {
11220                 this._super( key, value );
11222                 switch ( key ) {
11223                 case "handles":
11224                         this._removeHandles();
11225                         this._setupHandles();
11226                         break;
11227                 case "aspectRatio":
11228                         this._aspectRatio = !!value;
11229                         break;
11230                 default:
11231                         break;
11232                 }
11233         },
11235         _setupHandles: function() {
11236                 var o = this.options, handle, i, n, hname, axis, that = this;
11237                 this.handles = o.handles ||
11238                         ( !$( ".ui-resizable-handle", this.element ).length ?
11239                                 "e,s,se" : {
11240                                         n: ".ui-resizable-n",
11241                                         e: ".ui-resizable-e",
11242                                         s: ".ui-resizable-s",
11243                                         w: ".ui-resizable-w",
11244                                         se: ".ui-resizable-se",
11245                                         sw: ".ui-resizable-sw",
11246                                         ne: ".ui-resizable-ne",
11247                                         nw: ".ui-resizable-nw"
11248                                 } );
11250                 this._handles = $();
11251                 this._addedHandles = $();
11252                 if ( this.handles.constructor === String ) {
11254                         if ( this.handles === "all" ) {
11255                                 this.handles = "n,e,s,w,se,sw,ne,nw";
11256                         }
11258                         n = this.handles.split( "," );
11259                         this.handles = {};
11261                         for ( i = 0; i < n.length; i++ ) {
11263                                 handle = String.prototype.trim.call( n[ i ] );
11264                                 hname = "ui-resizable-" + handle;
11265                                 axis = $( "<div>" );
11266                                 this._addClass( axis, "ui-resizable-handle " + hname );
11268                                 axis.css( { zIndex: o.zIndex } );
11270                                 this.handles[ handle ] = ".ui-resizable-" + handle;
11271                                 if ( !this.element.children( this.handles[ handle ] ).length ) {
11272                                         this.element.append( axis );
11273                                         this._addedHandles = this._addedHandles.add( axis );
11274                                 }
11275                         }
11277                 }
11279                 this._renderAxis = function( target ) {
11281                         var i, axis, padPos, padWrapper;
11283                         target = target || this.element;
11285                         for ( i in this.handles ) {
11287                                 if ( this.handles[ i ].constructor === String ) {
11288                                         this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
11289                                 } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
11290                                         this.handles[ i ] = $( this.handles[ i ] );
11291                                         this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
11292                                 }
11294                                 if ( this.elementIsWrapper &&
11295                                                 this.originalElement[ 0 ]
11296                                                         .nodeName
11297                                                         .match( /^(textarea|input|select|button)$/i ) ) {
11298                                         axis = $( this.handles[ i ], this.element );
11300                                         padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
11301                                                 axis.outerHeight() :
11302                                                 axis.outerWidth();
11304                                         padPos = [ "padding",
11305                                                 /ne|nw|n/.test( i ) ? "Top" :
11306                                                 /se|sw|s/.test( i ) ? "Bottom" :
11307                                                 /^e$/.test( i ) ? "Right" : "Left" ].join( "" );
11309                                         target.css( padPos, padWrapper );
11311                                         this._proportionallyResize();
11312                                 }
11314                                 this._handles = this._handles.add( this.handles[ i ] );
11315                         }
11316                 };
11318                 // TODO: make renderAxis a prototype function
11319                 this._renderAxis( this.element );
11321                 this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
11322                 this._handles.disableSelection();
11324                 this._handles.on( "mouseover", function() {
11325                         if ( !that.resizing ) {
11326                                 if ( this.className ) {
11327                                         axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
11328                                 }
11329                                 that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
11330                         }
11331                 } );
11333                 if ( o.autoHide ) {
11334                         this._handles.hide();
11335                         this._addClass( "ui-resizable-autohide" );
11336                 }
11337         },
11339         _removeHandles: function() {
11340                 this._addedHandles.remove();
11341         },
11343         _mouseCapture: function( event ) {
11344                 var i, handle,
11345                         capture = false;
11347                 for ( i in this.handles ) {
11348                         handle = $( this.handles[ i ] )[ 0 ];
11349                         if ( handle === event.target || $.contains( handle, event.target ) ) {
11350                                 capture = true;
11351                         }
11352                 }
11354                 return !this.options.disabled && capture;
11355         },
11357         _mouseStart: function( event ) {
11359                 var curleft, curtop, cursor,
11360                         o = this.options,
11361                         el = this.element;
11363                 this.resizing = true;
11365                 this._renderProxy();
11367                 curleft = this._num( this.helper.css( "left" ) );
11368                 curtop = this._num( this.helper.css( "top" ) );
11370                 if ( o.containment ) {
11371                         curleft += $( o.containment ).scrollLeft() || 0;
11372                         curtop += $( o.containment ).scrollTop() || 0;
11373                 }
11375                 this.offset = this.helper.offset();
11376                 this.position = { left: curleft, top: curtop };
11378                 this.size = this._helper ? {
11379                                 width: this.helper.width(),
11380                                 height: this.helper.height()
11381                         } : {
11382                                 width: el.width(),
11383                                 height: el.height()
11384                         };
11386                 this.originalSize = this._helper ? {
11387                                 width: el.outerWidth(),
11388                                 height: el.outerHeight()
11389                         } : {
11390                                 width: el.width(),
11391                                 height: el.height()
11392                         };
11394                 this.sizeDiff = {
11395                         width: el.outerWidth() - el.width(),
11396                         height: el.outerHeight() - el.height()
11397                 };
11399                 this.originalPosition = { left: curleft, top: curtop };
11400                 this.originalMousePosition = { left: event.pageX, top: event.pageY };
11402                 this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
11403                         o.aspectRatio :
11404                         ( ( this.originalSize.width / this.originalSize.height ) || 1 );
11406                 cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
11407                 $( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
11409                 this._addClass( "ui-resizable-resizing" );
11410                 this._propagate( "start", event );
11411                 return true;
11412         },
11414         _mouseDrag: function( event ) {
11416                 var data, props,
11417                         smp = this.originalMousePosition,
11418                         a = this.axis,
11419                         dx = ( event.pageX - smp.left ) || 0,
11420                         dy = ( event.pageY - smp.top ) || 0,
11421                         trigger = this._change[ a ];
11423                 this._updatePrevProperties();
11425                 if ( !trigger ) {
11426                         return false;
11427                 }
11429                 data = trigger.apply( this, [ event, dx, dy ] );
11431                 this._updateVirtualBoundaries( event.shiftKey );
11432                 if ( this._aspectRatio || event.shiftKey ) {
11433                         data = this._updateRatio( data, event );
11434                 }
11436                 data = this._respectSize( data, event );
11438                 this._updateCache( data );
11440                 this._propagate( "resize", event );
11442                 props = this._applyChanges();
11444                 if ( !this._helper && this._proportionallyResizeElements.length ) {
11445                         this._proportionallyResize();
11446                 }
11448                 if ( !$.isEmptyObject( props ) ) {
11449                         this._updatePrevProperties();
11450                         this._trigger( "resize", event, this.ui() );
11451                         this._applyChanges();
11452                 }
11454                 return false;
11455         },
11457         _mouseStop: function( event ) {
11459                 this.resizing = false;
11460                 var pr, ista, soffseth, soffsetw, s, left, top,
11461                         o = this.options, that = this;
11463                 if ( this._helper ) {
11465                         pr = this._proportionallyResizeElements;
11466                         ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
11467                         soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
11468                         soffsetw = ista ? 0 : that.sizeDiff.width;
11470                         s = {
11471                                 width: ( that.helper.width()  - soffsetw ),
11472                                 height: ( that.helper.height() - soffseth )
11473                         };
11474                         left = ( parseFloat( that.element.css( "left" ) ) +
11475                                 ( that.position.left - that.originalPosition.left ) ) || null;
11476                         top = ( parseFloat( that.element.css( "top" ) ) +
11477                                 ( that.position.top - that.originalPosition.top ) ) || null;
11479                         if ( !o.animate ) {
11480                                 this.element.css( $.extend( s, { top: top, left: left } ) );
11481                         }
11483                         that.helper.height( that.size.height );
11484                         that.helper.width( that.size.width );
11486                         if ( this._helper && !o.animate ) {
11487                                 this._proportionallyResize();
11488                         }
11489                 }
11491                 $( "body" ).css( "cursor", "auto" );
11493                 this._removeClass( "ui-resizable-resizing" );
11495                 this._propagate( "stop", event );
11497                 if ( this._helper ) {
11498                         this.helper.remove();
11499                 }
11501                 return false;
11503         },
11505         _updatePrevProperties: function() {
11506                 this.prevPosition = {
11507                         top: this.position.top,
11508                         left: this.position.left
11509                 };
11510                 this.prevSize = {
11511                         width: this.size.width,
11512                         height: this.size.height
11513                 };
11514         },
11516         _applyChanges: function() {
11517                 var props = {};
11519                 if ( this.position.top !== this.prevPosition.top ) {
11520                         props.top = this.position.top + "px";
11521                 }
11522                 if ( this.position.left !== this.prevPosition.left ) {
11523                         props.left = this.position.left + "px";
11524                 }
11525                 if ( this.size.width !== this.prevSize.width ) {
11526                         props.width = this.size.width + "px";
11527                 }
11528                 if ( this.size.height !== this.prevSize.height ) {
11529                         props.height = this.size.height + "px";
11530                 }
11532                 this.helper.css( props );
11534                 return props;
11535         },
11537         _updateVirtualBoundaries: function( forceAspectRatio ) {
11538                 var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
11539                         o = this.options;
11541                 b = {
11542                         minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
11543                         maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
11544                         minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
11545                         maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
11546                 };
11548                 if ( this._aspectRatio || forceAspectRatio ) {
11549                         pMinWidth = b.minHeight * this.aspectRatio;
11550                         pMinHeight = b.minWidth / this.aspectRatio;
11551                         pMaxWidth = b.maxHeight * this.aspectRatio;
11552                         pMaxHeight = b.maxWidth / this.aspectRatio;
11554                         if ( pMinWidth > b.minWidth ) {
11555                                 b.minWidth = pMinWidth;
11556                         }
11557                         if ( pMinHeight > b.minHeight ) {
11558                                 b.minHeight = pMinHeight;
11559                         }
11560                         if ( pMaxWidth < b.maxWidth ) {
11561                                 b.maxWidth = pMaxWidth;
11562                         }
11563                         if ( pMaxHeight < b.maxHeight ) {
11564                                 b.maxHeight = pMaxHeight;
11565                         }
11566                 }
11567                 this._vBoundaries = b;
11568         },
11570         _updateCache: function( data ) {
11571                 this.offset = this.helper.offset();
11572                 if ( this._isNumber( data.left ) ) {
11573                         this.position.left = data.left;
11574                 }
11575                 if ( this._isNumber( data.top ) ) {
11576                         this.position.top = data.top;
11577                 }
11578                 if ( this._isNumber( data.height ) ) {
11579                         this.size.height = data.height;
11580                 }
11581                 if ( this._isNumber( data.width ) ) {
11582                         this.size.width = data.width;
11583                 }
11584         },
11586         _updateRatio: function( data ) {
11588                 var cpos = this.position,
11589                         csize = this.size,
11590                         a = this.axis;
11592                 if ( this._isNumber( data.height ) ) {
11593                         data.width = ( data.height * this.aspectRatio );
11594                 } else if ( this._isNumber( data.width ) ) {
11595                         data.height = ( data.width / this.aspectRatio );
11596                 }
11598                 if ( a === "sw" ) {
11599                         data.left = cpos.left + ( csize.width - data.width );
11600                         data.top = null;
11601                 }
11602                 if ( a === "nw" ) {
11603                         data.top = cpos.top + ( csize.height - data.height );
11604                         data.left = cpos.left + ( csize.width - data.width );
11605                 }
11607                 return data;
11608         },
11610         _respectSize: function( data ) {
11612                 var o = this._vBoundaries,
11613                         a = this.axis,
11614                         ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
11615                         ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
11616                         isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
11617                         isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
11618                         dw = this.originalPosition.left + this.originalSize.width,
11619                         dh = this.originalPosition.top + this.originalSize.height,
11620                         cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
11621                 if ( isminw ) {
11622                         data.width = o.minWidth;
11623                 }
11624                 if ( isminh ) {
11625                         data.height = o.minHeight;
11626                 }
11627                 if ( ismaxw ) {
11628                         data.width = o.maxWidth;
11629                 }
11630                 if ( ismaxh ) {
11631                         data.height = o.maxHeight;
11632                 }
11634                 if ( isminw && cw ) {
11635                         data.left = dw - o.minWidth;
11636                 }
11637                 if ( ismaxw && cw ) {
11638                         data.left = dw - o.maxWidth;
11639                 }
11640                 if ( isminh && ch ) {
11641                         data.top = dh - o.minHeight;
11642                 }
11643                 if ( ismaxh && ch ) {
11644                         data.top = dh - o.maxHeight;
11645                 }
11647                 // Fixing jump error on top/left - bug #2330
11648                 if ( !data.width && !data.height && !data.left && data.top ) {
11649                         data.top = null;
11650                 } else if ( !data.width && !data.height && !data.top && data.left ) {
11651                         data.left = null;
11652                 }
11654                 return data;
11655         },
11657         _getPaddingPlusBorderDimensions: function( element ) {
11658                 var i = 0,
11659                         widths = [],
11660                         borders = [
11661                                 element.css( "borderTopWidth" ),
11662                                 element.css( "borderRightWidth" ),
11663                                 element.css( "borderBottomWidth" ),
11664                                 element.css( "borderLeftWidth" )
11665                         ],
11666                         paddings = [
11667                                 element.css( "paddingTop" ),
11668                                 element.css( "paddingRight" ),
11669                                 element.css( "paddingBottom" ),
11670                                 element.css( "paddingLeft" )
11671                         ];
11673                 for ( ; i < 4; i++ ) {
11674                         widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
11675                         widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
11676                 }
11678                 return {
11679                         height: widths[ 0 ] + widths[ 2 ],
11680                         width: widths[ 1 ] + widths[ 3 ]
11681                 };
11682         },
11684         _proportionallyResize: function() {
11686                 if ( !this._proportionallyResizeElements.length ) {
11687                         return;
11688                 }
11690                 var prel,
11691                         i = 0,
11692                         element = this.helper || this.element;
11694                 for ( ; i < this._proportionallyResizeElements.length; i++ ) {
11696                         prel = this._proportionallyResizeElements[ i ];
11698                         // TODO: Seems like a bug to cache this.outerDimensions
11699                         // considering that we are in a loop.
11700                         if ( !this.outerDimensions ) {
11701                                 this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
11702                         }
11704                         prel.css( {
11705                                 height: ( element.height() - this.outerDimensions.height ) || 0,
11706                                 width: ( element.width() - this.outerDimensions.width ) || 0
11707                         } );
11709                 }
11711         },
11713         _renderProxy: function() {
11715                 var el = this.element, o = this.options;
11716                 this.elementOffset = el.offset();
11718                 if ( this._helper ) {
11720                         this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } );
11722                         this._addClass( this.helper, this._helper );
11723                         this.helper.css( {
11724                                 width: this.element.outerWidth(),
11725                                 height: this.element.outerHeight(),
11726                                 position: "absolute",
11727                                 left: this.elementOffset.left + "px",
11728                                 top: this.elementOffset.top + "px",
11729                                 zIndex: ++o.zIndex //TODO: Don't modify option
11730                         } );
11732                         this.helper
11733                                 .appendTo( "body" )
11734                                 .disableSelection();
11736                 } else {
11737                         this.helper = this.element;
11738                 }
11740         },
11742         _change: {
11743                 e: function( event, dx ) {
11744                         return { width: this.originalSize.width + dx };
11745                 },
11746                 w: function( event, dx ) {
11747                         var cs = this.originalSize, sp = this.originalPosition;
11748                         return { left: sp.left + dx, width: cs.width - dx };
11749                 },
11750                 n: function( event, dx, dy ) {
11751                         var cs = this.originalSize, sp = this.originalPosition;
11752                         return { top: sp.top + dy, height: cs.height - dy };
11753                 },
11754                 s: function( event, dx, dy ) {
11755                         return { height: this.originalSize.height + dy };
11756                 },
11757                 se: function( event, dx, dy ) {
11758                         return $.extend( this._change.s.apply( this, arguments ),
11759                                 this._change.e.apply( this, [ event, dx, dy ] ) );
11760                 },
11761                 sw: function( event, dx, dy ) {
11762                         return $.extend( this._change.s.apply( this, arguments ),
11763                                 this._change.w.apply( this, [ event, dx, dy ] ) );
11764                 },
11765                 ne: function( event, dx, dy ) {
11766                         return $.extend( this._change.n.apply( this, arguments ),
11767                                 this._change.e.apply( this, [ event, dx, dy ] ) );
11768                 },
11769                 nw: function( event, dx, dy ) {
11770                         return $.extend( this._change.n.apply( this, arguments ),
11771                                 this._change.w.apply( this, [ event, dx, dy ] ) );
11772                 }
11773         },
11775         _propagate: function( n, event ) {
11776                 $.ui.plugin.call( this, n, [ event, this.ui() ] );
11777                 if ( n !== "resize" ) {
11778                         this._trigger( n, event, this.ui() );
11779                 }
11780         },
11782         plugins: {},
11784         ui: function() {
11785                 return {
11786                         originalElement: this.originalElement,
11787                         element: this.element,
11788                         helper: this.helper,
11789                         position: this.position,
11790                         size: this.size,
11791                         originalSize: this.originalSize,
11792                         originalPosition: this.originalPosition
11793                 };
11794         }
11796 } );
11799  * Resizable Extensions
11800  */
11802 $.ui.plugin.add( "resizable", "animate", {
11804         stop: function( event ) {
11805                 var that = $( this ).resizable( "instance" ),
11806                         o = that.options,
11807                         pr = that._proportionallyResizeElements,
11808                         ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
11809                         soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
11810                         soffsetw = ista ? 0 : that.sizeDiff.width,
11811                         style = {
11812                                 width: ( that.size.width - soffsetw ),
11813                                 height: ( that.size.height - soffseth )
11814                         },
11815                         left = ( parseFloat( that.element.css( "left" ) ) +
11816                                 ( that.position.left - that.originalPosition.left ) ) || null,
11817                         top = ( parseFloat( that.element.css( "top" ) ) +
11818                                 ( that.position.top - that.originalPosition.top ) ) || null;
11820                 that.element.animate(
11821                         $.extend( style, top && left ? { top: top, left: left } : {} ), {
11822                                 duration: o.animateDuration,
11823                                 easing: o.animateEasing,
11824                                 step: function() {
11826                                         var data = {
11827                                                 width: parseFloat( that.element.css( "width" ) ),
11828                                                 height: parseFloat( that.element.css( "height" ) ),
11829                                                 top: parseFloat( that.element.css( "top" ) ),
11830                                                 left: parseFloat( that.element.css( "left" ) )
11831                                         };
11833                                         if ( pr && pr.length ) {
11834                                                 $( pr[ 0 ] ).css( { width: data.width, height: data.height } );
11835                                         }
11837                                         // Propagating resize, and updating values for each animation step
11838                                         that._updateCache( data );
11839                                         that._propagate( "resize", event );
11841                                 }
11842                         }
11843                 );
11844         }
11846 } );
11848 $.ui.plugin.add( "resizable", "containment", {
11850         start: function() {
11851                 var element, p, co, ch, cw, width, height,
11852                         that = $( this ).resizable( "instance" ),
11853                         o = that.options,
11854                         el = that.element,
11855                         oc = o.containment,
11856                         ce = ( oc instanceof $ ) ?
11857                                 oc.get( 0 ) :
11858                                 ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
11860                 if ( !ce ) {
11861                         return;
11862                 }
11864                 that.containerElement = $( ce );
11866                 if ( /document/.test( oc ) || oc === document ) {
11867                         that.containerOffset = {
11868                                 left: 0,
11869                                 top: 0
11870                         };
11871                         that.containerPosition = {
11872                                 left: 0,
11873                                 top: 0
11874                         };
11876                         that.parentData = {
11877                                 element: $( document ),
11878                                 left: 0,
11879                                 top: 0,
11880                                 width: $( document ).width(),
11881                                 height: $( document ).height() || document.body.parentNode.scrollHeight
11882                         };
11883                 } else {
11884                         element = $( ce );
11885                         p = [];
11886                         $( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
11887                                 p[ i ] = that._num( element.css( "padding" + name ) );
11888                         } );
11890                         that.containerOffset = element.offset();
11891                         that.containerPosition = element.position();
11892                         that.containerSize = {
11893                                 height: ( element.innerHeight() - p[ 3 ] ),
11894                                 width: ( element.innerWidth() - p[ 1 ] )
11895                         };
11897                         co = that.containerOffset;
11898                         ch = that.containerSize.height;
11899                         cw = that.containerSize.width;
11900                         width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw );
11901                         height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch );
11903                         that.parentData = {
11904                                 element: ce,
11905                                 left: co.left,
11906                                 top: co.top,
11907                                 width: width,
11908                                 height: height
11909                         };
11910                 }
11911         },
11913         resize: function( event ) {
11914                 var woset, hoset, isParent, isOffsetRelative,
11915                         that = $( this ).resizable( "instance" ),
11916                         o = that.options,
11917                         co = that.containerOffset,
11918                         cp = that.position,
11919                         pRatio = that._aspectRatio || event.shiftKey,
11920                         cop = {
11921                                 top: 0,
11922                                 left: 0
11923                         },
11924                         ce = that.containerElement,
11925                         continueResize = true;
11927                 if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
11928                         cop = co;
11929                 }
11931                 if ( cp.left < ( that._helper ? co.left : 0 ) ) {
11932                         that.size.width = that.size.width +
11933                                 ( that._helper ?
11934                                         ( that.position.left - co.left ) :
11935                                         ( that.position.left - cop.left ) );
11937                         if ( pRatio ) {
11938                                 that.size.height = that.size.width / that.aspectRatio;
11939                                 continueResize = false;
11940                         }
11941                         that.position.left = o.helper ? co.left : 0;
11942                 }
11944                 if ( cp.top < ( that._helper ? co.top : 0 ) ) {
11945                         that.size.height = that.size.height +
11946                                 ( that._helper ?
11947                                         ( that.position.top - co.top ) :
11948                                         that.position.top );
11950                         if ( pRatio ) {
11951                                 that.size.width = that.size.height * that.aspectRatio;
11952                                 continueResize = false;
11953                         }
11954                         that.position.top = that._helper ? co.top : 0;
11955                 }
11957                 isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
11958                 isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
11960                 if ( isParent && isOffsetRelative ) {
11961                         that.offset.left = that.parentData.left + that.position.left;
11962                         that.offset.top = that.parentData.top + that.position.top;
11963                 } else {
11964                         that.offset.left = that.element.offset().left;
11965                         that.offset.top = that.element.offset().top;
11966                 }
11968                 woset = Math.abs( that.sizeDiff.width +
11969                         ( that._helper ?
11970                                 that.offset.left - cop.left :
11971                                 ( that.offset.left - co.left ) ) );
11973                 hoset = Math.abs( that.sizeDiff.height +
11974                         ( that._helper ?
11975                                 that.offset.top - cop.top :
11976                                 ( that.offset.top - co.top ) ) );
11978                 if ( woset + that.size.width >= that.parentData.width ) {
11979                         that.size.width = that.parentData.width - woset;
11980                         if ( pRatio ) {
11981                                 that.size.height = that.size.width / that.aspectRatio;
11982                                 continueResize = false;
11983                         }
11984                 }
11986                 if ( hoset + that.size.height >= that.parentData.height ) {
11987                         that.size.height = that.parentData.height - hoset;
11988                         if ( pRatio ) {
11989                                 that.size.width = that.size.height * that.aspectRatio;
11990                                 continueResize = false;
11991                         }
11992                 }
11994                 if ( !continueResize ) {
11995                         that.position.left = that.prevPosition.left;
11996                         that.position.top = that.prevPosition.top;
11997                         that.size.width = that.prevSize.width;
11998                         that.size.height = that.prevSize.height;
11999                 }
12000         },
12002         stop: function() {
12003                 var that = $( this ).resizable( "instance" ),
12004                         o = that.options,
12005                         co = that.containerOffset,
12006                         cop = that.containerPosition,
12007                         ce = that.containerElement,
12008                         helper = $( that.helper ),
12009                         ho = helper.offset(),
12010                         w = helper.outerWidth() - that.sizeDiff.width,
12011                         h = helper.outerHeight() - that.sizeDiff.height;
12013                 if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
12014                         $( this ).css( {
12015                                 left: ho.left - cop.left - co.left,
12016                                 width: w,
12017                                 height: h
12018                         } );
12019                 }
12021                 if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
12022                         $( this ).css( {
12023                                 left: ho.left - cop.left - co.left,
12024                                 width: w,
12025                                 height: h
12026                         } );
12027                 }
12028         }
12029 } );
12031 $.ui.plugin.add( "resizable", "alsoResize", {
12033         start: function() {
12034                 var that = $( this ).resizable( "instance" ),
12035                         o = that.options;
12037                 $( o.alsoResize ).each( function() {
12038                         var el = $( this );
12039                         el.data( "ui-resizable-alsoresize", {
12040                                 width: parseFloat( el.width() ), height: parseFloat( el.height() ),
12041                                 left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
12042                         } );
12043                 } );
12044         },
12046         resize: function( event, ui ) {
12047                 var that = $( this ).resizable( "instance" ),
12048                         o = that.options,
12049                         os = that.originalSize,
12050                         op = that.originalPosition,
12051                         delta = {
12052                                 height: ( that.size.height - os.height ) || 0,
12053                                 width: ( that.size.width - os.width ) || 0,
12054                                 top: ( that.position.top - op.top ) || 0,
12055                                 left: ( that.position.left - op.left ) || 0
12056                         };
12058                         $( o.alsoResize ).each( function() {
12059                                 var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
12060                                         css = el.parents( ui.originalElement[ 0 ] ).length ?
12061                                                         [ "width", "height" ] :
12062                                                         [ "width", "height", "top", "left" ];
12064                                 $.each( css, function( i, prop ) {
12065                                         var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
12066                                         if ( sum && sum >= 0 ) {
12067                                                 style[ prop ] = sum || null;
12068                                         }
12069                                 } );
12071                                 el.css( style );
12072                         } );
12073         },
12075         stop: function() {
12076                 $( this ).removeData( "ui-resizable-alsoresize" );
12077         }
12078 } );
12080 $.ui.plugin.add( "resizable", "ghost", {
12082         start: function() {
12084                 var that = $( this ).resizable( "instance" ), cs = that.size;
12086                 that.ghost = that.originalElement.clone();
12087                 that.ghost.css( {
12088                         opacity: 0.25,
12089                         display: "block",
12090                         position: "relative",
12091                         height: cs.height,
12092                         width: cs.width,
12093                         margin: 0,
12094                         left: 0,
12095                         top: 0
12096                 } );
12098                 that._addClass( that.ghost, "ui-resizable-ghost" );
12100                 // DEPRECATED
12101                 // TODO: remove after 1.12
12102                 if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) {
12104                         // Ghost option
12105                         that.ghost.addClass( this.options.ghost );
12106                 }
12108                 that.ghost.appendTo( that.helper );
12110         },
12112         resize: function() {
12113                 var that = $( this ).resizable( "instance" );
12114                 if ( that.ghost ) {
12115                         that.ghost.css( {
12116                                 position: "relative",
12117                                 height: that.size.height,
12118                                 width: that.size.width
12119                         } );
12120                 }
12121         },
12123         stop: function() {
12124                 var that = $( this ).resizable( "instance" );
12125                 if ( that.ghost && that.helper ) {
12126                         that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
12127                 }
12128         }
12130 } );
12132 $.ui.plugin.add( "resizable", "grid", {
12134         resize: function() {
12135                 var outerDimensions,
12136                         that = $( this ).resizable( "instance" ),
12137                         o = that.options,
12138                         cs = that.size,
12139                         os = that.originalSize,
12140                         op = that.originalPosition,
12141                         a = that.axis,
12142                         grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
12143                         gridX = ( grid[ 0 ] || 1 ),
12144                         gridY = ( grid[ 1 ] || 1 ),
12145                         ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
12146                         oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
12147                         newWidth = os.width + ox,
12148                         newHeight = os.height + oy,
12149                         isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
12150                         isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
12151                         isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
12152                         isMinHeight = o.minHeight && ( o.minHeight > newHeight );
12154                 o.grid = grid;
12156                 if ( isMinWidth ) {
12157                         newWidth += gridX;
12158                 }
12159                 if ( isMinHeight ) {
12160                         newHeight += gridY;
12161                 }
12162                 if ( isMaxWidth ) {
12163                         newWidth -= gridX;
12164                 }
12165                 if ( isMaxHeight ) {
12166                         newHeight -= gridY;
12167                 }
12169                 if ( /^(se|s|e)$/.test( a ) ) {
12170                         that.size.width = newWidth;
12171                         that.size.height = newHeight;
12172                 } else if ( /^(ne)$/.test( a ) ) {
12173                         that.size.width = newWidth;
12174                         that.size.height = newHeight;
12175                         that.position.top = op.top - oy;
12176                 } else if ( /^(sw)$/.test( a ) ) {
12177                         that.size.width = newWidth;
12178                         that.size.height = newHeight;
12179                         that.position.left = op.left - ox;
12180                 } else {
12181                         if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
12182                                 outerDimensions = that._getPaddingPlusBorderDimensions( this );
12183                         }
12185                         if ( newHeight - gridY > 0 ) {
12186                                 that.size.height = newHeight;
12187                                 that.position.top = op.top - oy;
12188                         } else {
12189                                 newHeight = gridY - outerDimensions.height;
12190                                 that.size.height = newHeight;
12191                                 that.position.top = op.top + os.height - newHeight;
12192                         }
12193                         if ( newWidth - gridX > 0 ) {
12194                                 that.size.width = newWidth;
12195                                 that.position.left = op.left - ox;
12196                         } else {
12197                                 newWidth = gridX - outerDimensions.width;
12198                                 that.size.width = newWidth;
12199                                 that.position.left = op.left + os.width - newWidth;
12200                         }
12201                 }
12202         }
12204 } );
12206 var widgetsResizable = $.ui.resizable;
12210  * jQuery UI Dialog 1.13.0
12211  * http://jqueryui.com
12213  * Copyright jQuery Foundation and other contributors
12214  * Released under the MIT license.
12215  * http://jquery.org/license
12216  */
12218 //>>label: Dialog
12219 //>>group: Widgets
12220 //>>description: Displays customizable dialog windows.
12221 //>>docs: http://api.jqueryui.com/dialog/
12222 //>>demos: http://jqueryui.com/dialog/
12223 //>>css.structure: ../../themes/base/core.css
12224 //>>css.structure: ../../themes/base/dialog.css
12225 //>>css.theme: ../../themes/base/theme.css
12228 $.widget( "ui.dialog", {
12229         version: "1.13.0",
12230         options: {
12231                 appendTo: "body",
12232                 autoOpen: true,
12233                 buttons: [],
12234                 classes: {
12235                         "ui-dialog": "ui-corner-all",
12236                         "ui-dialog-titlebar": "ui-corner-all"
12237                 },
12238                 closeOnEscape: true,
12239                 closeText: "Close",
12240                 draggable: true,
12241                 hide: null,
12242                 height: "auto",
12243                 maxHeight: null,
12244                 maxWidth: null,
12245                 minHeight: 150,
12246                 minWidth: 150,
12247                 modal: false,
12248                 position: {
12249                         my: "center",
12250                         at: "center",
12251                         of: window,
12252                         collision: "fit",
12254                         // Ensure the titlebar is always visible
12255                         using: function( pos ) {
12256                                 var topOffset = $( this ).css( pos ).offset().top;
12257                                 if ( topOffset < 0 ) {
12258                                         $( this ).css( "top", pos.top - topOffset );
12259                                 }
12260                         }
12261                 },
12262                 resizable: true,
12263                 show: null,
12264                 title: null,
12265                 width: 300,
12267                 // Callbacks
12268                 beforeClose: null,
12269                 close: null,
12270                 drag: null,
12271                 dragStart: null,
12272                 dragStop: null,
12273                 focus: null,
12274                 open: null,
12275                 resize: null,
12276                 resizeStart: null,
12277                 resizeStop: null
12278         },
12280         sizeRelatedOptions: {
12281                 buttons: true,
12282                 height: true,
12283                 maxHeight: true,
12284                 maxWidth: true,
12285                 minHeight: true,
12286                 minWidth: true,
12287                 width: true
12288         },
12290         resizableRelatedOptions: {
12291                 maxHeight: true,
12292                 maxWidth: true,
12293                 minHeight: true,
12294                 minWidth: true
12295         },
12297         _create: function() {
12298                 this.originalCss = {
12299                         display: this.element[ 0 ].style.display,
12300                         width: this.element[ 0 ].style.width,
12301                         minHeight: this.element[ 0 ].style.minHeight,
12302                         maxHeight: this.element[ 0 ].style.maxHeight,
12303                         height: this.element[ 0 ].style.height
12304                 };
12305                 this.originalPosition = {
12306                         parent: this.element.parent(),
12307                         index: this.element.parent().children().index( this.element )
12308                 };
12309                 this.originalTitle = this.element.attr( "title" );
12310                 if ( this.options.title == null && this.originalTitle != null ) {
12311                         this.options.title = this.originalTitle;
12312                 }
12314                 // Dialogs can't be disabled
12315                 if ( this.options.disabled ) {
12316                         this.options.disabled = false;
12317                 }
12319                 this._createWrapper();
12321                 this.element
12322                         .show()
12323                         .removeAttr( "title" )
12324                         .appendTo( this.uiDialog );
12326                 this._addClass( "ui-dialog-content", "ui-widget-content" );
12328                 this._createTitlebar();
12329                 this._createButtonPane();
12331                 if ( this.options.draggable && $.fn.draggable ) {
12332                         this._makeDraggable();
12333                 }
12334                 if ( this.options.resizable && $.fn.resizable ) {
12335                         this._makeResizable();
12336                 }
12338                 this._isOpen = false;
12340                 this._trackFocus();
12341         },
12343         _init: function() {
12344                 if ( this.options.autoOpen ) {
12345                         this.open();
12346                 }
12347         },
12349         _appendTo: function() {
12350                 var element = this.options.appendTo;
12351                 if ( element && ( element.jquery || element.nodeType ) ) {
12352                         return $( element );
12353                 }
12354                 return this.document.find( element || "body" ).eq( 0 );
12355         },
12357         _destroy: function() {
12358                 var next,
12359                         originalPosition = this.originalPosition;
12361                 this._untrackInstance();
12362                 this._destroyOverlay();
12364                 this.element
12365                         .removeUniqueId()
12366                         .css( this.originalCss )
12368                         // Without detaching first, the following becomes really slow
12369                         .detach();
12371                 this.uiDialog.remove();
12373                 if ( this.originalTitle ) {
12374                         this.element.attr( "title", this.originalTitle );
12375                 }
12377                 next = originalPosition.parent.children().eq( originalPosition.index );
12379                 // Don't try to place the dialog next to itself (#8613)
12380                 if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
12381                         next.before( this.element );
12382                 } else {
12383                         originalPosition.parent.append( this.element );
12384                 }
12385         },
12387         widget: function() {
12388                 return this.uiDialog;
12389         },
12391         disable: $.noop,
12392         enable: $.noop,
12394         close: function( event ) {
12395                 var that = this;
12397                 if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
12398                         return;
12399                 }
12401                 this._isOpen = false;
12402                 this._focusedElement = null;
12403                 this._destroyOverlay();
12404                 this._untrackInstance();
12406                 if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
12408                         // Hiding a focused element doesn't trigger blur in WebKit
12409                         // so in case we have nothing to focus on, explicitly blur the active element
12410                         // https://bugs.webkit.org/show_bug.cgi?id=47182
12411                         $.ui.safeBlur( $.ui.safeActiveElement( this.document[ 0 ] ) );
12412                 }
12414                 this._hide( this.uiDialog, this.options.hide, function() {
12415                         that._trigger( "close", event );
12416                 } );
12417         },
12419         isOpen: function() {
12420                 return this._isOpen;
12421         },
12423         moveToTop: function() {
12424                 this._moveToTop();
12425         },
12427         _moveToTop: function( event, silent ) {
12428                 var moved = false,
12429                         zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
12430                                 return +$( this ).css( "z-index" );
12431                         } ).get(),
12432                         zIndexMax = Math.max.apply( null, zIndices );
12434                 if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
12435                         this.uiDialog.css( "z-index", zIndexMax + 1 );
12436                         moved = true;
12437                 }
12439                 if ( moved && !silent ) {
12440                         this._trigger( "focus", event );
12441                 }
12442                 return moved;
12443         },
12445         open: function() {
12446                 var that = this;
12447                 if ( this._isOpen ) {
12448                         if ( this._moveToTop() ) {
12449                                 this._focusTabbable();
12450                         }
12451                         return;
12452                 }
12454                 this._isOpen = true;
12455                 this.opener = $( $.ui.safeActiveElement( this.document[ 0 ] ) );
12457                 this._size();
12458                 this._position();
12459                 this._createOverlay();
12460                 this._moveToTop( null, true );
12462                 // Ensure the overlay is moved to the top with the dialog, but only when
12463                 // opening. The overlay shouldn't move after the dialog is open so that
12464                 // modeless dialogs opened after the modal dialog stack properly.
12465                 if ( this.overlay ) {
12466                         this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
12467                 }
12469                 this._show( this.uiDialog, this.options.show, function() {
12470                         that._focusTabbable();
12471                         that._trigger( "focus" );
12472                 } );
12474                 // Track the dialog immediately upon opening in case a focus event
12475                 // somehow occurs outside of the dialog before an element inside the
12476                 // dialog is focused (#10152)
12477                 this._makeFocusTarget();
12479                 this._trigger( "open" );
12480         },
12482         _focusTabbable: function() {
12484                 // Set focus to the first match:
12485                 // 1. An element that was focused previously
12486                 // 2. First element inside the dialog matching [autofocus]
12487                 // 3. Tabbable element inside the content element
12488                 // 4. Tabbable element inside the buttonpane
12489                 // 5. The close button
12490                 // 6. The dialog itself
12491                 var hasFocus = this._focusedElement;
12492                 if ( !hasFocus ) {
12493                         hasFocus = this.element.find( "[autofocus]" );
12494                 }
12495                 if ( !hasFocus.length ) {
12496                         hasFocus = this.element.find( ":tabbable" );
12497                 }
12498                 if ( !hasFocus.length ) {
12499                         hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
12500                 }
12501                 if ( !hasFocus.length ) {
12502                         hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
12503                 }
12504                 if ( !hasFocus.length ) {
12505                         hasFocus = this.uiDialog;
12506                 }
12507                 hasFocus.eq( 0 ).trigger( "focus" );
12508         },
12510         _restoreTabbableFocus: function() {
12511                 var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
12512                         isActive = this.uiDialog[ 0 ] === activeElement ||
12513                                 $.contains( this.uiDialog[ 0 ], activeElement );
12514                 if ( !isActive ) {
12515                         this._focusTabbable();
12516                 }
12517         },
12519         _keepFocus: function( event ) {
12520                 event.preventDefault();
12521                 this._restoreTabbableFocus();
12523                 // support: IE
12524                 // IE <= 8 doesn't prevent moving focus even with event.preventDefault()
12525                 // so we check again later
12526                 this._delay( this._restoreTabbableFocus );
12527         },
12529         _createWrapper: function() {
12530                 this.uiDialog = $( "<div>" )
12531                         .hide()
12532                         .attr( {
12534                                 // Setting tabIndex makes the div focusable
12535                                 tabIndex: -1,
12536                                 role: "dialog"
12537                         } )
12538                         .appendTo( this._appendTo() );
12540                 this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
12541                 this._on( this.uiDialog, {
12542                         keydown: function( event ) {
12543                                 if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
12544                                                 event.keyCode === $.ui.keyCode.ESCAPE ) {
12545                                         event.preventDefault();
12546                                         this.close( event );
12547                                         return;
12548                                 }
12550                                 // Prevent tabbing out of dialogs
12551                                 if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
12552                                         return;
12553                                 }
12554                                 var tabbables = this.uiDialog.find( ":tabbable" ),
12555                                         first = tabbables.first(),
12556                                         last = tabbables.last();
12558                                 if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
12559                                                 !event.shiftKey ) {
12560                                         this._delay( function() {
12561                                                 first.trigger( "focus" );
12562                                         } );
12563                                         event.preventDefault();
12564                                 } else if ( ( event.target === first[ 0 ] ||
12565                                                 event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
12566                                         this._delay( function() {
12567                                                 last.trigger( "focus" );
12568                                         } );
12569                                         event.preventDefault();
12570                                 }
12571                         },
12572                         mousedown: function( event ) {
12573                                 if ( this._moveToTop( event ) ) {
12574                                         this._focusTabbable();
12575                                 }
12576                         }
12577                 } );
12579                 // We assume that any existing aria-describedby attribute means
12580                 // that the dialog content is marked up properly
12581                 // otherwise we brute force the content as the description
12582                 if ( !this.element.find( "[aria-describedby]" ).length ) {
12583                         this.uiDialog.attr( {
12584                                 "aria-describedby": this.element.uniqueId().attr( "id" )
12585                         } );
12586                 }
12587         },
12589         _createTitlebar: function() {
12590                 var uiDialogTitle;
12592                 this.uiDialogTitlebar = $( "<div>" );
12593                 this._addClass( this.uiDialogTitlebar,
12594                         "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
12595                 this._on( this.uiDialogTitlebar, {
12596                         mousedown: function( event ) {
12598                                 // Don't prevent click on close button (#8838)
12599                                 // Focusing a dialog that is partially scrolled out of view
12600                                 // causes the browser to scroll it into view, preventing the click event
12601                                 if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
12603                                         // Dialog isn't getting focus when dragging (#8063)
12604                                         this.uiDialog.trigger( "focus" );
12605                                 }
12606                         }
12607                 } );
12609                 // Support: IE
12610                 // Use type="button" to prevent enter keypresses in textboxes from closing the
12611                 // dialog in IE (#9312)
12612                 this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
12613                         .button( {
12614                                 label: $( "<a>" ).text( this.options.closeText ).html(),
12615                                 icon: "ui-icon-closethick",
12616                                 showLabel: false
12617                         } )
12618                         .appendTo( this.uiDialogTitlebar );
12620                 this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
12621                 this._on( this.uiDialogTitlebarClose, {
12622                         click: function( event ) {
12623                                 event.preventDefault();
12624                                 this.close( event );
12625                         }
12626                 } );
12628                 uiDialogTitle = $( "<span>" ).uniqueId().prependTo( this.uiDialogTitlebar );
12629                 this._addClass( uiDialogTitle, "ui-dialog-title" );
12630                 this._title( uiDialogTitle );
12632                 this.uiDialogTitlebar.prependTo( this.uiDialog );
12634                 this.uiDialog.attr( {
12635                         "aria-labelledby": uiDialogTitle.attr( "id" )
12636                 } );
12637         },
12639         _title: function( title ) {
12640                 if ( this.options.title ) {
12641                         title.text( this.options.title );
12642                 } else {
12643                         title.html( "&#160;" );
12644                 }
12645         },
12647         _createButtonPane: function() {
12648                 this.uiDialogButtonPane = $( "<div>" );
12649                 this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
12650                         "ui-widget-content ui-helper-clearfix" );
12652                 this.uiButtonSet = $( "<div>" )
12653                         .appendTo( this.uiDialogButtonPane );
12654                 this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
12656                 this._createButtons();
12657         },
12659         _createButtons: function() {
12660                 var that = this,
12661                         buttons = this.options.buttons;
12663                 // If we already have a button pane, remove it
12664                 this.uiDialogButtonPane.remove();
12665                 this.uiButtonSet.empty();
12667                 if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) {
12668                         this._removeClass( this.uiDialog, "ui-dialog-buttons" );
12669                         return;
12670                 }
12672                 $.each( buttons, function( name, props ) {
12673                         var click, buttonOptions;
12674                         props = typeof props === "function" ?
12675                                 { click: props, text: name } :
12676                                 props;
12678                         // Default to a non-submitting button
12679                         props = $.extend( { type: "button" }, props );
12681                         // Change the context for the click callback to be the main element
12682                         click = props.click;
12683                         buttonOptions = {
12684                                 icon: props.icon,
12685                                 iconPosition: props.iconPosition,
12686                                 showLabel: props.showLabel,
12688                                 // Deprecated options
12689                                 icons: props.icons,
12690                                 text: props.text
12691                         };
12693                         delete props.click;
12694                         delete props.icon;
12695                         delete props.iconPosition;
12696                         delete props.showLabel;
12698                         // Deprecated options
12699                         delete props.icons;
12700                         if ( typeof props.text === "boolean" ) {
12701                                 delete props.text;
12702                         }
12704                         $( "<button></button>", props )
12705                                 .button( buttonOptions )
12706                                 .appendTo( that.uiButtonSet )
12707                                 .on( "click", function() {
12708                                         click.apply( that.element[ 0 ], arguments );
12709                                 } );
12710                 } );
12711                 this._addClass( this.uiDialog, "ui-dialog-buttons" );
12712                 this.uiDialogButtonPane.appendTo( this.uiDialog );
12713         },
12715         _makeDraggable: function() {
12716                 var that = this,
12717                         options = this.options;
12719                 function filteredUi( ui ) {
12720                         return {
12721                                 position: ui.position,
12722                                 offset: ui.offset
12723                         };
12724                 }
12726                 this.uiDialog.draggable( {
12727                         cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
12728                         handle: ".ui-dialog-titlebar",
12729                         containment: "document",
12730                         start: function( event, ui ) {
12731                                 that._addClass( $( this ), "ui-dialog-dragging" );
12732                                 that._blockFrames();
12733                                 that._trigger( "dragStart", event, filteredUi( ui ) );
12734                         },
12735                         drag: function( event, ui ) {
12736                                 that._trigger( "drag", event, filteredUi( ui ) );
12737                         },
12738                         stop: function( event, ui ) {
12739                                 var left = ui.offset.left - that.document.scrollLeft(),
12740                                         top = ui.offset.top - that.document.scrollTop();
12742                                 options.position = {
12743                                         my: "left top",
12744                                         at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12745                                                 "top" + ( top >= 0 ? "+" : "" ) + top,
12746                                         of: that.window
12747                                 };
12748                                 that._removeClass( $( this ), "ui-dialog-dragging" );
12749                                 that._unblockFrames();
12750                                 that._trigger( "dragStop", event, filteredUi( ui ) );
12751                         }
12752                 } );
12753         },
12755         _makeResizable: function() {
12756                 var that = this,
12757                         options = this.options,
12758                         handles = options.resizable,
12760                         // .ui-resizable has position: relative defined in the stylesheet
12761                         // but dialogs have to use absolute or fixed positioning
12762                         position = this.uiDialog.css( "position" ),
12763                         resizeHandles = typeof handles === "string" ?
12764                                 handles :
12765                                 "n,e,s,w,se,sw,ne,nw";
12767                 function filteredUi( ui ) {
12768                         return {
12769                                 originalPosition: ui.originalPosition,
12770                                 originalSize: ui.originalSize,
12771                                 position: ui.position,
12772                                 size: ui.size
12773                         };
12774                 }
12776                 this.uiDialog.resizable( {
12777                         cancel: ".ui-dialog-content",
12778                         containment: "document",
12779                         alsoResize: this.element,
12780                         maxWidth: options.maxWidth,
12781                         maxHeight: options.maxHeight,
12782                         minWidth: options.minWidth,
12783                         minHeight: this._minHeight(),
12784                         handles: resizeHandles,
12785                         start: function( event, ui ) {
12786                                 that._addClass( $( this ), "ui-dialog-resizing" );
12787                                 that._blockFrames();
12788                                 that._trigger( "resizeStart", event, filteredUi( ui ) );
12789                         },
12790                         resize: function( event, ui ) {
12791                                 that._trigger( "resize", event, filteredUi( ui ) );
12792                         },
12793                         stop: function( event, ui ) {
12794                                 var offset = that.uiDialog.offset(),
12795                                         left = offset.left - that.document.scrollLeft(),
12796                                         top = offset.top - that.document.scrollTop();
12798                                 options.height = that.uiDialog.height();
12799                                 options.width = that.uiDialog.width();
12800                                 options.position = {
12801                                         my: "left top",
12802                                         at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12803                                                 "top" + ( top >= 0 ? "+" : "" ) + top,
12804                                         of: that.window
12805                                 };
12806                                 that._removeClass( $( this ), "ui-dialog-resizing" );
12807                                 that._unblockFrames();
12808                                 that._trigger( "resizeStop", event, filteredUi( ui ) );
12809                         }
12810                 } )
12811                         .css( "position", position );
12812         },
12814         _trackFocus: function() {
12815                 this._on( this.widget(), {
12816                         focusin: function( event ) {
12817                                 this._makeFocusTarget();
12818                                 this._focusedElement = $( event.target );
12819                         }
12820                 } );
12821         },
12823         _makeFocusTarget: function() {
12824                 this._untrackInstance();
12825                 this._trackingInstances().unshift( this );
12826         },
12828         _untrackInstance: function() {
12829                 var instances = this._trackingInstances(),
12830                         exists = $.inArray( this, instances );
12831                 if ( exists !== -1 ) {
12832                         instances.splice( exists, 1 );
12833                 }
12834         },
12836         _trackingInstances: function() {
12837                 var instances = this.document.data( "ui-dialog-instances" );
12838                 if ( !instances ) {
12839                         instances = [];
12840                         this.document.data( "ui-dialog-instances", instances );
12841                 }
12842                 return instances;
12843         },
12845         _minHeight: function() {
12846                 var options = this.options;
12848                 return options.height === "auto" ?
12849                         options.minHeight :
12850                         Math.min( options.minHeight, options.height );
12851         },
12853         _position: function() {
12855                 // Need to show the dialog to get the actual offset in the position plugin
12856                 var isVisible = this.uiDialog.is( ":visible" );
12857                 if ( !isVisible ) {
12858                         this.uiDialog.show();
12859                 }
12860                 this.uiDialog.position( this.options.position );
12861                 if ( !isVisible ) {
12862                         this.uiDialog.hide();
12863                 }
12864         },
12866         _setOptions: function( options ) {
12867                 var that = this,
12868                         resize = false,
12869                         resizableOptions = {};
12871                 $.each( options, function( key, value ) {
12872                         that._setOption( key, value );
12874                         if ( key in that.sizeRelatedOptions ) {
12875                                 resize = true;
12876                         }
12877                         if ( key in that.resizableRelatedOptions ) {
12878                                 resizableOptions[ key ] = value;
12879                         }
12880                 } );
12882                 if ( resize ) {
12883                         this._size();
12884                         this._position();
12885                 }
12886                 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12887                         this.uiDialog.resizable( "option", resizableOptions );
12888                 }
12889         },
12891         _setOption: function( key, value ) {
12892                 var isDraggable, isResizable,
12893                         uiDialog = this.uiDialog;
12895                 if ( key === "disabled" ) {
12896                         return;
12897                 }
12899                 this._super( key, value );
12901                 if ( key === "appendTo" ) {
12902                         this.uiDialog.appendTo( this._appendTo() );
12903                 }
12905                 if ( key === "buttons" ) {
12906                         this._createButtons();
12907                 }
12909                 if ( key === "closeText" ) {
12910                         this.uiDialogTitlebarClose.button( {
12912                                 // Ensure that we always pass a string
12913                                 label: $( "<a>" ).text( "" + this.options.closeText ).html()
12914                         } );
12915                 }
12917                 if ( key === "draggable" ) {
12918                         isDraggable = uiDialog.is( ":data(ui-draggable)" );
12919                         if ( isDraggable && !value ) {
12920                                 uiDialog.draggable( "destroy" );
12921                         }
12923                         if ( !isDraggable && value ) {
12924                                 this._makeDraggable();
12925                         }
12926                 }
12928                 if ( key === "position" ) {
12929                         this._position();
12930                 }
12932                 if ( key === "resizable" ) {
12934                         // currently resizable, becoming non-resizable
12935                         isResizable = uiDialog.is( ":data(ui-resizable)" );
12936                         if ( isResizable && !value ) {
12937                                 uiDialog.resizable( "destroy" );
12938                         }
12940                         // Currently resizable, changing handles
12941                         if ( isResizable && typeof value === "string" ) {
12942                                 uiDialog.resizable( "option", "handles", value );
12943                         }
12945                         // Currently non-resizable, becoming resizable
12946                         if ( !isResizable && value !== false ) {
12947                                 this._makeResizable();
12948                         }
12949                 }
12951                 if ( key === "title" ) {
12952                         this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
12953                 }
12954         },
12956         _size: function() {
12958                 // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
12959                 // divs will both have width and height set, so we need to reset them
12960                 var nonContentHeight, minContentHeight, maxContentHeight,
12961                         options = this.options;
12963                 // Reset content sizing
12964                 this.element.show().css( {
12965                         width: "auto",
12966                         minHeight: 0,
12967                         maxHeight: "none",
12968                         height: 0
12969                 } );
12971                 if ( options.minWidth > options.width ) {
12972                         options.width = options.minWidth;
12973                 }
12975                 // Reset wrapper sizing
12976                 // determine the height of all the non-content elements
12977                 nonContentHeight = this.uiDialog.css( {
12978                         height: "auto",
12979                         width: options.width
12980                 } )
12981                         .outerHeight();
12982                 minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
12983                 maxContentHeight = typeof options.maxHeight === "number" ?
12984                         Math.max( 0, options.maxHeight - nonContentHeight ) :
12985                         "none";
12987                 if ( options.height === "auto" ) {
12988                         this.element.css( {
12989                                 minHeight: minContentHeight,
12990                                 maxHeight: maxContentHeight,
12991                                 height: "auto"
12992                         } );
12993                 } else {
12994                         this.element.height( Math.max( 0, options.height - nonContentHeight ) );
12995                 }
12997                 if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12998                         this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
12999                 }
13000         },
13002         _blockFrames: function() {
13003                 this.iframeBlocks = this.document.find( "iframe" ).map( function() {
13004                         var iframe = $( this );
13006                         return $( "<div>" )
13007                                 .css( {
13008                                         position: "absolute",
13009                                         width: iframe.outerWidth(),
13010                                         height: iframe.outerHeight()
13011                                 } )
13012                                 .appendTo( iframe.parent() )
13013                                 .offset( iframe.offset() )[ 0 ];
13014                 } );
13015         },
13017         _unblockFrames: function() {
13018                 if ( this.iframeBlocks ) {
13019                         this.iframeBlocks.remove();
13020                         delete this.iframeBlocks;
13021                 }
13022         },
13024         _allowInteraction: function( event ) {
13025                 if ( $( event.target ).closest( ".ui-dialog" ).length ) {
13026                         return true;
13027                 }
13029                 // TODO: Remove hack when datepicker implements
13030                 // the .ui-front logic (#8989)
13031                 return !!$( event.target ).closest( ".ui-datepicker" ).length;
13032         },
13034         _createOverlay: function() {
13035                 if ( !this.options.modal ) {
13036                         return;
13037                 }
13039                 var jqMinor = $.fn.jquery.substring( 0, 4 );
13041                 // We use a delay in case the overlay is created from an
13042                 // event that we're going to be cancelling (#2804)
13043                 var isOpening = true;
13044                 this._delay( function() {
13045                         isOpening = false;
13046                 } );
13048                 if ( !this.document.data( "ui-dialog-overlays" ) ) {
13050                         // Prevent use of anchors and inputs
13051                         // This doesn't use `_on()` because it is a shared event handler
13052                         // across all open modal dialogs.
13053                         this.document.on( "focusin.ui-dialog", function( event ) {
13054                                 if ( isOpening ) {
13055                                         return;
13056                                 }
13058                                 var instance = this._trackingInstances()[ 0 ];
13059                                 if ( !instance._allowInteraction( event ) ) {
13060                                         event.preventDefault();
13061                                         instance._focusTabbable();
13063                                         // Support: jQuery >=3.4 <3.6 only
13064                                         // Focus re-triggering in jQuery 3.4/3.5 makes the original element
13065                                         // have its focus event propagated last, breaking the re-targeting.
13066                                         // Trigger focus in a delay in addition if needed to avoid the issue
13067                                         // See https://github.com/jquery/jquery/issues/4382
13068                                         if ( jqMinor === "3.4." || jqMinor === "3.5." ) {
13069                                                 instance._delay( instance._restoreTabbableFocus );
13070                                         }
13071                                 }
13072                         }.bind( this ) );
13073                 }
13075                 this.overlay = $( "<div>" )
13076                         .appendTo( this._appendTo() );
13078                 this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
13079                 this._on( this.overlay, {
13080                         mousedown: "_keepFocus"
13081                 } );
13082                 this.document.data( "ui-dialog-overlays",
13083                         ( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
13084         },
13086         _destroyOverlay: function() {
13087                 if ( !this.options.modal ) {
13088                         return;
13089                 }
13091                 if ( this.overlay ) {
13092                         var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
13094                         if ( !overlays ) {
13095                                 this.document.off( "focusin.ui-dialog" );
13096                                 this.document.removeData( "ui-dialog-overlays" );
13097                         } else {
13098                                 this.document.data( "ui-dialog-overlays", overlays );
13099                         }
13101                         this.overlay.remove();
13102                         this.overlay = null;
13103                 }
13104         }
13105 } );
13107 // DEPRECATED
13108 // TODO: switch return back to widget declaration at top of file when this is removed
13109 if ( $.uiBackCompat !== false ) {
13111         // Backcompat for dialogClass option
13112         $.widget( "ui.dialog", $.ui.dialog, {
13113                 options: {
13114                         dialogClass: ""
13115                 },
13116                 _createWrapper: function() {
13117                         this._super();
13118                         this.uiDialog.addClass( this.options.dialogClass );
13119                 },
13120                 _setOption: function( key, value ) {
13121                         if ( key === "dialogClass" ) {
13122                                 this.uiDialog
13123                                         .removeClass( this.options.dialogClass )
13124                                         .addClass( value );
13125                         }
13126                         this._superApply( arguments );
13127                 }
13128         } );
13131 var widgetsDialog = $.ui.dialog;
13135  * jQuery UI Droppable 1.13.0
13136  * http://jqueryui.com
13138  * Copyright jQuery Foundation and other contributors
13139  * Released under the MIT license.
13140  * http://jquery.org/license
13141  */
13143 //>>label: Droppable
13144 //>>group: Interactions
13145 //>>description: Enables drop targets for draggable elements.
13146 //>>docs: http://api.jqueryui.com/droppable/
13147 //>>demos: http://jqueryui.com/droppable/
13150 $.widget( "ui.droppable", {
13151         version: "1.13.0",
13152         widgetEventPrefix: "drop",
13153         options: {
13154                 accept: "*",
13155                 addClasses: true,
13156                 greedy: false,
13157                 scope: "default",
13158                 tolerance: "intersect",
13160                 // Callbacks
13161                 activate: null,
13162                 deactivate: null,
13163                 drop: null,
13164                 out: null,
13165                 over: null
13166         },
13167         _create: function() {
13169                 var proportions,
13170                         o = this.options,
13171                         accept = o.accept;
13173                 this.isover = false;
13174                 this.isout = true;
13176                 this.accept = typeof accept === "function" ? accept : function( d ) {
13177                         return d.is( accept );
13178                 };
13180                 this.proportions = function( /* valueToWrite */ ) {
13181                         if ( arguments.length ) {
13183                                 // Store the droppable's proportions
13184                                 proportions = arguments[ 0 ];
13185                         } else {
13187                                 // Retrieve or derive the droppable's proportions
13188                                 return proportions ?
13189                                         proportions :
13190                                         proportions = {
13191                                                 width: this.element[ 0 ].offsetWidth,
13192                                                 height: this.element[ 0 ].offsetHeight
13193                                         };
13194                         }
13195                 };
13197                 this._addToManager( o.scope );
13199                 if ( o.addClasses ) {
13200                         this._addClass( "ui-droppable" );
13201                 }
13203         },
13205         _addToManager: function( scope ) {
13207                 // Add the reference and positions to the manager
13208                 $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
13209                 $.ui.ddmanager.droppables[ scope ].push( this );
13210         },
13212         _splice: function( drop ) {
13213                 var i = 0;
13214                 for ( ; i < drop.length; i++ ) {
13215                         if ( drop[ i ] === this ) {
13216                                 drop.splice( i, 1 );
13217                         }
13218                 }
13219         },
13221         _destroy: function() {
13222                 var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13224                 this._splice( drop );
13225         },
13227         _setOption: function( key, value ) {
13229                 if ( key === "accept" ) {
13230                         this.accept = typeof value === "function" ? value : function( d ) {
13231                                 return d.is( value );
13232                         };
13233                 } else if ( key === "scope" ) {
13234                         var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13236                         this._splice( drop );
13237                         this._addToManager( value );
13238                 }
13240                 this._super( key, value );
13241         },
13243         _activate: function( event ) {
13244                 var draggable = $.ui.ddmanager.current;
13246                 this._addActiveClass();
13247                 if ( draggable ) {
13248                         this._trigger( "activate", event, this.ui( draggable ) );
13249                 }
13250         },
13252         _deactivate: function( event ) {
13253                 var draggable = $.ui.ddmanager.current;
13255                 this._removeActiveClass();
13256                 if ( draggable ) {
13257                         this._trigger( "deactivate", event, this.ui( draggable ) );
13258                 }
13259         },
13261         _over: function( event ) {
13263                 var draggable = $.ui.ddmanager.current;
13265                 // Bail if draggable and droppable are same element
13266                 if ( !draggable || ( draggable.currentItem ||
13267                                 draggable.element )[ 0 ] === this.element[ 0 ] ) {
13268                         return;
13269                 }
13271                 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13272                                 draggable.element ) ) ) {
13273                         this._addHoverClass();
13274                         this._trigger( "over", event, this.ui( draggable ) );
13275                 }
13277         },
13279         _out: function( event ) {
13281                 var draggable = $.ui.ddmanager.current;
13283                 // Bail if draggable and droppable are same element
13284                 if ( !draggable || ( draggable.currentItem ||
13285                                 draggable.element )[ 0 ] === this.element[ 0 ] ) {
13286                         return;
13287                 }
13289                 if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13290                                 draggable.element ) ) ) {
13291                         this._removeHoverClass();
13292                         this._trigger( "out", event, this.ui( draggable ) );
13293                 }
13295         },
13297         _drop: function( event, custom ) {
13299                 var draggable = custom || $.ui.ddmanager.current,
13300                         childrenIntersection = false;
13302                 // Bail if draggable and droppable are same element
13303                 if ( !draggable || ( draggable.currentItem ||
13304                                 draggable.element )[ 0 ] === this.element[ 0 ] ) {
13305                         return false;
13306                 }
13308                 this.element
13309                         .find( ":data(ui-droppable)" )
13310                         .not( ".ui-draggable-dragging" )
13311                         .each( function() {
13312                                 var inst = $( this ).droppable( "instance" );
13313                                 if (
13314                                         inst.options.greedy &&
13315                                         !inst.options.disabled &&
13316                                         inst.options.scope === draggable.options.scope &&
13317                                         inst.accept.call(
13318                                                 inst.element[ 0 ], ( draggable.currentItem || draggable.element )
13319                                         ) &&
13320                                         $.ui.intersect(
13321                                                 draggable,
13322                                                 $.extend( inst, { offset: inst.element.offset() } ),
13323                                                 inst.options.tolerance, event
13324                                         )
13325                                 ) {
13326                                         childrenIntersection = true;
13327                                         return false;
13328                                 }
13329                         } );
13330                 if ( childrenIntersection ) {
13331                         return false;
13332                 }
13334                 if ( this.accept.call( this.element[ 0 ],
13335                                 ( draggable.currentItem || draggable.element ) ) ) {
13336                         this._removeActiveClass();
13337                         this._removeHoverClass();
13339                         this._trigger( "drop", event, this.ui( draggable ) );
13340                         return this.element;
13341                 }
13343                 return false;
13345         },
13347         ui: function( c ) {
13348                 return {
13349                         draggable: ( c.currentItem || c.element ),
13350                         helper: c.helper,
13351                         position: c.position,
13352                         offset: c.positionAbs
13353                 };
13354         },
13356         // Extension points just to make backcompat sane and avoid duplicating logic
13357         // TODO: Remove in 1.14 along with call to it below
13358         _addHoverClass: function() {
13359                 this._addClass( "ui-droppable-hover" );
13360         },
13362         _removeHoverClass: function() {
13363                 this._removeClass( "ui-droppable-hover" );
13364         },
13366         _addActiveClass: function() {
13367                 this._addClass( "ui-droppable-active" );
13368         },
13370         _removeActiveClass: function() {
13371                 this._removeClass( "ui-droppable-active" );
13372         }
13373 } );
13375 $.ui.intersect = ( function() {
13376         function isOverAxis( x, reference, size ) {
13377                 return ( x >= reference ) && ( x < ( reference + size ) );
13378         }
13380         return function( draggable, droppable, toleranceMode, event ) {
13382                 if ( !droppable.offset ) {
13383                         return false;
13384                 }
13386                 var x1 = ( draggable.positionAbs ||
13387                                 draggable.position.absolute ).left + draggable.margins.left,
13388                         y1 = ( draggable.positionAbs ||
13389                                 draggable.position.absolute ).top + draggable.margins.top,
13390                         x2 = x1 + draggable.helperProportions.width,
13391                         y2 = y1 + draggable.helperProportions.height,
13392                         l = droppable.offset.left,
13393                         t = droppable.offset.top,
13394                         r = l + droppable.proportions().width,
13395                         b = t + droppable.proportions().height;
13397                 switch ( toleranceMode ) {
13398                 case "fit":
13399                         return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
13400                 case "intersect":
13401                         return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
13402                                 x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
13403                                 t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
13404                                 y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
13405                 case "pointer":
13406                         return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
13407                                 isOverAxis( event.pageX, l, droppable.proportions().width );
13408                 case "touch":
13409                         return (
13410                                 ( y1 >= t && y1 <= b ) || // Top edge touching
13411                                 ( y2 >= t && y2 <= b ) || // Bottom edge touching
13412                                 ( y1 < t && y2 > b ) // Surrounded vertically
13413                         ) && (
13414                                 ( x1 >= l && x1 <= r ) || // Left edge touching
13415                                 ( x2 >= l && x2 <= r ) || // Right edge touching
13416                                 ( x1 < l && x2 > r ) // Surrounded horizontally
13417                         );
13418                 default:
13419                         return false;
13420                 }
13421         };
13422 } )();
13425         This manager tracks offsets of draggables and droppables
13427 $.ui.ddmanager = {
13428         current: null,
13429         droppables: { "default": [] },
13430         prepareOffsets: function( t, event ) {
13432                 var i, j,
13433                         m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
13434                         type = event ? event.type : null, // workaround for #2317
13435                         list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
13437                 droppablesLoop: for ( i = 0; i < m.length; i++ ) {
13439                         // No disabled and non-accepted
13440                         if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
13441                                         ( t.currentItem || t.element ) ) ) ) {
13442                                 continue;
13443                         }
13445                         // Filter out elements in the current dragged item
13446                         for ( j = 0; j < list.length; j++ ) {
13447                                 if ( list[ j ] === m[ i ].element[ 0 ] ) {
13448                                         m[ i ].proportions().height = 0;
13449                                         continue droppablesLoop;
13450                                 }
13451                         }
13453                         m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
13454                         if ( !m[ i ].visible ) {
13455                                 continue;
13456                         }
13458                         // Activate the droppable if used directly from draggables
13459                         if ( type === "mousedown" ) {
13460                                 m[ i ]._activate.call( m[ i ], event );
13461                         }
13463                         m[ i ].offset = m[ i ].element.offset();
13464                         m[ i ].proportions( {
13465                                 width: m[ i ].element[ 0 ].offsetWidth,
13466                                 height: m[ i ].element[ 0 ].offsetHeight
13467                         } );
13469                 }
13471         },
13472         drop: function( draggable, event ) {
13474                 var dropped = false;
13476                 // Create a copy of the droppables in case the list changes during the drop (#9116)
13477                 $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
13479                         if ( !this.options ) {
13480                                 return;
13481                         }
13482                         if ( !this.options.disabled && this.visible &&
13483                                         $.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
13484                                 dropped = this._drop.call( this, event ) || dropped;
13485                         }
13487                         if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
13488                                         ( draggable.currentItem || draggable.element ) ) ) {
13489                                 this.isout = true;
13490                                 this.isover = false;
13491                                 this._deactivate.call( this, event );
13492                         }
13494                 } );
13495                 return dropped;
13497         },
13498         dragStart: function( draggable, event ) {
13500                 // Listen for scrolling so that if the dragging causes scrolling the position of the
13501                 // droppables can be recalculated (see #5003)
13502                 draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
13503                         if ( !draggable.options.refreshPositions ) {
13504                                 $.ui.ddmanager.prepareOffsets( draggable, event );
13505                         }
13506                 } );
13507         },
13508         drag: function( draggable, event ) {
13510                 // If you have a highly dynamic page, you might try this option. It renders positions
13511                 // every time you move the mouse.
13512                 if ( draggable.options.refreshPositions ) {
13513                         $.ui.ddmanager.prepareOffsets( draggable, event );
13514                 }
13516                 // Run through all droppables and check their positions based on specific tolerance options
13517                 $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
13519                         if ( this.options.disabled || this.greedyChild || !this.visible ) {
13520                                 return;
13521                         }
13523                         var parentInstance, scope, parent,
13524                                 intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
13525                                 c = !intersects && this.isover ?
13526                                         "isout" :
13527                                         ( intersects && !this.isover ? "isover" : null );
13528                         if ( !c ) {
13529                                 return;
13530                         }
13532                         if ( this.options.greedy ) {
13534                                 // find droppable parents with same scope
13535                                 scope = this.options.scope;
13536                                 parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
13537                                         return $( this ).droppable( "instance" ).options.scope === scope;
13538                                 } );
13540                                 if ( parent.length ) {
13541                                         parentInstance = $( parent[ 0 ] ).droppable( "instance" );
13542                                         parentInstance.greedyChild = ( c === "isover" );
13543                                 }
13544                         }
13546                         // We just moved into a greedy child
13547                         if ( parentInstance && c === "isover" ) {
13548                                 parentInstance.isover = false;
13549                                 parentInstance.isout = true;
13550                                 parentInstance._out.call( parentInstance, event );
13551                         }
13553                         this[ c ] = true;
13554                         this[ c === "isout" ? "isover" : "isout" ] = false;
13555                         this[ c === "isover" ? "_over" : "_out" ].call( this, event );
13557                         // We just moved out of a greedy child
13558                         if ( parentInstance && c === "isout" ) {
13559                                 parentInstance.isout = false;
13560                                 parentInstance.isover = true;
13561                                 parentInstance._over.call( parentInstance, event );
13562                         }
13563                 } );
13565         },
13566         dragStop: function( draggable, event ) {
13567                 draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
13569                 // Call prepareOffsets one final time since IE does not fire return scroll events when
13570                 // overflow was caused by drag (see #5003)
13571                 if ( !draggable.options.refreshPositions ) {
13572                         $.ui.ddmanager.prepareOffsets( draggable, event );
13573                 }
13574         }
13577 // DEPRECATED
13578 // TODO: switch return back to widget declaration at top of file when this is removed
13579 if ( $.uiBackCompat !== false ) {
13581         // Backcompat for activeClass and hoverClass options
13582         $.widget( "ui.droppable", $.ui.droppable, {
13583                 options: {
13584                         hoverClass: false,
13585                         activeClass: false
13586                 },
13587                 _addActiveClass: function() {
13588                         this._super();
13589                         if ( this.options.activeClass ) {
13590                                 this.element.addClass( this.options.activeClass );
13591                         }
13592                 },
13593                 _removeActiveClass: function() {
13594                         this._super();
13595                         if ( this.options.activeClass ) {
13596                                 this.element.removeClass( this.options.activeClass );
13597                         }
13598                 },
13599                 _addHoverClass: function() {
13600                         this._super();
13601                         if ( this.options.hoverClass ) {
13602                                 this.element.addClass( this.options.hoverClass );
13603                         }
13604                 },
13605                 _removeHoverClass: function() {
13606                         this._super();
13607                         if ( this.options.hoverClass ) {
13608                                 this.element.removeClass( this.options.hoverClass );
13609                         }
13610                 }
13611         } );
13614 var widgetsDroppable = $.ui.droppable;
13618  * jQuery UI Progressbar 1.13.0
13619  * http://jqueryui.com
13621  * Copyright jQuery Foundation and other contributors
13622  * Released under the MIT license.
13623  * http://jquery.org/license
13624  */
13626 //>>label: Progressbar
13627 //>>group: Widgets
13628 /* eslint-disable max-len */
13629 //>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
13630 /* eslint-enable max-len */
13631 //>>docs: http://api.jqueryui.com/progressbar/
13632 //>>demos: http://jqueryui.com/progressbar/
13633 //>>css.structure: ../../themes/base/core.css
13634 //>>css.structure: ../../themes/base/progressbar.css
13635 //>>css.theme: ../../themes/base/theme.css
13638 var widgetsProgressbar = $.widget( "ui.progressbar", {
13639         version: "1.13.0",
13640         options: {
13641                 classes: {
13642                         "ui-progressbar": "ui-corner-all",
13643                         "ui-progressbar-value": "ui-corner-left",
13644                         "ui-progressbar-complete": "ui-corner-right"
13645                 },
13646                 max: 100,
13647                 value: 0,
13649                 change: null,
13650                 complete: null
13651         },
13653         min: 0,
13655         _create: function() {
13657                 // Constrain initial value
13658                 this.oldValue = this.options.value = this._constrainedValue();
13660                 this.element.attr( {
13662                         // Only set static values; aria-valuenow and aria-valuemax are
13663                         // set inside _refreshValue()
13664                         role: "progressbar",
13665                         "aria-valuemin": this.min
13666                 } );
13667                 this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
13669                 this.valueDiv = $( "<div>" ).appendTo( this.element );
13670                 this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
13671                 this._refreshValue();
13672         },
13674         _destroy: function() {
13675                 this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
13677                 this.valueDiv.remove();
13678         },
13680         value: function( newValue ) {
13681                 if ( newValue === undefined ) {
13682                         return this.options.value;
13683                 }
13685                 this.options.value = this._constrainedValue( newValue );
13686                 this._refreshValue();
13687         },
13689         _constrainedValue: function( newValue ) {
13690                 if ( newValue === undefined ) {
13691                         newValue = this.options.value;
13692                 }
13694                 this.indeterminate = newValue === false;
13696                 // Sanitize value
13697                 if ( typeof newValue !== "number" ) {
13698                         newValue = 0;
13699                 }
13701                 return this.indeterminate ? false :
13702                         Math.min( this.options.max, Math.max( this.min, newValue ) );
13703         },
13705         _setOptions: function( options ) {
13707                 // Ensure "value" option is set after other values (like max)
13708                 var value = options.value;
13709                 delete options.value;
13711                 this._super( options );
13713                 this.options.value = this._constrainedValue( value );
13714                 this._refreshValue();
13715         },
13717         _setOption: function( key, value ) {
13718                 if ( key === "max" ) {
13720                         // Don't allow a max less than min
13721                         value = Math.max( this.min, value );
13722                 }
13723                 this._super( key, value );
13724         },
13726         _setOptionDisabled: function( value ) {
13727                 this._super( value );
13729                 this.element.attr( "aria-disabled", value );
13730                 this._toggleClass( null, "ui-state-disabled", !!value );
13731         },
13733         _percentage: function() {
13734                 return this.indeterminate ?
13735                         100 :
13736                         100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
13737         },
13739         _refreshValue: function() {
13740                 var value = this.options.value,
13741                         percentage = this._percentage();
13743                 this.valueDiv
13744                         .toggle( this.indeterminate || value > this.min )
13745                         .width( percentage.toFixed( 0 ) + "%" );
13747                 this
13748                         ._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
13749                                 value === this.options.max )
13750                         ._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
13752                 if ( this.indeterminate ) {
13753                         this.element.removeAttr( "aria-valuenow" );
13754                         if ( !this.overlayDiv ) {
13755                                 this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
13756                                 this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
13757                         }
13758                 } else {
13759                         this.element.attr( {
13760                                 "aria-valuemax": this.options.max,
13761                                 "aria-valuenow": value
13762                         } );
13763                         if ( this.overlayDiv ) {
13764                                 this.overlayDiv.remove();
13765                                 this.overlayDiv = null;
13766                         }
13767                 }
13769                 if ( this.oldValue !== value ) {
13770                         this.oldValue = value;
13771                         this._trigger( "change" );
13772                 }
13773                 if ( value === this.options.max ) {
13774                         this._trigger( "complete" );
13775                 }
13776         }
13777 } );
13781  * jQuery UI Selectable 1.13.0
13782  * http://jqueryui.com
13784  * Copyright jQuery Foundation and other contributors
13785  * Released under the MIT license.
13786  * http://jquery.org/license
13787  */
13789 //>>label: Selectable
13790 //>>group: Interactions
13791 //>>description: Allows groups of elements to be selected with the mouse.
13792 //>>docs: http://api.jqueryui.com/selectable/
13793 //>>demos: http://jqueryui.com/selectable/
13794 //>>css.structure: ../../themes/base/selectable.css
13797 var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, {
13798         version: "1.13.0",
13799         options: {
13800                 appendTo: "body",
13801                 autoRefresh: true,
13802                 distance: 0,
13803                 filter: "*",
13804                 tolerance: "touch",
13806                 // Callbacks
13807                 selected: null,
13808                 selecting: null,
13809                 start: null,
13810                 stop: null,
13811                 unselected: null,
13812                 unselecting: null
13813         },
13814         _create: function() {
13815                 var that = this;
13817                 this._addClass( "ui-selectable" );
13819                 this.dragged = false;
13821                 // Cache selectee children based on filter
13822                 this.refresh = function() {
13823                         that.elementPos = $( that.element[ 0 ] ).offset();
13824                         that.selectees = $( that.options.filter, that.element[ 0 ] );
13825                         that._addClass( that.selectees, "ui-selectee" );
13826                         that.selectees.each( function() {
13827                                 var $this = $( this ),
13828                                         selecteeOffset = $this.offset(),
13829                                         pos = {
13830                                                 left: selecteeOffset.left - that.elementPos.left,
13831                                                 top: selecteeOffset.top - that.elementPos.top
13832                                         };
13833                                 $.data( this, "selectable-item", {
13834                                         element: this,
13835                                         $element: $this,
13836                                         left: pos.left,
13837                                         top: pos.top,
13838                                         right: pos.left + $this.outerWidth(),
13839                                         bottom: pos.top + $this.outerHeight(),
13840                                         startselected: false,
13841                                         selected: $this.hasClass( "ui-selected" ),
13842                                         selecting: $this.hasClass( "ui-selecting" ),
13843                                         unselecting: $this.hasClass( "ui-unselecting" )
13844                                 } );
13845                         } );
13846                 };
13847                 this.refresh();
13849                 this._mouseInit();
13851                 this.helper = $( "<div>" );
13852                 this._addClass( this.helper, "ui-selectable-helper" );
13853         },
13855         _destroy: function() {
13856                 this.selectees.removeData( "selectable-item" );
13857                 this._mouseDestroy();
13858         },
13860         _mouseStart: function( event ) {
13861                 var that = this,
13862                         options = this.options;
13864                 this.opos = [ event.pageX, event.pageY ];
13865                 this.elementPos = $( this.element[ 0 ] ).offset();
13867                 if ( this.options.disabled ) {
13868                         return;
13869                 }
13871                 this.selectees = $( options.filter, this.element[ 0 ] );
13873                 this._trigger( "start", event );
13875                 $( options.appendTo ).append( this.helper );
13877                 // position helper (lasso)
13878                 this.helper.css( {
13879                         "left": event.pageX,
13880                         "top": event.pageY,
13881                         "width": 0,
13882                         "height": 0
13883                 } );
13885                 if ( options.autoRefresh ) {
13886                         this.refresh();
13887                 }
13889                 this.selectees.filter( ".ui-selected" ).each( function() {
13890                         var selectee = $.data( this, "selectable-item" );
13891                         selectee.startselected = true;
13892                         if ( !event.metaKey && !event.ctrlKey ) {
13893                                 that._removeClass( selectee.$element, "ui-selected" );
13894                                 selectee.selected = false;
13895                                 that._addClass( selectee.$element, "ui-unselecting" );
13896                                 selectee.unselecting = true;
13898                                 // selectable UNSELECTING callback
13899                                 that._trigger( "unselecting", event, {
13900                                         unselecting: selectee.element
13901                                 } );
13902                         }
13903                 } );
13905                 $( event.target ).parents().addBack().each( function() {
13906                         var doSelect,
13907                                 selectee = $.data( this, "selectable-item" );
13908                         if ( selectee ) {
13909                                 doSelect = ( !event.metaKey && !event.ctrlKey ) ||
13910                                         !selectee.$element.hasClass( "ui-selected" );
13911                                 that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
13912                                         ._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
13913                                 selectee.unselecting = !doSelect;
13914                                 selectee.selecting = doSelect;
13915                                 selectee.selected = doSelect;
13917                                 // selectable (UN)SELECTING callback
13918                                 if ( doSelect ) {
13919                                         that._trigger( "selecting", event, {
13920                                                 selecting: selectee.element
13921                                         } );
13922                                 } else {
13923                                         that._trigger( "unselecting", event, {
13924                                                 unselecting: selectee.element
13925                                         } );
13926                                 }
13927                                 return false;
13928                         }
13929                 } );
13931         },
13933         _mouseDrag: function( event ) {
13935                 this.dragged = true;
13937                 if ( this.options.disabled ) {
13938                         return;
13939                 }
13941                 var tmp,
13942                         that = this,
13943                         options = this.options,
13944                         x1 = this.opos[ 0 ],
13945                         y1 = this.opos[ 1 ],
13946                         x2 = event.pageX,
13947                         y2 = event.pageY;
13949                 if ( x1 > x2 ) {
13950                         tmp = x2; x2 = x1; x1 = tmp;
13951                 }
13952                 if ( y1 > y2 ) {
13953                         tmp = y2; y2 = y1; y1 = tmp;
13954                 }
13955                 this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
13957                 this.selectees.each( function() {
13958                         var selectee = $.data( this, "selectable-item" ),
13959                                 hit = false,
13960                                 offset = {};
13962                         //prevent helper from being selected if appendTo: selectable
13963                         if ( !selectee || selectee.element === that.element[ 0 ] ) {
13964                                 return;
13965                         }
13967                         offset.left   = selectee.left   + that.elementPos.left;
13968                         offset.right  = selectee.right  + that.elementPos.left;
13969                         offset.top    = selectee.top    + that.elementPos.top;
13970                         offset.bottom = selectee.bottom + that.elementPos.top;
13972                         if ( options.tolerance === "touch" ) {
13973                                 hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
13974                     offset.bottom < y1 ) );
13975                         } else if ( options.tolerance === "fit" ) {
13976                                 hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
13977                     offset.bottom < y2 );
13978                         }
13980                         if ( hit ) {
13982                                 // SELECT
13983                                 if ( selectee.selected ) {
13984                                         that._removeClass( selectee.$element, "ui-selected" );
13985                                         selectee.selected = false;
13986                                 }
13987                                 if ( selectee.unselecting ) {
13988                                         that._removeClass( selectee.$element, "ui-unselecting" );
13989                                         selectee.unselecting = false;
13990                                 }
13991                                 if ( !selectee.selecting ) {
13992                                         that._addClass( selectee.$element, "ui-selecting" );
13993                                         selectee.selecting = true;
13995                                         // selectable SELECTING callback
13996                                         that._trigger( "selecting", event, {
13997                                                 selecting: selectee.element
13998                                         } );
13999                                 }
14000                         } else {
14002                                 // UNSELECT
14003                                 if ( selectee.selecting ) {
14004                                         if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
14005                                                 that._removeClass( selectee.$element, "ui-selecting" );
14006                                                 selectee.selecting = false;
14007                                                 that._addClass( selectee.$element, "ui-selected" );
14008                                                 selectee.selected = true;
14009                                         } else {
14010                                                 that._removeClass( selectee.$element, "ui-selecting" );
14011                                                 selectee.selecting = false;
14012                                                 if ( selectee.startselected ) {
14013                                                         that._addClass( selectee.$element, "ui-unselecting" );
14014                                                         selectee.unselecting = true;
14015                                                 }
14017                                                 // selectable UNSELECTING callback
14018                                                 that._trigger( "unselecting", event, {
14019                                                         unselecting: selectee.element
14020                                                 } );
14021                                         }
14022                                 }
14023                                 if ( selectee.selected ) {
14024                                         if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
14025                                                 that._removeClass( selectee.$element, "ui-selected" );
14026                                                 selectee.selected = false;
14028                                                 that._addClass( selectee.$element, "ui-unselecting" );
14029                                                 selectee.unselecting = true;
14031                                                 // selectable UNSELECTING callback
14032                                                 that._trigger( "unselecting", event, {
14033                                                         unselecting: selectee.element
14034                                                 } );
14035                                         }
14036                                 }
14037                         }
14038                 } );
14040                 return false;
14041         },
14043         _mouseStop: function( event ) {
14044                 var that = this;
14046                 this.dragged = false;
14048                 $( ".ui-unselecting", this.element[ 0 ] ).each( function() {
14049                         var selectee = $.data( this, "selectable-item" );
14050                         that._removeClass( selectee.$element, "ui-unselecting" );
14051                         selectee.unselecting = false;
14052                         selectee.startselected = false;
14053                         that._trigger( "unselected", event, {
14054                                 unselected: selectee.element
14055                         } );
14056                 } );
14057                 $( ".ui-selecting", this.element[ 0 ] ).each( function() {
14058                         var selectee = $.data( this, "selectable-item" );
14059                         that._removeClass( selectee.$element, "ui-selecting" )
14060                                 ._addClass( selectee.$element, "ui-selected" );
14061                         selectee.selecting = false;
14062                         selectee.selected = true;
14063                         selectee.startselected = true;
14064                         that._trigger( "selected", event, {
14065                                 selected: selectee.element
14066                         } );
14067                 } );
14068                 this._trigger( "stop", event );
14070                 this.helper.remove();
14072                 return false;
14073         }
14075 } );
14079  * jQuery UI Selectmenu 1.13.0
14080  * http://jqueryui.com
14082  * Copyright jQuery Foundation and other contributors
14083  * Released under the MIT license.
14084  * http://jquery.org/license
14085  */
14087 //>>label: Selectmenu
14088 //>>group: Widgets
14089 /* eslint-disable max-len */
14090 //>>description: Duplicates and extends the functionality of a native HTML select element, allowing it to be customizable in behavior and appearance far beyond the limitations of a native select.
14091 /* eslint-enable max-len */
14092 //>>docs: http://api.jqueryui.com/selectmenu/
14093 //>>demos: http://jqueryui.com/selectmenu/
14094 //>>css.structure: ../../themes/base/core.css
14095 //>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
14096 //>>css.theme: ../../themes/base/theme.css
14099 var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
14100         version: "1.13.0",
14101         defaultElement: "<select>",
14102         options: {
14103                 appendTo: null,
14104                 classes: {
14105                         "ui-selectmenu-button-open": "ui-corner-top",
14106                         "ui-selectmenu-button-closed": "ui-corner-all"
14107                 },
14108                 disabled: null,
14109                 icons: {
14110                         button: "ui-icon-triangle-1-s"
14111                 },
14112                 position: {
14113                         my: "left top",
14114                         at: "left bottom",
14115                         collision: "none"
14116                 },
14117                 width: false,
14119                 // Callbacks
14120                 change: null,
14121                 close: null,
14122                 focus: null,
14123                 open: null,
14124                 select: null
14125         },
14127         _create: function() {
14128                 var selectmenuId = this.element.uniqueId().attr( "id" );
14129                 this.ids = {
14130                         element: selectmenuId,
14131                         button: selectmenuId + "-button",
14132                         menu: selectmenuId + "-menu"
14133                 };
14135                 this._drawButton();
14136                 this._drawMenu();
14137                 this._bindFormResetHandler();
14139                 this._rendered = false;
14140                 this.menuItems = $();
14141         },
14143         _drawButton: function() {
14144                 var icon,
14145                         that = this,
14146                         item = this._parseOption(
14147                                 this.element.find( "option:selected" ),
14148                                 this.element[ 0 ].selectedIndex
14149                         );
14151                 // Associate existing label with the new button
14152                 this.labels = this.element.labels().attr( "for", this.ids.button );
14153                 this._on( this.labels, {
14154                         click: function( event ) {
14155                                 this.button.trigger( "focus" );
14156                                 event.preventDefault();
14157                         }
14158                 } );
14160                 // Hide original select element
14161                 this.element.hide();
14163                 // Create button
14164                 this.button = $( "<span>", {
14165                         tabindex: this.options.disabled ? -1 : 0,
14166                         id: this.ids.button,
14167                         role: "combobox",
14168                         "aria-expanded": "false",
14169                         "aria-autocomplete": "list",
14170                         "aria-owns": this.ids.menu,
14171                         "aria-haspopup": "true",
14172                         title: this.element.attr( "title" )
14173                 } )
14174                         .insertAfter( this.element );
14176                 this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
14177                         "ui-button ui-widget" );
14179                 icon = $( "<span>" ).appendTo( this.button );
14180                 this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
14181                 this.buttonItem = this._renderButtonItem( item )
14182                         .appendTo( this.button );
14184                 if ( this.options.width !== false ) {
14185                         this._resizeButton();
14186                 }
14188                 this._on( this.button, this._buttonEvents );
14189                 this.button.one( "focusin", function() {
14191                         // Delay rendering the menu items until the button receives focus.
14192                         // The menu may have already been rendered via a programmatic open.
14193                         if ( !that._rendered ) {
14194                                 that._refreshMenu();
14195                         }
14196                 } );
14197         },
14199         _drawMenu: function() {
14200                 var that = this;
14202                 // Create menu
14203                 this.menu = $( "<ul>", {
14204                         "aria-hidden": "true",
14205                         "aria-labelledby": this.ids.button,
14206                         id: this.ids.menu
14207                 } );
14209                 // Wrap menu
14210                 this.menuWrap = $( "<div>" ).append( this.menu );
14211                 this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
14212                 this.menuWrap.appendTo( this._appendTo() );
14214                 // Initialize menu widget
14215                 this.menuInstance = this.menu
14216                         .menu( {
14217                                 classes: {
14218                                         "ui-menu": "ui-corner-bottom"
14219                                 },
14220                                 role: "listbox",
14221                                 select: function( event, ui ) {
14222                                         event.preventDefault();
14224                                         // Support: IE8
14225                                         // If the item was selected via a click, the text selection
14226                                         // will be destroyed in IE
14227                                         that._setSelection();
14229                                         that._select( ui.item.data( "ui-selectmenu-item" ), event );
14230                                 },
14231                                 focus: function( event, ui ) {
14232                                         var item = ui.item.data( "ui-selectmenu-item" );
14234                                         // Prevent inital focus from firing and check if its a newly focused item
14235                                         if ( that.focusIndex != null && item.index !== that.focusIndex ) {
14236                                                 that._trigger( "focus", event, { item: item } );
14237                                                 if ( !that.isOpen ) {
14238                                                         that._select( item, event );
14239                                                 }
14240                                         }
14241                                         that.focusIndex = item.index;
14243                                         that.button.attr( "aria-activedescendant",
14244                                                 that.menuItems.eq( item.index ).attr( "id" ) );
14245                                 }
14246                         } )
14247                         .menu( "instance" );
14249                 // Don't close the menu on mouseleave
14250                 this.menuInstance._off( this.menu, "mouseleave" );
14252                 // Cancel the menu's collapseAll on document click
14253                 this.menuInstance._closeOnDocumentClick = function() {
14254                         return false;
14255                 };
14257                 // Selects often contain empty items, but never contain dividers
14258                 this.menuInstance._isDivider = function() {
14259                         return false;
14260                 };
14261         },
14263         refresh: function() {
14264                 this._refreshMenu();
14265                 this.buttonItem.replaceWith(
14266                         this.buttonItem = this._renderButtonItem(
14268                                 // Fall back to an empty object in case there are no options
14269                                 this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
14270                         )
14271                 );
14272                 if ( this.options.width === null ) {
14273                         this._resizeButton();
14274                 }
14275         },
14277         _refreshMenu: function() {
14278                 var item,
14279                         options = this.element.find( "option" );
14281                 this.menu.empty();
14283                 this._parseOptions( options );
14284                 this._renderMenu( this.menu, this.items );
14286                 this.menuInstance.refresh();
14287                 this.menuItems = this.menu.find( "li" )
14288                         .not( ".ui-selectmenu-optgroup" )
14289                                 .find( ".ui-menu-item-wrapper" );
14291                 this._rendered = true;
14293                 if ( !options.length ) {
14294                         return;
14295                 }
14297                 item = this._getSelectedItem();
14299                 // Update the menu to have the correct item focused
14300                 this.menuInstance.focus( null, item );
14301                 this._setAria( item.data( "ui-selectmenu-item" ) );
14303                 // Set disabled state
14304                 this._setOption( "disabled", this.element.prop( "disabled" ) );
14305         },
14307         open: function( event ) {
14308                 if ( this.options.disabled ) {
14309                         return;
14310                 }
14312                 // If this is the first time the menu is being opened, render the items
14313                 if ( !this._rendered ) {
14314                         this._refreshMenu();
14315                 } else {
14317                         // Menu clears focus on close, reset focus to selected item
14318                         this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
14319                         this.menuInstance.focus( null, this._getSelectedItem() );
14320                 }
14322                 // If there are no options, don't open the menu
14323                 if ( !this.menuItems.length ) {
14324                         return;
14325                 }
14327                 this.isOpen = true;
14328                 this._toggleAttr();
14329                 this._resizeMenu();
14330                 this._position();
14332                 this._on( this.document, this._documentClick );
14334                 this._trigger( "open", event );
14335         },
14337         _position: function() {
14338                 this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
14339         },
14341         close: function( event ) {
14342                 if ( !this.isOpen ) {
14343                         return;
14344                 }
14346                 this.isOpen = false;
14347                 this._toggleAttr();
14349                 this.range = null;
14350                 this._off( this.document );
14352                 this._trigger( "close", event );
14353         },
14355         widget: function() {
14356                 return this.button;
14357         },
14359         menuWidget: function() {
14360                 return this.menu;
14361         },
14363         _renderButtonItem: function( item ) {
14364                 var buttonItem = $( "<span>" );
14366                 this._setText( buttonItem, item.label );
14367                 this._addClass( buttonItem, "ui-selectmenu-text" );
14369                 return buttonItem;
14370         },
14372         _renderMenu: function( ul, items ) {
14373                 var that = this,
14374                         currentOptgroup = "";
14376                 $.each( items, function( index, item ) {
14377                         var li;
14379                         if ( item.optgroup !== currentOptgroup ) {
14380                                 li = $( "<li>", {
14381                                         text: item.optgroup
14382                                 } );
14383                                 that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
14384                                         ( item.element.parent( "optgroup" ).prop( "disabled" ) ?
14385                                                 " ui-state-disabled" :
14386                                                 "" ) );
14388                                 li.appendTo( ul );
14390                                 currentOptgroup = item.optgroup;
14391                         }
14393                         that._renderItemData( ul, item );
14394                 } );
14395         },
14397         _renderItemData: function( ul, item ) {
14398                 return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
14399         },
14401         _renderItem: function( ul, item ) {
14402                 var li = $( "<li>" ),
14403                         wrapper = $( "<div>", {
14404                                 title: item.element.attr( "title" )
14405                         } );
14407                 if ( item.disabled ) {
14408                         this._addClass( li, null, "ui-state-disabled" );
14409                 }
14410                 this._setText( wrapper, item.label );
14412                 return li.append( wrapper ).appendTo( ul );
14413         },
14415         _setText: function( element, value ) {
14416                 if ( value ) {
14417                         element.text( value );
14418                 } else {
14419                         element.html( "&#160;" );
14420                 }
14421         },
14423         _move: function( direction, event ) {
14424                 var item, next,
14425                         filter = ".ui-menu-item";
14427                 if ( this.isOpen ) {
14428                         item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14429                 } else {
14430                         item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14431                         filter += ":not(.ui-state-disabled)";
14432                 }
14434                 if ( direction === "first" || direction === "last" ) {
14435                         next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
14436                 } else {
14437                         next = item[ direction + "All" ]( filter ).eq( 0 );
14438                 }
14440                 if ( next.length ) {
14441                         this.menuInstance.focus( event, next );
14442                 }
14443         },
14445         _getSelectedItem: function() {
14446                 return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14447         },
14449         _toggle: function( event ) {
14450                 this[ this.isOpen ? "close" : "open" ]( event );
14451         },
14453         _setSelection: function() {
14454                 var selection;
14456                 if ( !this.range ) {
14457                         return;
14458                 }
14460                 if ( window.getSelection ) {
14461                         selection = window.getSelection();
14462                         selection.removeAllRanges();
14463                         selection.addRange( this.range );
14465                 // Support: IE8
14466                 } else {
14467                         this.range.select();
14468                 }
14470                 // Support: IE
14471                 // Setting the text selection kills the button focus in IE, but
14472                 // restoring the focus doesn't kill the selection.
14473                 this.button.focus();
14474         },
14476         _documentClick: {
14477                 mousedown: function( event ) {
14478                         if ( !this.isOpen ) {
14479                                 return;
14480                         }
14482                         if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
14483                                 $.escapeSelector( this.ids.button ) ).length ) {
14484                                 this.close( event );
14485                         }
14486                 }
14487         },
14489         _buttonEvents: {
14491                 // Prevent text selection from being reset when interacting with the selectmenu (#10144)
14492                 mousedown: function() {
14493                         var selection;
14495                         if ( window.getSelection ) {
14496                                 selection = window.getSelection();
14497                                 if ( selection.rangeCount ) {
14498                                         this.range = selection.getRangeAt( 0 );
14499                                 }
14501                         // Support: IE8
14502                         } else {
14503                                 this.range = document.selection.createRange();
14504                         }
14505                 },
14507                 click: function( event ) {
14508                         this._setSelection();
14509                         this._toggle( event );
14510                 },
14512                 keydown: function( event ) {
14513                         var preventDefault = true;
14514                         switch ( event.keyCode ) {
14515                         case $.ui.keyCode.TAB:
14516                         case $.ui.keyCode.ESCAPE:
14517                                 this.close( event );
14518                                 preventDefault = false;
14519                                 break;
14520                         case $.ui.keyCode.ENTER:
14521                                 if ( this.isOpen ) {
14522                                         this._selectFocusedItem( event );
14523                                 }
14524                                 break;
14525                         case $.ui.keyCode.UP:
14526                                 if ( event.altKey ) {
14527                                         this._toggle( event );
14528                                 } else {
14529                                         this._move( "prev", event );
14530                                 }
14531                                 break;
14532                         case $.ui.keyCode.DOWN:
14533                                 if ( event.altKey ) {
14534                                         this._toggle( event );
14535                                 } else {
14536                                         this._move( "next", event );
14537                                 }
14538                                 break;
14539                         case $.ui.keyCode.SPACE:
14540                                 if ( this.isOpen ) {
14541                                         this._selectFocusedItem( event );
14542                                 } else {
14543                                         this._toggle( event );
14544                                 }
14545                                 break;
14546                         case $.ui.keyCode.LEFT:
14547                                 this._move( "prev", event );
14548                                 break;
14549                         case $.ui.keyCode.RIGHT:
14550                                 this._move( "next", event );
14551                                 break;
14552                         case $.ui.keyCode.HOME:
14553                         case $.ui.keyCode.PAGE_UP:
14554                                 this._move( "first", event );
14555                                 break;
14556                         case $.ui.keyCode.END:
14557                         case $.ui.keyCode.PAGE_DOWN:
14558                                 this._move( "last", event );
14559                                 break;
14560                         default:
14561                                 this.menu.trigger( event );
14562                                 preventDefault = false;
14563                         }
14565                         if ( preventDefault ) {
14566                                 event.preventDefault();
14567                         }
14568                 }
14569         },
14571         _selectFocusedItem: function( event ) {
14572                 var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14573                 if ( !item.hasClass( "ui-state-disabled" ) ) {
14574                         this._select( item.data( "ui-selectmenu-item" ), event );
14575                 }
14576         },
14578         _select: function( item, event ) {
14579                 var oldIndex = this.element[ 0 ].selectedIndex;
14581                 // Change native select element
14582                 this.element[ 0 ].selectedIndex = item.index;
14583                 this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
14584                 this._setAria( item );
14585                 this._trigger( "select", event, { item: item } );
14587                 if ( item.index !== oldIndex ) {
14588                         this._trigger( "change", event, { item: item } );
14589                 }
14591                 this.close( event );
14592         },
14594         _setAria: function( item ) {
14595                 var id = this.menuItems.eq( item.index ).attr( "id" );
14597                 this.button.attr( {
14598                         "aria-labelledby": id,
14599                         "aria-activedescendant": id
14600                 } );
14601                 this.menu.attr( "aria-activedescendant", id );
14602         },
14604         _setOption: function( key, value ) {
14605                 if ( key === "icons" ) {
14606                         var icon = this.button.find( "span.ui-icon" );
14607                         this._removeClass( icon, null, this.options.icons.button )
14608                                 ._addClass( icon, null, value.button );
14609                 }
14611                 this._super( key, value );
14613                 if ( key === "appendTo" ) {
14614                         this.menuWrap.appendTo( this._appendTo() );
14615                 }
14617                 if ( key === "width" ) {
14618                         this._resizeButton();
14619                 }
14620         },
14622         _setOptionDisabled: function( value ) {
14623                 this._super( value );
14625                 this.menuInstance.option( "disabled", value );
14626                 this.button.attr( "aria-disabled", value );
14627                 this._toggleClass( this.button, null, "ui-state-disabled", value );
14629                 this.element.prop( "disabled", value );
14630                 if ( value ) {
14631                         this.button.attr( "tabindex", -1 );
14632                         this.close();
14633                 } else {
14634                         this.button.attr( "tabindex", 0 );
14635                 }
14636         },
14638         _appendTo: function() {
14639                 var element = this.options.appendTo;
14641                 if ( element ) {
14642                         element = element.jquery || element.nodeType ?
14643                                 $( element ) :
14644                                 this.document.find( element ).eq( 0 );
14645                 }
14647                 if ( !element || !element[ 0 ] ) {
14648                         element = this.element.closest( ".ui-front, dialog" );
14649                 }
14651                 if ( !element.length ) {
14652                         element = this.document[ 0 ].body;
14653                 }
14655                 return element;
14656         },
14658         _toggleAttr: function() {
14659                 this.button.attr( "aria-expanded", this.isOpen );
14661                 // We can't use two _toggleClass() calls here, because we need to make sure
14662                 // we always remove classes first and add them second, otherwise if both classes have the
14663                 // same theme class, it will be removed after we add it.
14664                 this._removeClass( this.button, "ui-selectmenu-button-" +
14665                         ( this.isOpen ? "closed" : "open" ) )
14666                         ._addClass( this.button, "ui-selectmenu-button-" +
14667                                 ( this.isOpen ? "open" : "closed" ) )
14668                         ._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
14670                 this.menu.attr( "aria-hidden", !this.isOpen );
14671         },
14673         _resizeButton: function() {
14674                 var width = this.options.width;
14676                 // For `width: false`, just remove inline style and stop
14677                 if ( width === false ) {
14678                         this.button.css( "width", "" );
14679                         return;
14680                 }
14682                 // For `width: null`, match the width of the original element
14683                 if ( width === null ) {
14684                         width = this.element.show().outerWidth();
14685                         this.element.hide();
14686                 }
14688                 this.button.outerWidth( width );
14689         },
14691         _resizeMenu: function() {
14692                 this.menu.outerWidth( Math.max(
14693                         this.button.outerWidth(),
14695                         // Support: IE10
14696                         // IE10 wraps long text (possibly a rounding bug)
14697                         // so we add 1px to avoid the wrapping
14698                         this.menu.width( "" ).outerWidth() + 1
14699                 ) );
14700         },
14702         _getCreateOptions: function() {
14703                 var options = this._super();
14705                 options.disabled = this.element.prop( "disabled" );
14707                 return options;
14708         },
14710         _parseOptions: function( options ) {
14711                 var that = this,
14712                         data = [];
14713                 options.each( function( index, item ) {
14714                         if ( item.hidden ) {
14715                                 return;
14716                         }
14718                         data.push( that._parseOption( $( item ), index ) );
14719                 } );
14720                 this.items = data;
14721         },
14723         _parseOption: function( option, index ) {
14724                 var optgroup = option.parent( "optgroup" );
14726                 return {
14727                         element: option,
14728                         index: index,
14729                         value: option.val(),
14730                         label: option.text(),
14731                         optgroup: optgroup.attr( "label" ) || "",
14732                         disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
14733                 };
14734         },
14736         _destroy: function() {
14737                 this._unbindFormResetHandler();
14738                 this.menuWrap.remove();
14739                 this.button.remove();
14740                 this.element.show();
14741                 this.element.removeUniqueId();
14742                 this.labels.attr( "for", this.ids.element );
14743         }
14744 } ] );
14748  * jQuery UI Slider 1.13.0
14749  * http://jqueryui.com
14751  * Copyright jQuery Foundation and other contributors
14752  * Released under the MIT license.
14753  * http://jquery.org/license
14754  */
14756 //>>label: Slider
14757 //>>group: Widgets
14758 //>>description: Displays a flexible slider with ranges and accessibility via keyboard.
14759 //>>docs: http://api.jqueryui.com/slider/
14760 //>>demos: http://jqueryui.com/slider/
14761 //>>css.structure: ../../themes/base/core.css
14762 //>>css.structure: ../../themes/base/slider.css
14763 //>>css.theme: ../../themes/base/theme.css
14766 var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
14767         version: "1.13.0",
14768         widgetEventPrefix: "slide",
14770         options: {
14771                 animate: false,
14772                 classes: {
14773                         "ui-slider": "ui-corner-all",
14774                         "ui-slider-handle": "ui-corner-all",
14776                         // Note: ui-widget-header isn't the most fittingly semantic framework class for this
14777                         // element, but worked best visually with a variety of themes
14778                         "ui-slider-range": "ui-corner-all ui-widget-header"
14779                 },
14780                 distance: 0,
14781                 max: 100,
14782                 min: 0,
14783                 orientation: "horizontal",
14784                 range: false,
14785                 step: 1,
14786                 value: 0,
14787                 values: null,
14789                 // Callbacks
14790                 change: null,
14791                 slide: null,
14792                 start: null,
14793                 stop: null
14794         },
14796         // Number of pages in a slider
14797         // (how many times can you page up/down to go through the whole range)
14798         numPages: 5,
14800         _create: function() {
14801                 this._keySliding = false;
14802                 this._mouseSliding = false;
14803                 this._animateOff = true;
14804                 this._handleIndex = null;
14805                 this._detectOrientation();
14806                 this._mouseInit();
14807                 this._calculateNewMax();
14809                 this._addClass( "ui-slider ui-slider-" + this.orientation,
14810                         "ui-widget ui-widget-content" );
14812                 this._refresh();
14814                 this._animateOff = false;
14815         },
14817         _refresh: function() {
14818                 this._createRange();
14819                 this._createHandles();
14820                 this._setupEvents();
14821                 this._refreshValue();
14822         },
14824         _createHandles: function() {
14825                 var i, handleCount,
14826                         options = this.options,
14827                         existingHandles = this.element.find( ".ui-slider-handle" ),
14828                         handle = "<span tabindex='0'></span>",
14829                         handles = [];
14831                 handleCount = ( options.values && options.values.length ) || 1;
14833                 if ( existingHandles.length > handleCount ) {
14834                         existingHandles.slice( handleCount ).remove();
14835                         existingHandles = existingHandles.slice( 0, handleCount );
14836                 }
14838                 for ( i = existingHandles.length; i < handleCount; i++ ) {
14839                         handles.push( handle );
14840                 }
14842                 this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
14844                 this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
14846                 this.handle = this.handles.eq( 0 );
14848                 this.handles.each( function( i ) {
14849                         $( this )
14850                                 .data( "ui-slider-handle-index", i )
14851                                 .attr( "tabIndex", 0 );
14852                 } );
14853         },
14855         _createRange: function() {
14856                 var options = this.options;
14858                 if ( options.range ) {
14859                         if ( options.range === true ) {
14860                                 if ( !options.values ) {
14861                                         options.values = [ this._valueMin(), this._valueMin() ];
14862                                 } else if ( options.values.length && options.values.length !== 2 ) {
14863                                         options.values = [ options.values[ 0 ], options.values[ 0 ] ];
14864                                 } else if ( Array.isArray( options.values ) ) {
14865                                         options.values = options.values.slice( 0 );
14866                                 }
14867                         }
14869                         if ( !this.range || !this.range.length ) {
14870                                 this.range = $( "<div>" )
14871                                         .appendTo( this.element );
14873                                 this._addClass( this.range, "ui-slider-range" );
14874                         } else {
14875                                 this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
14877                                 // Handle range switching from true to min/max
14878                                 this.range.css( {
14879                                         "left": "",
14880                                         "bottom": ""
14881                                 } );
14882                         }
14883                         if ( options.range === "min" || options.range === "max" ) {
14884                                 this._addClass( this.range, "ui-slider-range-" + options.range );
14885                         }
14886                 } else {
14887                         if ( this.range ) {
14888                                 this.range.remove();
14889                         }
14890                         this.range = null;
14891                 }
14892         },
14894         _setupEvents: function() {
14895                 this._off( this.handles );
14896                 this._on( this.handles, this._handleEvents );
14897                 this._hoverable( this.handles );
14898                 this._focusable( this.handles );
14899         },
14901         _destroy: function() {
14902                 this.handles.remove();
14903                 if ( this.range ) {
14904                         this.range.remove();
14905                 }
14907                 this._mouseDestroy();
14908         },
14910         _mouseCapture: function( event ) {
14911                 var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
14912                         that = this,
14913                         o = this.options;
14915                 if ( o.disabled ) {
14916                         return false;
14917                 }
14919                 this.elementSize = {
14920                         width: this.element.outerWidth(),
14921                         height: this.element.outerHeight()
14922                 };
14923                 this.elementOffset = this.element.offset();
14925                 position = { x: event.pageX, y: event.pageY };
14926                 normValue = this._normValueFromMouse( position );
14927                 distance = this._valueMax() - this._valueMin() + 1;
14928                 this.handles.each( function( i ) {
14929                         var thisDistance = Math.abs( normValue - that.values( i ) );
14930                         if ( ( distance > thisDistance ) ||
14931                                 ( distance === thisDistance &&
14932                                         ( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
14933                                 distance = thisDistance;
14934                                 closestHandle = $( this );
14935                                 index = i;
14936                         }
14937                 } );
14939                 allowed = this._start( event, index );
14940                 if ( allowed === false ) {
14941                         return false;
14942                 }
14943                 this._mouseSliding = true;
14945                 this._handleIndex = index;
14947                 this._addClass( closestHandle, null, "ui-state-active" );
14948                 closestHandle.trigger( "focus" );
14950                 offset = closestHandle.offset();
14951                 mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
14952                 this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
14953                         left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
14954                         top: event.pageY - offset.top -
14955                                 ( closestHandle.height() / 2 ) -
14956                                 ( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
14957                                 ( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
14958                                 ( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
14959                 };
14961                 if ( !this.handles.hasClass( "ui-state-hover" ) ) {
14962                         this._slide( event, index, normValue );
14963                 }
14964                 this._animateOff = true;
14965                 return true;
14966         },
14968         _mouseStart: function() {
14969                 return true;
14970         },
14972         _mouseDrag: function( event ) {
14973                 var position = { x: event.pageX, y: event.pageY },
14974                         normValue = this._normValueFromMouse( position );
14976                 this._slide( event, this._handleIndex, normValue );
14978                 return false;
14979         },
14981         _mouseStop: function( event ) {
14982                 this._removeClass( this.handles, null, "ui-state-active" );
14983                 this._mouseSliding = false;
14985                 this._stop( event, this._handleIndex );
14986                 this._change( event, this._handleIndex );
14988                 this._handleIndex = null;
14989                 this._clickOffset = null;
14990                 this._animateOff = false;
14992                 return false;
14993         },
14995         _detectOrientation: function() {
14996                 this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
14997         },
14999         _normValueFromMouse: function( position ) {
15000                 var pixelTotal,
15001                         pixelMouse,
15002                         percentMouse,
15003                         valueTotal,
15004                         valueMouse;
15006                 if ( this.orientation === "horizontal" ) {
15007                         pixelTotal = this.elementSize.width;
15008                         pixelMouse = position.x - this.elementOffset.left -
15009                                 ( this._clickOffset ? this._clickOffset.left : 0 );
15010                 } else {
15011                         pixelTotal = this.elementSize.height;
15012                         pixelMouse = position.y - this.elementOffset.top -
15013                                 ( this._clickOffset ? this._clickOffset.top : 0 );
15014                 }
15016                 percentMouse = ( pixelMouse / pixelTotal );
15017                 if ( percentMouse > 1 ) {
15018                         percentMouse = 1;
15019                 }
15020                 if ( percentMouse < 0 ) {
15021                         percentMouse = 0;
15022                 }
15023                 if ( this.orientation === "vertical" ) {
15024                         percentMouse = 1 - percentMouse;
15025                 }
15027                 valueTotal = this._valueMax() - this._valueMin();
15028                 valueMouse = this._valueMin() + percentMouse * valueTotal;
15030                 return this._trimAlignValue( valueMouse );
15031         },
15033         _uiHash: function( index, value, values ) {
15034                 var uiHash = {
15035                         handle: this.handles[ index ],
15036                         handleIndex: index,
15037                         value: value !== undefined ? value : this.value()
15038                 };
15040                 if ( this._hasMultipleValues() ) {
15041                         uiHash.value = value !== undefined ? value : this.values( index );
15042                         uiHash.values = values || this.values();
15043                 }
15045                 return uiHash;
15046         },
15048         _hasMultipleValues: function() {
15049                 return this.options.values && this.options.values.length;
15050         },
15052         _start: function( event, index ) {
15053                 return this._trigger( "start", event, this._uiHash( index ) );
15054         },
15056         _slide: function( event, index, newVal ) {
15057                 var allowed, otherVal,
15058                         currentValue = this.value(),
15059                         newValues = this.values();
15061                 if ( this._hasMultipleValues() ) {
15062                         otherVal = this.values( index ? 0 : 1 );
15063                         currentValue = this.values( index );
15065                         if ( this.options.values.length === 2 && this.options.range === true ) {
15066                                 newVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
15067                         }
15069                         newValues[ index ] = newVal;
15070                 }
15072                 if ( newVal === currentValue ) {
15073                         return;
15074                 }
15076                 allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
15078                 // A slide can be canceled by returning false from the slide callback
15079                 if ( allowed === false ) {
15080                         return;
15081                 }
15083                 if ( this._hasMultipleValues() ) {
15084                         this.values( index, newVal );
15085                 } else {
15086                         this.value( newVal );
15087                 }
15088         },
15090         _stop: function( event, index ) {
15091                 this._trigger( "stop", event, this._uiHash( index ) );
15092         },
15094         _change: function( event, index ) {
15095                 if ( !this._keySliding && !this._mouseSliding ) {
15097                         //store the last changed value index for reference when handles overlap
15098                         this._lastChangedValue = index;
15099                         this._trigger( "change", event, this._uiHash( index ) );
15100                 }
15101         },
15103         value: function( newValue ) {
15104                 if ( arguments.length ) {
15105                         this.options.value = this._trimAlignValue( newValue );
15106                         this._refreshValue();
15107                         this._change( null, 0 );
15108                         return;
15109                 }
15111                 return this._value();
15112         },
15114         values: function( index, newValue ) {
15115                 var vals,
15116                         newValues,
15117                         i;
15119                 if ( arguments.length > 1 ) {
15120                         this.options.values[ index ] = this._trimAlignValue( newValue );
15121                         this._refreshValue();
15122                         this._change( null, index );
15123                         return;
15124                 }
15126                 if ( arguments.length ) {
15127                         if ( Array.isArray( arguments[ 0 ] ) ) {
15128                                 vals = this.options.values;
15129                                 newValues = arguments[ 0 ];
15130                                 for ( i = 0; i < vals.length; i += 1 ) {
15131                                         vals[ i ] = this._trimAlignValue( newValues[ i ] );
15132                                         this._change( null, i );
15133                                 }
15134                                 this._refreshValue();
15135                         } else {
15136                                 if ( this._hasMultipleValues() ) {
15137                                         return this._values( index );
15138                                 } else {
15139                                         return this.value();
15140                                 }
15141                         }
15142                 } else {
15143                         return this._values();
15144                 }
15145         },
15147         _setOption: function( key, value ) {
15148                 var i,
15149                         valsLength = 0;
15151                 if ( key === "range" && this.options.range === true ) {
15152                         if ( value === "min" ) {
15153                                 this.options.value = this._values( 0 );
15154                                 this.options.values = null;
15155                         } else if ( value === "max" ) {
15156                                 this.options.value = this._values( this.options.values.length - 1 );
15157                                 this.options.values = null;
15158                         }
15159                 }
15161                 if ( Array.isArray( this.options.values ) ) {
15162                         valsLength = this.options.values.length;
15163                 }
15165                 this._super( key, value );
15167                 switch ( key ) {
15168                         case "orientation":
15169                                 this._detectOrientation();
15170                                 this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
15171                                         ._addClass( "ui-slider-" + this.orientation );
15172                                 this._refreshValue();
15173                                 if ( this.options.range ) {
15174                                         this._refreshRange( value );
15175                                 }
15177                                 // Reset positioning from previous orientation
15178                                 this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
15179                                 break;
15180                         case "value":
15181                                 this._animateOff = true;
15182                                 this._refreshValue();
15183                                 this._change( null, 0 );
15184                                 this._animateOff = false;
15185                                 break;
15186                         case "values":
15187                                 this._animateOff = true;
15188                                 this._refreshValue();
15190                                 // Start from the last handle to prevent unreachable handles (#9046)
15191                                 for ( i = valsLength - 1; i >= 0; i-- ) {
15192                                         this._change( null, i );
15193                                 }
15194                                 this._animateOff = false;
15195                                 break;
15196                         case "step":
15197                         case "min":
15198                         case "max":
15199                                 this._animateOff = true;
15200                                 this._calculateNewMax();
15201                                 this._refreshValue();
15202                                 this._animateOff = false;
15203                                 break;
15204                         case "range":
15205                                 this._animateOff = true;
15206                                 this._refresh();
15207                                 this._animateOff = false;
15208                                 break;
15209                 }
15210         },
15212         _setOptionDisabled: function( value ) {
15213                 this._super( value );
15215                 this._toggleClass( null, "ui-state-disabled", !!value );
15216         },
15218         //internal value getter
15219         // _value() returns value trimmed by min and max, aligned by step
15220         _value: function() {
15221                 var val = this.options.value;
15222                 val = this._trimAlignValue( val );
15224                 return val;
15225         },
15227         //internal values getter
15228         // _values() returns array of values trimmed by min and max, aligned by step
15229         // _values( index ) returns single value trimmed by min and max, aligned by step
15230         _values: function( index ) {
15231                 var val,
15232                         vals,
15233                         i;
15235                 if ( arguments.length ) {
15236                         val = this.options.values[ index ];
15237                         val = this._trimAlignValue( val );
15239                         return val;
15240                 } else if ( this._hasMultipleValues() ) {
15242                         // .slice() creates a copy of the array
15243                         // this copy gets trimmed by min and max and then returned
15244                         vals = this.options.values.slice();
15245                         for ( i = 0; i < vals.length; i += 1 ) {
15246                                 vals[ i ] = this._trimAlignValue( vals[ i ] );
15247                         }
15249                         return vals;
15250                 } else {
15251                         return [];
15252                 }
15253         },
15255         // Returns the step-aligned value that val is closest to, between (inclusive) min and max
15256         _trimAlignValue: function( val ) {
15257                 if ( val <= this._valueMin() ) {
15258                         return this._valueMin();
15259                 }
15260                 if ( val >= this._valueMax() ) {
15261                         return this._valueMax();
15262                 }
15263                 var step = ( this.options.step > 0 ) ? this.options.step : 1,
15264                         valModStep = ( val - this._valueMin() ) % step,
15265                         alignValue = val - valModStep;
15267                 if ( Math.abs( valModStep ) * 2 >= step ) {
15268                         alignValue += ( valModStep > 0 ) ? step : ( -step );
15269                 }
15271                 // Since JavaScript has problems with large floats, round
15272                 // the final value to 5 digits after the decimal point (see #4124)
15273                 return parseFloat( alignValue.toFixed( 5 ) );
15274         },
15276         _calculateNewMax: function() {
15277                 var max = this.options.max,
15278                         min = this._valueMin(),
15279                         step = this.options.step,
15280                         aboveMin = Math.round( ( max - min ) / step ) * step;
15281                 max = aboveMin + min;
15282                 if ( max > this.options.max ) {
15284                         //If max is not divisible by step, rounding off may increase its value
15285                         max -= step;
15286                 }
15287                 this.max = parseFloat( max.toFixed( this._precision() ) );
15288         },
15290         _precision: function() {
15291                 var precision = this._precisionOf( this.options.step );
15292                 if ( this.options.min !== null ) {
15293                         precision = Math.max( precision, this._precisionOf( this.options.min ) );
15294                 }
15295                 return precision;
15296         },
15298         _precisionOf: function( num ) {
15299                 var str = num.toString(),
15300                         decimal = str.indexOf( "." );
15301                 return decimal === -1 ? 0 : str.length - decimal - 1;
15302         },
15304         _valueMin: function() {
15305                 return this.options.min;
15306         },
15308         _valueMax: function() {
15309                 return this.max;
15310         },
15312         _refreshRange: function( orientation ) {
15313                 if ( orientation === "vertical" ) {
15314                         this.range.css( { "width": "", "left": "" } );
15315                 }
15316                 if ( orientation === "horizontal" ) {
15317                         this.range.css( { "height": "", "bottom": "" } );
15318                 }
15319         },
15321         _refreshValue: function() {
15322                 var lastValPercent, valPercent, value, valueMin, valueMax,
15323                         oRange = this.options.range,
15324                         o = this.options,
15325                         that = this,
15326                         animate = ( !this._animateOff ) ? o.animate : false,
15327                         _set = {};
15329                 if ( this._hasMultipleValues() ) {
15330                         this.handles.each( function( i ) {
15331                                 valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
15332                                         that._valueMin() ) * 100;
15333                                 _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15334                                 $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15335                                 if ( that.options.range === true ) {
15336                                         if ( that.orientation === "horizontal" ) {
15337                                                 if ( i === 0 ) {
15338                                                         that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15339                                                                 left: valPercent + "%"
15340                                                         }, o.animate );
15341                                                 }
15342                                                 if ( i === 1 ) {
15343                                                         that.range[ animate ? "animate" : "css" ]( {
15344                                                                 width: ( valPercent - lastValPercent ) + "%"
15345                                                         }, {
15346                                                                 queue: false,
15347                                                                 duration: o.animate
15348                                                         } );
15349                                                 }
15350                                         } else {
15351                                                 if ( i === 0 ) {
15352                                                         that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15353                                                                 bottom: ( valPercent ) + "%"
15354                                                         }, o.animate );
15355                                                 }
15356                                                 if ( i === 1 ) {
15357                                                         that.range[ animate ? "animate" : "css" ]( {
15358                                                                 height: ( valPercent - lastValPercent ) + "%"
15359                                                         }, {
15360                                                                 queue: false,
15361                                                                 duration: o.animate
15362                                                         } );
15363                                                 }
15364                                         }
15365                                 }
15366                                 lastValPercent = valPercent;
15367                         } );
15368                 } else {
15369                         value = this.value();
15370                         valueMin = this._valueMin();
15371                         valueMax = this._valueMax();
15372                         valPercent = ( valueMax !== valueMin ) ?
15373                                         ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
15374                                         0;
15375                         _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15376                         this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15378                         if ( oRange === "min" && this.orientation === "horizontal" ) {
15379                                 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15380                                         width: valPercent + "%"
15381                                 }, o.animate );
15382                         }
15383                         if ( oRange === "max" && this.orientation === "horizontal" ) {
15384                                 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15385                                         width: ( 100 - valPercent ) + "%"
15386                                 }, o.animate );
15387                         }
15388                         if ( oRange === "min" && this.orientation === "vertical" ) {
15389                                 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15390                                         height: valPercent + "%"
15391                                 }, o.animate );
15392                         }
15393                         if ( oRange === "max" && this.orientation === "vertical" ) {
15394                                 this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15395                                         height: ( 100 - valPercent ) + "%"
15396                                 }, o.animate );
15397                         }
15398                 }
15399         },
15401         _handleEvents: {
15402                 keydown: function( event ) {
15403                         var allowed, curVal, newVal, step,
15404                                 index = $( event.target ).data( "ui-slider-handle-index" );
15406                         switch ( event.keyCode ) {
15407                                 case $.ui.keyCode.HOME:
15408                                 case $.ui.keyCode.END:
15409                                 case $.ui.keyCode.PAGE_UP:
15410                                 case $.ui.keyCode.PAGE_DOWN:
15411                                 case $.ui.keyCode.UP:
15412                                 case $.ui.keyCode.RIGHT:
15413                                 case $.ui.keyCode.DOWN:
15414                                 case $.ui.keyCode.LEFT:
15415                                         event.preventDefault();
15416                                         if ( !this._keySliding ) {
15417                                                 this._keySliding = true;
15418                                                 this._addClass( $( event.target ), null, "ui-state-active" );
15419                                                 allowed = this._start( event, index );
15420                                                 if ( allowed === false ) {
15421                                                         return;
15422                                                 }
15423                                         }
15424                                         break;
15425                         }
15427                         step = this.options.step;
15428                         if ( this._hasMultipleValues() ) {
15429                                 curVal = newVal = this.values( index );
15430                         } else {
15431                                 curVal = newVal = this.value();
15432                         }
15434                         switch ( event.keyCode ) {
15435                                 case $.ui.keyCode.HOME:
15436                                         newVal = this._valueMin();
15437                                         break;
15438                                 case $.ui.keyCode.END:
15439                                         newVal = this._valueMax();
15440                                         break;
15441                                 case $.ui.keyCode.PAGE_UP:
15442                                         newVal = this._trimAlignValue(
15443                                                 curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
15444                                         );
15445                                         break;
15446                                 case $.ui.keyCode.PAGE_DOWN:
15447                                         newVal = this._trimAlignValue(
15448                                                 curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
15449                                         break;
15450                                 case $.ui.keyCode.UP:
15451                                 case $.ui.keyCode.RIGHT:
15452                                         if ( curVal === this._valueMax() ) {
15453                                                 return;
15454                                         }
15455                                         newVal = this._trimAlignValue( curVal + step );
15456                                         break;
15457                                 case $.ui.keyCode.DOWN:
15458                                 case $.ui.keyCode.LEFT:
15459                                         if ( curVal === this._valueMin() ) {
15460                                                 return;
15461                                         }
15462                                         newVal = this._trimAlignValue( curVal - step );
15463                                         break;
15464                         }
15466                         this._slide( event, index, newVal );
15467                 },
15468                 keyup: function( event ) {
15469                         var index = $( event.target ).data( "ui-slider-handle-index" );
15471                         if ( this._keySliding ) {
15472                                 this._keySliding = false;
15473                                 this._stop( event, index );
15474                                 this._change( event, index );
15475                                 this._removeClass( $( event.target ), null, "ui-state-active" );
15476                         }
15477                 }
15478         }
15479 } );
15483  * jQuery UI Sortable 1.13.0
15484  * http://jqueryui.com
15486  * Copyright jQuery Foundation and other contributors
15487  * Released under the MIT license.
15488  * http://jquery.org/license
15489  */
15491 //>>label: Sortable
15492 //>>group: Interactions
15493 //>>description: Enables items in a list to be sorted using the mouse.
15494 //>>docs: http://api.jqueryui.com/sortable/
15495 //>>demos: http://jqueryui.com/sortable/
15496 //>>css.structure: ../../themes/base/sortable.css
15499 var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
15500         version: "1.13.0",
15501         widgetEventPrefix: "sort",
15502         ready: false,
15503         options: {
15504                 appendTo: "parent",
15505                 axis: false,
15506                 connectWith: false,
15507                 containment: false,
15508                 cursor: "auto",
15509                 cursorAt: false,
15510                 dropOnEmpty: true,
15511                 forcePlaceholderSize: false,
15512                 forceHelperSize: false,
15513                 grid: false,
15514                 handle: false,
15515                 helper: "original",
15516                 items: "> *",
15517                 opacity: false,
15518                 placeholder: false,
15519                 revert: false,
15520                 scroll: true,
15521                 scrollSensitivity: 20,
15522                 scrollSpeed: 20,
15523                 scope: "default",
15524                 tolerance: "intersect",
15525                 zIndex: 1000,
15527                 // Callbacks
15528                 activate: null,
15529                 beforeStop: null,
15530                 change: null,
15531                 deactivate: null,
15532                 out: null,
15533                 over: null,
15534                 receive: null,
15535                 remove: null,
15536                 sort: null,
15537                 start: null,
15538                 stop: null,
15539                 update: null
15540         },
15542         _isOverAxis: function( x, reference, size ) {
15543                 return ( x >= reference ) && ( x < ( reference + size ) );
15544         },
15546         _isFloating: function( item ) {
15547                 return ( /left|right/ ).test( item.css( "float" ) ) ||
15548                         ( /inline|table-cell/ ).test( item.css( "display" ) );
15549         },
15551         _create: function() {
15552                 this.containerCache = {};
15553                 this._addClass( "ui-sortable" );
15555                 //Get the items
15556                 this.refresh();
15558                 //Let's determine the parent's offset
15559                 this.offset = this.element.offset();
15561                 //Initialize mouse events for interaction
15562                 this._mouseInit();
15564                 this._setHandleClassName();
15566                 //We're ready to go
15567                 this.ready = true;
15569         },
15571         _setOption: function( key, value ) {
15572                 this._super( key, value );
15574                 if ( key === "handle" ) {
15575                         this._setHandleClassName();
15576                 }
15577         },
15579         _setHandleClassName: function() {
15580                 var that = this;
15581                 this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
15582                 $.each( this.items, function() {
15583                         that._addClass(
15584                                 this.instance.options.handle ?
15585                                         this.item.find( this.instance.options.handle ) :
15586                                         this.item,
15587                                 "ui-sortable-handle"
15588                         );
15589                 } );
15590         },
15592         _destroy: function() {
15593                 this._mouseDestroy();
15595                 for ( var i = this.items.length - 1; i >= 0; i-- ) {
15596                         this.items[ i ].item.removeData( this.widgetName + "-item" );
15597                 }
15599                 return this;
15600         },
15602         _mouseCapture: function( event, overrideHandle ) {
15603                 var currentItem = null,
15604                         validHandle = false,
15605                         that = this;
15607                 if ( this.reverting ) {
15608                         return false;
15609                 }
15611                 if ( this.options.disabled || this.options.type === "static" ) {
15612                         return false;
15613                 }
15615                 //We have to refresh the items data once first
15616                 this._refreshItems( event );
15618                 //Find out if the clicked node (or one of its parents) is a actual item in this.items
15619                 $( event.target ).parents().each( function() {
15620                         if ( $.data( this, that.widgetName + "-item" ) === that ) {
15621                                 currentItem = $( this );
15622                                 return false;
15623                         }
15624                 } );
15625                 if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
15626                         currentItem = $( event.target );
15627                 }
15629                 if ( !currentItem ) {
15630                         return false;
15631                 }
15632                 if ( this.options.handle && !overrideHandle ) {
15633                         $( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
15634                                 if ( this === event.target ) {
15635                                         validHandle = true;
15636                                 }
15637                         } );
15638                         if ( !validHandle ) {
15639                                 return false;
15640                         }
15641                 }
15643                 this.currentItem = currentItem;
15644                 this._removeCurrentsFromItems();
15645                 return true;
15647         },
15649         _mouseStart: function( event, overrideHandle, noActivation ) {
15651                 var i, body,
15652                         o = this.options;
15654                 this.currentContainer = this;
15656                 //We only need to call refreshPositions, because the refreshItems call has been moved to
15657                 // mouseCapture
15658                 this.refreshPositions();
15660                 //Prepare the dragged items parent
15661                 this.appendTo = $( o.appendTo !== "parent" ?
15662                                 o.appendTo :
15663                                 this.currentItem.parent() );
15665                 //Create and append the visible helper
15666                 this.helper = this._createHelper( event );
15668                 //Cache the helper size
15669                 this._cacheHelperProportions();
15671                 /*
15672                  * - Position generation -
15673                  * This block generates everything position related - it's the core of draggables.
15674                  */
15676                 //Cache the margins of the original element
15677                 this._cacheMargins();
15679                 //The element's absolute position on the page minus margins
15680                 this.offset = this.currentItem.offset();
15681                 this.offset = {
15682                         top: this.offset.top - this.margins.top,
15683                         left: this.offset.left - this.margins.left
15684                 };
15686                 $.extend( this.offset, {
15687                         click: { //Where the click happened, relative to the element
15688                                 left: event.pageX - this.offset.left,
15689                                 top: event.pageY - this.offset.top
15690                         },
15692                         // This is a relative to absolute position minus the actual position calculation -
15693                         // only used for relative positioned helper
15694                         relative: this._getRelativeOffset()
15695                 } );
15697                 // After we get the helper offset, but before we get the parent offset we can
15698                 // change the helper's position to absolute
15699                 // TODO: Still need to figure out a way to make relative sorting possible
15700                 this.helper.css( "position", "absolute" );
15701                 this.cssPosition = this.helper.css( "position" );
15703                 //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
15704                 if ( o.cursorAt ) {
15705                         this._adjustOffsetFromHelper( o.cursorAt );
15706                 }
15708                 //Cache the former DOM position
15709                 this.domPosition = {
15710                         prev: this.currentItem.prev()[ 0 ],
15711                         parent: this.currentItem.parent()[ 0 ]
15712                 };
15714                 // If the helper is not the original, hide the original so it's not playing any role during
15715                 // the drag, won't cause anything bad this way
15716                 if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
15717                         this.currentItem.hide();
15718                 }
15720                 //Create the placeholder
15721                 this._createPlaceholder();
15723                 //Get the next scrolling parent
15724                 this.scrollParent = this.placeholder.scrollParent();
15726                 $.extend( this.offset, {
15727                         parent: this._getParentOffset()
15728                 } );
15730                 //Set a containment if given in the options
15731                 if ( o.containment ) {
15732                         this._setContainment();
15733                 }
15735                 if ( o.cursor && o.cursor !== "auto" ) { // cursor option
15736                         body = this.document.find( "body" );
15738                         // Support: IE
15739                         this.storedCursor = body.css( "cursor" );
15740                         body.css( "cursor", o.cursor );
15742                         this.storedStylesheet =
15743                                 $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
15744                 }
15746                 // We need to make sure to grab the zIndex before setting the
15747                 // opacity, because setting the opacity to anything lower than 1
15748                 // causes the zIndex to change from "auto" to 0.
15749                 if ( o.zIndex ) { // zIndex option
15750                         if ( this.helper.css( "zIndex" ) ) {
15751                                 this._storedZIndex = this.helper.css( "zIndex" );
15752                         }
15753                         this.helper.css( "zIndex", o.zIndex );
15754                 }
15756                 if ( o.opacity ) { // opacity option
15757                         if ( this.helper.css( "opacity" ) ) {
15758                                 this._storedOpacity = this.helper.css( "opacity" );
15759                         }
15760                         this.helper.css( "opacity", o.opacity );
15761                 }
15763                 //Prepare scrolling
15764                 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15765                                 this.scrollParent[ 0 ].tagName !== "HTML" ) {
15766                         this.overflowOffset = this.scrollParent.offset();
15767                 }
15769                 //Call callbacks
15770                 this._trigger( "start", event, this._uiHash() );
15772                 //Recache the helper size
15773                 if ( !this._preserveHelperProportions ) {
15774                         this._cacheHelperProportions();
15775                 }
15777                 //Post "activate" events to possible containers
15778                 if ( !noActivation ) {
15779                         for ( i = this.containers.length - 1; i >= 0; i-- ) {
15780                                 this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
15781                         }
15782                 }
15784                 //Prepare possible droppables
15785                 if ( $.ui.ddmanager ) {
15786                         $.ui.ddmanager.current = this;
15787                 }
15789                 if ( $.ui.ddmanager && !o.dropBehaviour ) {
15790                         $.ui.ddmanager.prepareOffsets( this, event );
15791                 }
15793                 this.dragging = true;
15795                 this._addClass( this.helper, "ui-sortable-helper" );
15797                 //Move the helper, if needed
15798                 if ( !this.helper.parent().is( this.appendTo ) ) {
15799                         this.helper.detach().appendTo( this.appendTo );
15801                         //Update position
15802                         this.offset.parent = this._getParentOffset();
15803                 }
15805                 //Generate the original position
15806                 this.position = this.originalPosition = this._generatePosition( event );
15807                 this.originalPageX = event.pageX;
15808                 this.originalPageY = event.pageY;
15809                 this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" );
15811                 this._mouseDrag( event );
15813                 return true;
15815         },
15817         _scroll: function( event ) {
15818                 var o = this.options,
15819                         scrolled = false;
15821                 if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15822                                 this.scrollParent[ 0 ].tagName !== "HTML" ) {
15824                         if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
15825                                         event.pageY < o.scrollSensitivity ) {
15826                                 this.scrollParent[ 0 ].scrollTop =
15827                                         scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
15828                         } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
15829                                 this.scrollParent[ 0 ].scrollTop =
15830                                         scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
15831                         }
15833                         if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
15834                                         event.pageX < o.scrollSensitivity ) {
15835                                 this.scrollParent[ 0 ].scrollLeft = scrolled =
15836                                         this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
15837                         } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
15838                                 this.scrollParent[ 0 ].scrollLeft = scrolled =
15839                                         this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
15840                         }
15842                 } else {
15844                         if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
15845                                 scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
15846                         } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
15847                                         o.scrollSensitivity ) {
15848                                 scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
15849                         }
15851                         if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
15852                                 scrolled = this.document.scrollLeft(
15853                                         this.document.scrollLeft() - o.scrollSpeed
15854                                 );
15855                         } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
15856                                         o.scrollSensitivity ) {
15857                                 scrolled = this.document.scrollLeft(
15858                                         this.document.scrollLeft() + o.scrollSpeed
15859                                 );
15860                         }
15862                 }
15864                 return scrolled;
15865         },
15867         _mouseDrag: function( event ) {
15868                 var i, item, itemElement, intersection,
15869                         o = this.options;
15871                 //Compute the helpers position
15872                 this.position = this._generatePosition( event );
15873                 this.positionAbs = this._convertPositionTo( "absolute" );
15875                 //Set the helper position
15876                 if ( !this.options.axis || this.options.axis !== "y" ) {
15877                         this.helper[ 0 ].style.left = this.position.left + "px";
15878                 }
15879                 if ( !this.options.axis || this.options.axis !== "x" ) {
15880                         this.helper[ 0 ].style.top = this.position.top + "px";
15881                 }
15883                 //Post events to containers
15884                 this._contactContainers( event );
15886                 if ( this.innermostContainer !== null ) {
15888                         //Do scrolling
15889                         if ( o.scroll ) {
15890                                 if ( this._scroll( event ) !== false ) {
15892                                         //Update item positions used in position checks
15893                                         this._refreshItemPositions( true );
15895                                         if ( $.ui.ddmanager && !o.dropBehaviour ) {
15896                                                 $.ui.ddmanager.prepareOffsets( this, event );
15897                                         }
15898                                 }
15899                         }
15901                         this.dragDirection = {
15902                                 vertical: this._getDragVerticalDirection(),
15903                                 horizontal: this._getDragHorizontalDirection()
15904                         };
15906                         //Rearrange
15907                         for ( i = this.items.length - 1; i >= 0; i-- ) {
15909                                 //Cache variables and intersection, continue if no intersection
15910                                 item = this.items[ i ];
15911                                 itemElement = item.item[ 0 ];
15912                                 intersection = this._intersectsWithPointer( item );
15913                                 if ( !intersection ) {
15914                                         continue;
15915                                 }
15917                                 // Only put the placeholder inside the current Container, skip all
15918                                 // items from other containers. This works because when moving
15919                                 // an item from one container to another the
15920                                 // currentContainer is switched before the placeholder is moved.
15921                                 //
15922                                 // Without this, moving items in "sub-sortables" can cause
15923                                 // the placeholder to jitter between the outer and inner container.
15924                                 if ( item.instance !== this.currentContainer ) {
15925                                         continue;
15926                                 }
15928                                 // Cannot intersect with itself
15929                                 // no useless actions that have been done before
15930                                 // no action if the item moved is the parent of the item checked
15931                                 if ( itemElement !== this.currentItem[ 0 ] &&
15932                                         this.placeholder[ intersection === 1 ?
15933                                         "next" : "prev" ]()[ 0 ] !== itemElement &&
15934                                         !$.contains( this.placeholder[ 0 ], itemElement ) &&
15935                                         ( this.options.type === "semi-dynamic" ?
15936                                                 !$.contains( this.element[ 0 ], itemElement ) :
15937                                                 true
15938                                         )
15939                                 ) {
15941                                         this.direction = intersection === 1 ? "down" : "up";
15943                                         if ( this.options.tolerance === "pointer" ||
15944                                                         this._intersectsWithSides( item ) ) {
15945                                                 this._rearrange( event, item );
15946                                         } else {
15947                                                 break;
15948                                         }
15950                                         this._trigger( "change", event, this._uiHash() );
15951                                         break;
15952                                 }
15953                         }
15954                 }
15956                 //Interconnect with droppables
15957                 if ( $.ui.ddmanager ) {
15958                         $.ui.ddmanager.drag( this, event );
15959                 }
15961                 //Call callbacks
15962                 this._trigger( "sort", event, this._uiHash() );
15964                 this.lastPositionAbs = this.positionAbs;
15965                 return false;
15967         },
15969         _mouseStop: function( event, noPropagation ) {
15971                 if ( !event ) {
15972                         return;
15973                 }
15975                 //If we are using droppables, inform the manager about the drop
15976                 if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
15977                         $.ui.ddmanager.drop( this, event );
15978                 }
15980                 if ( this.options.revert ) {
15981                         var that = this,
15982                                 cur = this.placeholder.offset(),
15983                                 axis = this.options.axis,
15984                                 animation = {};
15986                         if ( !axis || axis === "x" ) {
15987                                 animation.left = cur.left - this.offset.parent.left - this.margins.left +
15988                                         ( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15989                                                 0 :
15990                                                 this.offsetParent[ 0 ].scrollLeft
15991                                         );
15992                         }
15993                         if ( !axis || axis === "y" ) {
15994                                 animation.top = cur.top - this.offset.parent.top - this.margins.top +
15995                                         ( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15996                                                 0 :
15997                                                 this.offsetParent[ 0 ].scrollTop
15998                                         );
15999                         }
16000                         this.reverting = true;
16001                         $( this.helper ).animate(
16002                                 animation,
16003                                 parseInt( this.options.revert, 10 ) || 500,
16004                                 function() {
16005                                         that._clear( event );
16006                                 }
16007                         );
16008                 } else {
16009                         this._clear( event, noPropagation );
16010                 }
16012                 return false;
16014         },
16016         cancel: function() {
16018                 if ( this.dragging ) {
16020                         this._mouseUp( new $.Event( "mouseup", { target: null } ) );
16022                         if ( this.options.helper === "original" ) {
16023                                 this.currentItem.css( this._storedCSS );
16024                                 this._removeClass( this.currentItem, "ui-sortable-helper" );
16025                         } else {
16026                                 this.currentItem.show();
16027                         }
16029                         //Post deactivating events to containers
16030                         for ( var i = this.containers.length - 1; i >= 0; i-- ) {
16031                                 this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
16032                                 if ( this.containers[ i ].containerCache.over ) {
16033                                         this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
16034                                         this.containers[ i ].containerCache.over = 0;
16035                                 }
16036                         }
16038                 }
16040                 if ( this.placeholder ) {
16042                         //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
16043                         // it unbinds ALL events from the original node!
16044                         if ( this.placeholder[ 0 ].parentNode ) {
16045                                 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
16046                         }
16047                         if ( this.options.helper !== "original" && this.helper &&
16048                                         this.helper[ 0 ].parentNode ) {
16049                                 this.helper.remove();
16050                         }
16052                         $.extend( this, {
16053                                 helper: null,
16054                                 dragging: false,
16055                                 reverting: false,
16056                                 _noFinalSort: null
16057                         } );
16059                         if ( this.domPosition.prev ) {
16060                                 $( this.domPosition.prev ).after( this.currentItem );
16061                         } else {
16062                                 $( this.domPosition.parent ).prepend( this.currentItem );
16063                         }
16064                 }
16066                 return this;
16068         },
16070         serialize: function( o ) {
16072                 var items = this._getItemsAsjQuery( o && o.connected ),
16073                         str = [];
16074                 o = o || {};
16076                 $( items ).each( function() {
16077                         var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
16078                                 .match( o.expression || ( /(.+)[\-=_](.+)/ ) );
16079                         if ( res ) {
16080                                 str.push(
16081                                         ( o.key || res[ 1 ] + "[]" ) +
16082                                         "=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
16083                         }
16084                 } );
16086                 if ( !str.length && o.key ) {
16087                         str.push( o.key + "=" );
16088                 }
16090                 return str.join( "&" );
16092         },
16094         toArray: function( o ) {
16096                 var items = this._getItemsAsjQuery( o && o.connected ),
16097                         ret = [];
16099                 o = o || {};
16101                 items.each( function() {
16102                         ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
16103                 } );
16104                 return ret;
16106         },
16108         /* Be careful with the following core functions */
16109         _intersectsWith: function( item ) {
16111                 var x1 = this.positionAbs.left,
16112                         x2 = x1 + this.helperProportions.width,
16113                         y1 = this.positionAbs.top,
16114                         y2 = y1 + this.helperProportions.height,
16115                         l = item.left,
16116                         r = l + item.width,
16117                         t = item.top,
16118                         b = t + item.height,
16119                         dyClick = this.offset.click.top,
16120                         dxClick = this.offset.click.left,
16121                         isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
16122                                 ( y1 + dyClick ) < b ),
16123                         isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
16124                                 ( x1 + dxClick ) < r ),
16125                         isOverElement = isOverElementHeight && isOverElementWidth;
16127                 if ( this.options.tolerance === "pointer" ||
16128                         this.options.forcePointerForContainers ||
16129                         ( this.options.tolerance !== "pointer" &&
16130                                 this.helperProportions[ this.floating ? "width" : "height" ] >
16131                                 item[ this.floating ? "width" : "height" ] )
16132                 ) {
16133                         return isOverElement;
16134                 } else {
16136                         return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
16137                                 x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
16138                                 t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
16139                                 y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
16141                 }
16142         },
16144         _intersectsWithPointer: function( item ) {
16145                 var verticalDirection, horizontalDirection,
16146                         isOverElementHeight = ( this.options.axis === "x" ) ||
16147                                 this._isOverAxis(
16148                                         this.positionAbs.top + this.offset.click.top, item.top, item.height ),
16149                         isOverElementWidth = ( this.options.axis === "y" ) ||
16150                                 this._isOverAxis(
16151                                         this.positionAbs.left + this.offset.click.left, item.left, item.width ),
16152                         isOverElement = isOverElementHeight && isOverElementWidth;
16154                 if ( !isOverElement ) {
16155                         return false;
16156                 }
16158                 verticalDirection = this.dragDirection.vertical;
16159                 horizontalDirection = this.dragDirection.horizontal;
16161                 return this.floating ?
16162                         ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) :
16163                         ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
16165         },
16167         _intersectsWithSides: function( item ) {
16169                 var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
16170                                 this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
16171                         isOverRightHalf = this._isOverAxis( this.positionAbs.left +
16172                                 this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
16173                         verticalDirection = this.dragDirection.vertical,
16174                         horizontalDirection = this.dragDirection.horizontal;
16176                 if ( this.floating && horizontalDirection ) {
16177                         return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
16178                                 ( horizontalDirection === "left" && !isOverRightHalf ) );
16179                 } else {
16180                         return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
16181                                 ( verticalDirection === "up" && !isOverBottomHalf ) );
16182                 }
16184         },
16186         _getDragVerticalDirection: function() {
16187                 var delta = this.positionAbs.top - this.lastPositionAbs.top;
16188                 return delta !== 0 && ( delta > 0 ? "down" : "up" );
16189         },
16191         _getDragHorizontalDirection: function() {
16192                 var delta = this.positionAbs.left - this.lastPositionAbs.left;
16193                 return delta !== 0 && ( delta > 0 ? "right" : "left" );
16194         },
16196         refresh: function( event ) {
16197                 this._refreshItems( event );
16198                 this._setHandleClassName();
16199                 this.refreshPositions();
16200                 return this;
16201         },
16203         _connectWith: function() {
16204                 var options = this.options;
16205                 return options.connectWith.constructor === String ?
16206                         [ options.connectWith ] :
16207                         options.connectWith;
16208         },
16210         _getItemsAsjQuery: function( connected ) {
16212                 var i, j, cur, inst,
16213                         items = [],
16214                         queries = [],
16215                         connectWith = this._connectWith();
16217                 if ( connectWith && connected ) {
16218                         for ( i = connectWith.length - 1; i >= 0; i-- ) {
16219                                 cur = $( connectWith[ i ], this.document[ 0 ] );
16220                                 for ( j = cur.length - 1; j >= 0; j-- ) {
16221                                         inst = $.data( cur[ j ], this.widgetFullName );
16222                                         if ( inst && inst !== this && !inst.options.disabled ) {
16223                                                 queries.push( [ typeof inst.options.items === "function" ?
16224                                                         inst.options.items.call( inst.element ) :
16225                                                         $( inst.options.items, inst.element )
16226                                                                 .not( ".ui-sortable-helper" )
16227                                                                 .not( ".ui-sortable-placeholder" ), inst ] );
16228                                         }
16229                                 }
16230                         }
16231                 }
16233                 queries.push( [ typeof this.options.items === "function" ?
16234                         this.options.items
16235                                 .call( this.element, null, { options: this.options, item: this.currentItem } ) :
16236                         $( this.options.items, this.element )
16237                                 .not( ".ui-sortable-helper" )
16238                                 .not( ".ui-sortable-placeholder" ), this ] );
16240                 function addItems() {
16241                         items.push( this );
16242                 }
16243                 for ( i = queries.length - 1; i >= 0; i-- ) {
16244                         queries[ i ][ 0 ].each( addItems );
16245                 }
16247                 return $( items );
16249         },
16251         _removeCurrentsFromItems: function() {
16253                 var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
16255                 this.items = $.grep( this.items, function( item ) {
16256                         for ( var j = 0; j < list.length; j++ ) {
16257                                 if ( list[ j ] === item.item[ 0 ] ) {
16258                                         return false;
16259                                 }
16260                         }
16261                         return true;
16262                 } );
16264         },
16266         _refreshItems: function( event ) {
16268                 this.items = [];
16269                 this.containers = [ this ];
16271                 var i, j, cur, inst, targetData, _queries, item, queriesLength,
16272                         items = this.items,
16273                         queries = [ [ typeof this.options.items === "function" ?
16274                                 this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
16275                                 $( this.options.items, this.element ), this ] ],
16276                         connectWith = this._connectWith();
16278                 //Shouldn't be run the first time through due to massive slow-down
16279                 if ( connectWith && this.ready ) {
16280                         for ( i = connectWith.length - 1; i >= 0; i-- ) {
16281                                 cur = $( connectWith[ i ], this.document[ 0 ] );
16282                                 for ( j = cur.length - 1; j >= 0; j-- ) {
16283                                         inst = $.data( cur[ j ], this.widgetFullName );
16284                                         if ( inst && inst !== this && !inst.options.disabled ) {
16285                                                 queries.push( [ typeof inst.options.items === "function" ?
16286                                                         inst.options.items
16287                                                                 .call( inst.element[ 0 ], event, { item: this.currentItem } ) :
16288                                                         $( inst.options.items, inst.element ), inst ] );
16289                                                 this.containers.push( inst );
16290                                         }
16291                                 }
16292                         }
16293                 }
16295                 for ( i = queries.length - 1; i >= 0; i-- ) {
16296                         targetData = queries[ i ][ 1 ];
16297                         _queries = queries[ i ][ 0 ];
16299                         for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
16300                                 item = $( _queries[ j ] );
16302                                 // Data for target checking (mouse manager)
16303                                 item.data( this.widgetName + "-item", targetData );
16305                                 items.push( {
16306                                         item: item,
16307                                         instance: targetData,
16308                                         width: 0, height: 0,
16309                                         left: 0, top: 0
16310                                 } );
16311                         }
16312                 }
16314         },
16316         _refreshItemPositions: function( fast ) {
16317                 var i, item, t, p;
16319                 for ( i = this.items.length - 1; i >= 0; i-- ) {
16320                         item = this.items[ i ];
16322                         //We ignore calculating positions of all connected containers when we're not over them
16323                         if ( this.currentContainer && item.instance !== this.currentContainer &&
16324                                         item.item[ 0 ] !== this.currentItem[ 0 ] ) {
16325                                 continue;
16326                         }
16328                         t = this.options.toleranceElement ?
16329                                 $( this.options.toleranceElement, item.item ) :
16330                                 item.item;
16332                         if ( !fast ) {
16333                                 item.width = t.outerWidth();
16334                                 item.height = t.outerHeight();
16335                         }
16337                         p = t.offset();
16338                         item.left = p.left;
16339                         item.top = p.top;
16340                 }
16341         },
16343         refreshPositions: function( fast ) {
16345                 // Determine whether items are being displayed horizontally
16346                 this.floating = this.items.length ?
16347                         this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
16348                         false;
16350                 if ( this.innermostContainer !== null ) {
16351                         this._refreshItemPositions( fast );
16352                 }
16354                 var i, p;
16356                 if ( this.options.custom && this.options.custom.refreshContainers ) {
16357                         this.options.custom.refreshContainers.call( this );
16358                 } else {
16359                         for ( i = this.containers.length - 1; i >= 0; i-- ) {
16360                                 p = this.containers[ i ].element.offset();
16361                                 this.containers[ i ].containerCache.left = p.left;
16362                                 this.containers[ i ].containerCache.top = p.top;
16363                                 this.containers[ i ].containerCache.width =
16364                                         this.containers[ i ].element.outerWidth();
16365                                 this.containers[ i ].containerCache.height =
16366                                         this.containers[ i ].element.outerHeight();
16367                         }
16368                 }
16370                 return this;
16371         },
16373         _createPlaceholder: function( that ) {
16374                 that = that || this;
16375                 var className, nodeName,
16376                         o = that.options;
16378                 if ( !o.placeholder || o.placeholder.constructor === String ) {
16379                         className = o.placeholder;
16380                         nodeName = that.currentItem[ 0 ].nodeName.toLowerCase();
16381                         o.placeholder = {
16382                                 element: function() {
16384                                         var element = $( "<" + nodeName + ">", that.document[ 0 ] );
16386                                         that._addClass( element, "ui-sortable-placeholder",
16387                                                         className || that.currentItem[ 0 ].className )
16388                                                 ._removeClass( element, "ui-sortable-helper" );
16390                                         if ( nodeName === "tbody" ) {
16391                                                 that._createTrPlaceholder(
16392                                                         that.currentItem.find( "tr" ).eq( 0 ),
16393                                                         $( "<tr>", that.document[ 0 ] ).appendTo( element )
16394                                                 );
16395                                         } else if ( nodeName === "tr" ) {
16396                                                 that._createTrPlaceholder( that.currentItem, element );
16397                                         } else if ( nodeName === "img" ) {
16398                                                 element.attr( "src", that.currentItem.attr( "src" ) );
16399                                         }
16401                                         if ( !className ) {
16402                                                 element.css( "visibility", "hidden" );
16403                                         }
16405                                         return element;
16406                                 },
16407                                 update: function( container, p ) {
16409                                         // 1. If a className is set as 'placeholder option, we don't force sizes -
16410                                         // the class is responsible for that
16411                                         // 2. The option 'forcePlaceholderSize can be enabled to force it even if a
16412                                         // class name is specified
16413                                         if ( className && !o.forcePlaceholderSize ) {
16414                                                 return;
16415                                         }
16417                                         // If the element doesn't have a actual height or width by itself (without
16418                                         // styles coming from a stylesheet), it receives the inline height and width
16419                                         // from the dragged item. Or, if it's a tbody or tr, it's going to have a height
16420                                         // anyway since we're populating them with <td>s above, but they're unlikely to
16421                                         // be the correct height on their own if the row heights are dynamic, so we'll
16422                                         // always assign the height of the dragged item given forcePlaceholderSize
16423                                         // is true.
16424                                         if ( !p.height() || ( o.forcePlaceholderSize &&
16425                                                         ( nodeName === "tbody" || nodeName === "tr" ) ) ) {
16426                                                 p.height(
16427                                                         that.currentItem.innerHeight() -
16428                                                         parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
16429                                                         parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
16430                                         }
16431                                         if ( !p.width() ) {
16432                                                 p.width(
16433                                                         that.currentItem.innerWidth() -
16434                                                         parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
16435                                                         parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
16436                                         }
16437                                 }
16438                         };
16439                 }
16441                 //Create the placeholder
16442                 that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
16444                 //Append it after the actual current item
16445                 that.currentItem.after( that.placeholder );
16447                 //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
16448                 o.placeholder.update( that, that.placeholder );
16450         },
16452         _createTrPlaceholder: function( sourceTr, targetTr ) {
16453                 var that = this;
16455                 sourceTr.children().each( function() {
16456                         $( "<td>&#160;</td>", that.document[ 0 ] )
16457                                 .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
16458                                 .appendTo( targetTr );
16459                 } );
16460         },
16462         _contactContainers: function( event ) {
16463                 var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
16464                         floating, axis,
16465                         innermostContainer = null,
16466                         innermostIndex = null;
16468                 // Get innermost container that intersects with item
16469                 for ( i = this.containers.length - 1; i >= 0; i-- ) {
16471                         // Never consider a container that's located within the item itself
16472                         if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
16473                                 continue;
16474                         }
16476                         if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
16478                                 // If we've already found a container and it's more "inner" than this, then continue
16479                                 if ( innermostContainer &&
16480                                                 $.contains(
16481                                                         this.containers[ i ].element[ 0 ],
16482                                                         innermostContainer.element[ 0 ] ) ) {
16483                                         continue;
16484                                 }
16486                                 innermostContainer = this.containers[ i ];
16487                                 innermostIndex = i;
16489                         } else {
16491                                 // container doesn't intersect. trigger "out" event if necessary
16492                                 if ( this.containers[ i ].containerCache.over ) {
16493                                         this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
16494                                         this.containers[ i ].containerCache.over = 0;
16495                                 }
16496                         }
16498                 }
16500                 this.innermostContainer = innermostContainer;
16502                 // If no intersecting containers found, return
16503                 if ( !innermostContainer ) {
16504                         return;
16505                 }
16507                 // Move the item into the container if it's not there already
16508                 if ( this.containers.length === 1 ) {
16509                         if ( !this.containers[ innermostIndex ].containerCache.over ) {
16510                                 this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16511                                 this.containers[ innermostIndex ].containerCache.over = 1;
16512                         }
16513                 } else {
16515                         // When entering a new container, we will find the item with the least distance and
16516                         // append our item near it
16517                         dist = 10000;
16518                         itemWithLeastDistance = null;
16519                         floating = innermostContainer.floating || this._isFloating( this.currentItem );
16520                         posProperty = floating ? "left" : "top";
16521                         sizeProperty = floating ? "width" : "height";
16522                         axis = floating ? "pageX" : "pageY";
16524                         for ( j = this.items.length - 1; j >= 0; j-- ) {
16525                                 if ( !$.contains(
16526                                                 this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
16527                                 ) {
16528                                         continue;
16529                                 }
16530                                 if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
16531                                         continue;
16532                                 }
16534                                 cur = this.items[ j ].item.offset()[ posProperty ];
16535                                 nearBottom = false;
16536                                 if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
16537                                         nearBottom = true;
16538                                 }
16540                                 if ( Math.abs( event[ axis ] - cur ) < dist ) {
16541                                         dist = Math.abs( event[ axis ] - cur );
16542                                         itemWithLeastDistance = this.items[ j ];
16543                                         this.direction = nearBottom ? "up" : "down";
16544                                 }
16545                         }
16547                         //Check if dropOnEmpty is enabled
16548                         if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
16549                                 return;
16550                         }
16552                         if ( this.currentContainer === this.containers[ innermostIndex ] ) {
16553                                 if ( !this.currentContainer.containerCache.over ) {
16554                                         this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
16555                                         this.currentContainer.containerCache.over = 1;
16556                                 }
16557                                 return;
16558                         }
16560                         if ( itemWithLeastDistance ) {
16561                                 this._rearrange( event, itemWithLeastDistance, null, true );
16562                         } else {
16563                                 this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
16564                         }
16565                         this._trigger( "change", event, this._uiHash() );
16566                         this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
16567                         this.currentContainer = this.containers[ innermostIndex ];
16569                         //Update the placeholder
16570                         this.options.placeholder.update( this.currentContainer, this.placeholder );
16572                         //Update scrollParent
16573                         this.scrollParent = this.placeholder.scrollParent();
16575                         //Update overflowOffset
16576                         if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16577                                         this.scrollParent[ 0 ].tagName !== "HTML" ) {
16578                                 this.overflowOffset = this.scrollParent.offset();
16579                         }
16581                         this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16582                         this.containers[ innermostIndex ].containerCache.over = 1;
16583                 }
16585         },
16587         _createHelper: function( event ) {
16589                 var o = this.options,
16590                         helper = typeof o.helper === "function" ?
16591                                 $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
16592                                 ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
16594                 //Add the helper to the DOM if that didn't happen already
16595                 if ( !helper.parents( "body" ).length ) {
16596                         this.appendTo[ 0 ].appendChild( helper[ 0 ] );
16597                 }
16599                 if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
16600                         this._storedCSS = {
16601                                 width: this.currentItem[ 0 ].style.width,
16602                                 height: this.currentItem[ 0 ].style.height,
16603                                 position: this.currentItem.css( "position" ),
16604                                 top: this.currentItem.css( "top" ),
16605                                 left: this.currentItem.css( "left" )
16606                         };
16607                 }
16609                 if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
16610                         helper.width( this.currentItem.width() );
16611                 }
16612                 if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
16613                         helper.height( this.currentItem.height() );
16614                 }
16616                 return helper;
16618         },
16620         _adjustOffsetFromHelper: function( obj ) {
16621                 if ( typeof obj === "string" ) {
16622                         obj = obj.split( " " );
16623                 }
16624                 if ( Array.isArray( obj ) ) {
16625                         obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
16626                 }
16627                 if ( "left" in obj ) {
16628                         this.offset.click.left = obj.left + this.margins.left;
16629                 }
16630                 if ( "right" in obj ) {
16631                         this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
16632                 }
16633                 if ( "top" in obj ) {
16634                         this.offset.click.top = obj.top + this.margins.top;
16635                 }
16636                 if ( "bottom" in obj ) {
16637                         this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
16638                 }
16639         },
16641         _getParentOffset: function() {
16643                 //Get the offsetParent and cache its position
16644                 this.offsetParent = this.helper.offsetParent();
16645                 var po = this.offsetParent.offset();
16647                 // This is a special case where we need to modify a offset calculated on start, since the
16648                 // following happened:
16649                 // 1. The position of the helper is absolute, so it's position is calculated based on the
16650                 // next positioned parent
16651                 // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
16652                 // the document, which means that the scroll is included in the initial calculation of the
16653                 // offset of the parent, and never recalculated upon drag
16654                 if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16655                                 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
16656                         po.left += this.scrollParent.scrollLeft();
16657                         po.top += this.scrollParent.scrollTop();
16658                 }
16660                 // This needs to be actually done for all browsers, since pageX/pageY includes this
16661                 // information with an ugly IE fix
16662                 if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ||
16663                                 ( this.offsetParent[ 0 ].tagName &&
16664                                 this.offsetParent[ 0 ].tagName.toLowerCase() === "html" && $.ui.ie ) ) {
16665                         po = { top: 0, left: 0 };
16666                 }
16668                 return {
16669                         top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
16670                         left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
16671                 };
16673         },
16675         _getRelativeOffset: function() {
16677                 if ( this.cssPosition === "relative" ) {
16678                         var p = this.currentItem.position();
16679                         return {
16680                                 top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
16681                                         this.scrollParent.scrollTop(),
16682                                 left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
16683                                         this.scrollParent.scrollLeft()
16684                         };
16685                 } else {
16686                         return { top: 0, left: 0 };
16687                 }
16689         },
16691         _cacheMargins: function() {
16692                 this.margins = {
16693                         left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
16694                         top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
16695                 };
16696         },
16698         _cacheHelperProportions: function() {
16699                 this.helperProportions = {
16700                         width: this.helper.outerWidth(),
16701                         height: this.helper.outerHeight()
16702                 };
16703         },
16705         _setContainment: function() {
16707                 var ce, co, over,
16708                         o = this.options;
16709                 if ( o.containment === "parent" ) {
16710                         o.containment = this.helper[ 0 ].parentNode;
16711                 }
16712                 if ( o.containment === "document" || o.containment === "window" ) {
16713                         this.containment = [
16714                                 0 - this.offset.relative.left - this.offset.parent.left,
16715                                 0 - this.offset.relative.top - this.offset.parent.top,
16716                                 o.containment === "document" ?
16717                                         this.document.width() :
16718                                         this.window.width() - this.helperProportions.width - this.margins.left,
16719                                 ( o.containment === "document" ?
16720                                         ( this.document.height() || document.body.parentNode.scrollHeight ) :
16721                                         this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
16722                                 ) - this.helperProportions.height - this.margins.top
16723                         ];
16724                 }
16726                 if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
16727                         ce = $( o.containment )[ 0 ];
16728                         co = $( o.containment ).offset();
16729                         over = ( $( ce ).css( "overflow" ) !== "hidden" );
16731                         this.containment = [
16732                                 co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
16733                                         ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
16734                                 co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
16735                                         ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
16736                                 co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
16737                                         ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
16738                                         ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
16739                                         this.helperProportions.width - this.margins.left,
16740                                 co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
16741                                         ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
16742                                         ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
16743                                         this.helperProportions.height - this.margins.top
16744                         ];
16745                 }
16747         },
16749         _convertPositionTo: function( d, pos ) {
16751                 if ( !pos ) {
16752                         pos = this.position;
16753                 }
16754                 var mod = d === "absolute" ? 1 : -1,
16755                         scroll = this.cssPosition === "absolute" &&
16756                                 !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16757                                 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16758                                         this.offsetParent :
16759                                         this.scrollParent,
16760                         scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16762                 return {
16763                         top: (
16765                                 // The absolute mouse position
16766                                 pos.top +
16768                                 // Only for relative positioned nodes: Relative offset from element to offset parent
16769                                 this.offset.relative.top * mod +
16771                                 // The offsetParent's offset without borders (offset + border)
16772                                 this.offset.parent.top * mod -
16773                                 ( ( this.cssPosition === "fixed" ?
16774                                         -this.scrollParent.scrollTop() :
16775                                         ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
16776                         ),
16777                         left: (
16779                                 // The absolute mouse position
16780                                 pos.left +
16782                                 // Only for relative positioned nodes: Relative offset from element to offset parent
16783                                 this.offset.relative.left * mod +
16785                                 // The offsetParent's offset without borders (offset + border)
16786                                 this.offset.parent.left * mod   -
16787                                 ( ( this.cssPosition === "fixed" ?
16788                                         -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
16789                                         scroll.scrollLeft() ) * mod )
16790                         )
16791                 };
16793         },
16795         _generatePosition: function( event ) {
16797                 var top, left,
16798                         o = this.options,
16799                         pageX = event.pageX,
16800                         pageY = event.pageY,
16801                         scroll = this.cssPosition === "absolute" &&
16802                                 !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16803                                 $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16804                                         this.offsetParent :
16805                                         this.scrollParent,
16806                                 scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16808                 // This is another very weird special case that only happens for relative elements:
16809                 // 1. If the css position is relative
16810                 // 2. and the scroll parent is the document or similar to the offset parent
16811                 // we have to refresh the relative offset during the scroll so there are no jumps
16812                 if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16813                                 this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
16814                         this.offset.relative = this._getRelativeOffset();
16815                 }
16817                 /*
16818                  * - Position constraining -
16819                  * Constrain the position to a mix of grid, containment.
16820                  */
16822                 if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
16824                         if ( this.containment ) {
16825                                 if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
16826                                         pageX = this.containment[ 0 ] + this.offset.click.left;
16827                                 }
16828                                 if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
16829                                         pageY = this.containment[ 1 ] + this.offset.click.top;
16830                                 }
16831                                 if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
16832                                         pageX = this.containment[ 2 ] + this.offset.click.left;
16833                                 }
16834                                 if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
16835                                         pageY = this.containment[ 3 ] + this.offset.click.top;
16836                                 }
16837                         }
16839                         if ( o.grid ) {
16840                                 top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
16841                                         o.grid[ 1 ] ) * o.grid[ 1 ];
16842                                 pageY = this.containment ?
16843                                         ( ( top - this.offset.click.top >= this.containment[ 1 ] &&
16844                                                 top - this.offset.click.top <= this.containment[ 3 ] ) ?
16845                                                         top :
16846                                                         ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
16847                                                                 top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
16848                                                                 top;
16850                                 left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
16851                                         o.grid[ 0 ] ) * o.grid[ 0 ];
16852                                 pageX = this.containment ?
16853                                         ( ( left - this.offset.click.left >= this.containment[ 0 ] &&
16854                                                 left - this.offset.click.left <= this.containment[ 2 ] ) ?
16855                                                         left :
16856                                                         ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
16857                                                                 left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
16858                                                                 left;
16859                         }
16861                 }
16863                 return {
16864                         top: (
16866                                 // The absolute mouse position
16867                                 pageY -
16869                                 // Click offset (relative to the element)
16870                                 this.offset.click.top -
16872                                 // Only for relative positioned nodes: Relative offset from element to offset parent
16873                                 this.offset.relative.top -
16875                                 // The offsetParent's offset without borders (offset + border)
16876                                 this.offset.parent.top +
16877                                 ( ( this.cssPosition === "fixed" ?
16878                                         -this.scrollParent.scrollTop() :
16879                                         ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
16880                         ),
16881                         left: (
16883                                 // The absolute mouse position
16884                                 pageX -
16886                                 // Click offset (relative to the element)
16887                                 this.offset.click.left -
16889                                 // Only for relative positioned nodes: Relative offset from element to offset parent
16890                                 this.offset.relative.left -
16892                                 // The offsetParent's offset without borders (offset + border)
16893                                 this.offset.parent.left +
16894                                 ( ( this.cssPosition === "fixed" ?
16895                                         -this.scrollParent.scrollLeft() :
16896                                         scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
16897                         )
16898                 };
16900         },
16902         _rearrange: function( event, i, a, hardRefresh ) {
16904                 if ( a ) {
16905                         a[ 0 ].appendChild( this.placeholder[ 0 ] );
16906                 } else {
16907                         i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
16908                                 ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
16909                 }
16911                 //Various things done here to improve the performance:
16912                 // 1. we create a setTimeout, that calls refreshPositions
16913                 // 2. on the instance, we have a counter variable, that get's higher after every append
16914                 // 3. on the local scope, we copy the counter variable, and check in the timeout,
16915                 // if it's still the same
16916                 // 4. this lets only the last addition to the timeout stack through
16917                 this.counter = this.counter ? ++this.counter : 1;
16918                 var counter = this.counter;
16920                 this._delay( function() {
16921                         if ( counter === this.counter ) {
16923                                 //Precompute after each DOM insertion, NOT on mousemove
16924                                 this.refreshPositions( !hardRefresh );
16925                         }
16926                 } );
16928         },
16930         _clear: function( event, noPropagation ) {
16932                 this.reverting = false;
16934                 // We delay all events that have to be triggered to after the point where the placeholder
16935                 // has been removed and everything else normalized again
16936                 var i,
16937                         delayedTriggers = [];
16939                 // We first have to update the dom position of the actual currentItem
16940                 // Note: don't do it if the current item is already removed (by a user), or it gets
16941                 // reappended (see #4088)
16942                 if ( !this._noFinalSort && this.currentItem.parent().length ) {
16943                         this.placeholder.before( this.currentItem );
16944                 }
16945                 this._noFinalSort = null;
16947                 if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
16948                         for ( i in this._storedCSS ) {
16949                                 if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
16950                                         this._storedCSS[ i ] = "";
16951                                 }
16952                         }
16953                         this.currentItem.css( this._storedCSS );
16954                         this._removeClass( this.currentItem, "ui-sortable-helper" );
16955                 } else {
16956                         this.currentItem.show();
16957                 }
16959                 if ( this.fromOutside && !noPropagation ) {
16960                         delayedTriggers.push( function( event ) {
16961                                 this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
16962                         } );
16963                 }
16964                 if ( ( this.fromOutside ||
16965                                 this.domPosition.prev !==
16966                                 this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
16967                                 this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
16969                         // Trigger update callback if the DOM position has changed
16970                         delayedTriggers.push( function( event ) {
16971                                 this._trigger( "update", event, this._uiHash() );
16972                         } );
16973                 }
16975                 // Check if the items Container has Changed and trigger appropriate
16976                 // events.
16977                 if ( this !== this.currentContainer ) {
16978                         if ( !noPropagation ) {
16979                                 delayedTriggers.push( function( event ) {
16980                                         this._trigger( "remove", event, this._uiHash() );
16981                                 } );
16982                                 delayedTriggers.push( ( function( c ) {
16983                                         return function( event ) {
16984                                                 c._trigger( "receive", event, this._uiHash( this ) );
16985                                         };
16986                                 } ).call( this, this.currentContainer ) );
16987                                 delayedTriggers.push( ( function( c ) {
16988                                         return function( event ) {
16989                                                 c._trigger( "update", event, this._uiHash( this ) );
16990                                         };
16991                                 } ).call( this, this.currentContainer ) );
16992                         }
16993                 }
16995                 //Post events to containers
16996                 function delayEvent( type, instance, container ) {
16997                         return function( event ) {
16998                                 container._trigger( type, event, instance._uiHash( instance ) );
16999                         };
17000                 }
17001                 for ( i = this.containers.length - 1; i >= 0; i-- ) {
17002                         if ( !noPropagation ) {
17003                                 delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
17004                         }
17005                         if ( this.containers[ i ].containerCache.over ) {
17006                                 delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
17007                                 this.containers[ i ].containerCache.over = 0;
17008                         }
17009                 }
17011                 //Do what was originally in plugins
17012                 if ( this.storedCursor ) {
17013                         this.document.find( "body" ).css( "cursor", this.storedCursor );
17014                         this.storedStylesheet.remove();
17015                 }
17016                 if ( this._storedOpacity ) {
17017                         this.helper.css( "opacity", this._storedOpacity );
17018                 }
17019                 if ( this._storedZIndex ) {
17020                         this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
17021                 }
17023                 this.dragging = false;
17025                 if ( !noPropagation ) {
17026                         this._trigger( "beforeStop", event, this._uiHash() );
17027                 }
17029                 //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
17030                 // it unbinds ALL events from the original node!
17031                 this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
17033                 if ( !this.cancelHelperRemoval ) {
17034                         if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
17035                                 this.helper.remove();
17036                         }
17037                         this.helper = null;
17038                 }
17040                 if ( !noPropagation ) {
17041                         for ( i = 0; i < delayedTriggers.length; i++ ) {
17043                                 // Trigger all delayed events
17044                                 delayedTriggers[ i ].call( this, event );
17045                         }
17046                         this._trigger( "stop", event, this._uiHash() );
17047                 }
17049                 this.fromOutside = false;
17050                 return !this.cancelHelperRemoval;
17052         },
17054         _trigger: function() {
17055                 if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
17056                         this.cancel();
17057                 }
17058         },
17060         _uiHash: function( _inst ) {
17061                 var inst = _inst || this;
17062                 return {
17063                         helper: inst.helper,
17064                         placeholder: inst.placeholder || $( [] ),
17065                         position: inst.position,
17066                         originalPosition: inst.originalPosition,
17067                         offset: inst.positionAbs,
17068                         item: inst.currentItem,
17069                         sender: _inst ? _inst.element : null
17070                 };
17071         }
17073 } );
17077  * jQuery UI Spinner 1.13.0
17078  * http://jqueryui.com
17080  * Copyright jQuery Foundation and other contributors
17081  * Released under the MIT license.
17082  * http://jquery.org/license
17083  */
17085 //>>label: Spinner
17086 //>>group: Widgets
17087 //>>description: Displays buttons to easily input numbers via the keyboard or mouse.
17088 //>>docs: http://api.jqueryui.com/spinner/
17089 //>>demos: http://jqueryui.com/spinner/
17090 //>>css.structure: ../../themes/base/core.css
17091 //>>css.structure: ../../themes/base/spinner.css
17092 //>>css.theme: ../../themes/base/theme.css
17095 function spinnerModifier( fn ) {
17096         return function() {
17097                 var previous = this.element.val();
17098                 fn.apply( this, arguments );
17099                 this._refresh();
17100                 if ( previous !== this.element.val() ) {
17101                         this._trigger( "change" );
17102                 }
17103         };
17106 $.widget( "ui.spinner", {
17107         version: "1.13.0",
17108         defaultElement: "<input>",
17109         widgetEventPrefix: "spin",
17110         options: {
17111                 classes: {
17112                         "ui-spinner": "ui-corner-all",
17113                         "ui-spinner-down": "ui-corner-br",
17114                         "ui-spinner-up": "ui-corner-tr"
17115                 },
17116                 culture: null,
17117                 icons: {
17118                         down: "ui-icon-triangle-1-s",
17119                         up: "ui-icon-triangle-1-n"
17120                 },
17121                 incremental: true,
17122                 max: null,
17123                 min: null,
17124                 numberFormat: null,
17125                 page: 10,
17126                 step: 1,
17128                 change: null,
17129                 spin: null,
17130                 start: null,
17131                 stop: null
17132         },
17134         _create: function() {
17136                 // handle string values that need to be parsed
17137                 this._setOption( "max", this.options.max );
17138                 this._setOption( "min", this.options.min );
17139                 this._setOption( "step", this.options.step );
17141                 // Only format if there is a value, prevents the field from being marked
17142                 // as invalid in Firefox, see #9573.
17143                 if ( this.value() !== "" ) {
17145                         // Format the value, but don't constrain.
17146                         this._value( this.element.val(), true );
17147                 }
17149                 this._draw();
17150                 this._on( this._events );
17151                 this._refresh();
17153                 // Turning off autocomplete prevents the browser from remembering the
17154                 // value when navigating through history, so we re-enable autocomplete
17155                 // if the page is unloaded before the widget is destroyed. #7790
17156                 this._on( this.window, {
17157                         beforeunload: function() {
17158                                 this.element.removeAttr( "autocomplete" );
17159                         }
17160                 } );
17161         },
17163         _getCreateOptions: function() {
17164                 var options = this._super();
17165                 var element = this.element;
17167                 $.each( [ "min", "max", "step" ], function( i, option ) {
17168                         var value = element.attr( option );
17169                         if ( value != null && value.length ) {
17170                                 options[ option ] = value;
17171                         }
17172                 } );
17174                 return options;
17175         },
17177         _events: {
17178                 keydown: function( event ) {
17179                         if ( this._start( event ) && this._keydown( event ) ) {
17180                                 event.preventDefault();
17181                         }
17182                 },
17183                 keyup: "_stop",
17184                 focus: function() {
17185                         this.previous = this.element.val();
17186                 },
17187                 blur: function( event ) {
17188                         if ( this.cancelBlur ) {
17189                                 delete this.cancelBlur;
17190                                 return;
17191                         }
17193                         this._stop();
17194                         this._refresh();
17195                         if ( this.previous !== this.element.val() ) {
17196                                 this._trigger( "change", event );
17197                         }
17198                 },
17199                 mousewheel: function( event, delta ) {
17200                         var activeElement = $.ui.safeActiveElement( this.document[ 0 ] );
17201                         var isActive = this.element[ 0 ] === activeElement;
17203                         if ( !isActive || !delta ) {
17204                                 return;
17205                         }
17207                         if ( !this.spinning && !this._start( event ) ) {
17208                                 return false;
17209                         }
17211                         this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
17212                         clearTimeout( this.mousewheelTimer );
17213                         this.mousewheelTimer = this._delay( function() {
17214                                 if ( this.spinning ) {
17215                                         this._stop( event );
17216                                 }
17217                         }, 100 );
17218                         event.preventDefault();
17219                 },
17220                 "mousedown .ui-spinner-button": function( event ) {
17221                         var previous;
17223                         // We never want the buttons to have focus; whenever the user is
17224                         // interacting with the spinner, the focus should be on the input.
17225                         // If the input is focused then this.previous is properly set from
17226                         // when the input first received focus. If the input is not focused
17227                         // then we need to set this.previous based on the value before spinning.
17228                         previous = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] ) ?
17229                                 this.previous : this.element.val();
17230                         function checkFocus() {
17231                                 var isActive = this.element[ 0 ] === $.ui.safeActiveElement( this.document[ 0 ] );
17232                                 if ( !isActive ) {
17233                                         this.element.trigger( "focus" );
17234                                         this.previous = previous;
17236                                         // support: IE
17237                                         // IE sets focus asynchronously, so we need to check if focus
17238                                         // moved off of the input because the user clicked on the button.
17239                                         this._delay( function() {
17240                                                 this.previous = previous;
17241                                         } );
17242                                 }
17243                         }
17245                         // Ensure focus is on (or stays on) the text field
17246                         event.preventDefault();
17247                         checkFocus.call( this );
17249                         // Support: IE
17250                         // IE doesn't prevent moving focus even with event.preventDefault()
17251                         // so we set a flag to know when we should ignore the blur event
17252                         // and check (again) if focus moved off of the input.
17253                         this.cancelBlur = true;
17254                         this._delay( function() {
17255                                 delete this.cancelBlur;
17256                                 checkFocus.call( this );
17257                         } );
17259                         if ( this._start( event ) === false ) {
17260                                 return;
17261                         }
17263                         this._repeat( null, $( event.currentTarget )
17264                                 .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17265                 },
17266                 "mouseup .ui-spinner-button": "_stop",
17267                 "mouseenter .ui-spinner-button": function( event ) {
17269                         // button will add ui-state-active if mouse was down while mouseleave and kept down
17270                         if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
17271                                 return;
17272                         }
17274                         if ( this._start( event ) === false ) {
17275                                 return false;
17276                         }
17277                         this._repeat( null, $( event.currentTarget )
17278                                 .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17279                 },
17281                 // TODO: do we really want to consider this a stop?
17282                 // shouldn't we just stop the repeater and wait until mouseup before
17283                 // we trigger the stop event?
17284                 "mouseleave .ui-spinner-button": "_stop"
17285         },
17287         // Support mobile enhanced option and make backcompat more sane
17288         _enhance: function() {
17289                 this.uiSpinner = this.element
17290                         .attr( "autocomplete", "off" )
17291                         .wrap( "<span>" )
17292                         .parent()
17294                                 // Add buttons
17295                                 .append(
17296                                         "<a></a><a></a>"
17297                                 );
17298         },
17300         _draw: function() {
17301                 this._enhance();
17303                 this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
17304                 this._addClass( "ui-spinner-input" );
17306                 this.element.attr( "role", "spinbutton" );
17308                 // Button bindings
17309                 this.buttons = this.uiSpinner.children( "a" )
17310                         .attr( "tabIndex", -1 )
17311                         .attr( "aria-hidden", true )
17312                         .button( {
17313                                 classes: {
17314                                         "ui-button": ""
17315                                 }
17316                         } );
17318                 // TODO: Right now button does not support classes this is already updated in button PR
17319                 this._removeClass( this.buttons, "ui-corner-all" );
17321                 this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
17322                 this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
17323                 this.buttons.first().button( {
17324                         "icon": this.options.icons.up,
17325                         "showLabel": false
17326                 } );
17327                 this.buttons.last().button( {
17328                         "icon": this.options.icons.down,
17329                         "showLabel": false
17330                 } );
17332                 // IE 6 doesn't understand height: 50% for the buttons
17333                 // unless the wrapper has an explicit height
17334                 if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
17335                                 this.uiSpinner.height() > 0 ) {
17336                         this.uiSpinner.height( this.uiSpinner.height() );
17337                 }
17338         },
17340         _keydown: function( event ) {
17341                 var options = this.options,
17342                         keyCode = $.ui.keyCode;
17344                 switch ( event.keyCode ) {
17345                 case keyCode.UP:
17346                         this._repeat( null, 1, event );
17347                         return true;
17348                 case keyCode.DOWN:
17349                         this._repeat( null, -1, event );
17350                         return true;
17351                 case keyCode.PAGE_UP:
17352                         this._repeat( null, options.page, event );
17353                         return true;
17354                 case keyCode.PAGE_DOWN:
17355                         this._repeat( null, -options.page, event );
17356                         return true;
17357                 }
17359                 return false;
17360         },
17362         _start: function( event ) {
17363                 if ( !this.spinning && this._trigger( "start", event ) === false ) {
17364                         return false;
17365                 }
17367                 if ( !this.counter ) {
17368                         this.counter = 1;
17369                 }
17370                 this.spinning = true;
17371                 return true;
17372         },
17374         _repeat: function( i, steps, event ) {
17375                 i = i || 500;
17377                 clearTimeout( this.timer );
17378                 this.timer = this._delay( function() {
17379                         this._repeat( 40, steps, event );
17380                 }, i );
17382                 this._spin( steps * this.options.step, event );
17383         },
17385         _spin: function( step, event ) {
17386                 var value = this.value() || 0;
17388                 if ( !this.counter ) {
17389                         this.counter = 1;
17390                 }
17392                 value = this._adjustValue( value + step * this._increment( this.counter ) );
17394                 if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
17395                         this._value( value );
17396                         this.counter++;
17397                 }
17398         },
17400         _increment: function( i ) {
17401                 var incremental = this.options.incremental;
17403                 if ( incremental ) {
17404                         return typeof incremental === "function" ?
17405                                 incremental( i ) :
17406                                 Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
17407                 }
17409                 return 1;
17410         },
17412         _precision: function() {
17413                 var precision = this._precisionOf( this.options.step );
17414                 if ( this.options.min !== null ) {
17415                         precision = Math.max( precision, this._precisionOf( this.options.min ) );
17416                 }
17417                 return precision;
17418         },
17420         _precisionOf: function( num ) {
17421                 var str = num.toString(),
17422                         decimal = str.indexOf( "." );
17423                 return decimal === -1 ? 0 : str.length - decimal - 1;
17424         },
17426         _adjustValue: function( value ) {
17427                 var base, aboveMin,
17428                         options = this.options;
17430                 // Make sure we're at a valid step
17431                 // - find out where we are relative to the base (min or 0)
17432                 base = options.min !== null ? options.min : 0;
17433                 aboveMin = value - base;
17435                 // - round to the nearest step
17436                 aboveMin = Math.round( aboveMin / options.step ) * options.step;
17438                 // - rounding is based on 0, so adjust back to our base
17439                 value = base + aboveMin;
17441                 // Fix precision from bad JS floating point math
17442                 value = parseFloat( value.toFixed( this._precision() ) );
17444                 // Clamp the value
17445                 if ( options.max !== null && value > options.max ) {
17446                         return options.max;
17447                 }
17448                 if ( options.min !== null && value < options.min ) {
17449                         return options.min;
17450                 }
17452                 return value;
17453         },
17455         _stop: function( event ) {
17456                 if ( !this.spinning ) {
17457                         return;
17458                 }
17460                 clearTimeout( this.timer );
17461                 clearTimeout( this.mousewheelTimer );
17462                 this.counter = 0;
17463                 this.spinning = false;
17464                 this._trigger( "stop", event );
17465         },
17467         _setOption: function( key, value ) {
17468                 var prevValue, first, last;
17470                 if ( key === "culture" || key === "numberFormat" ) {
17471                         prevValue = this._parse( this.element.val() );
17472                         this.options[ key ] = value;
17473                         this.element.val( this._format( prevValue ) );
17474                         return;
17475                 }
17477                 if ( key === "max" || key === "min" || key === "step" ) {
17478                         if ( typeof value === "string" ) {
17479                                 value = this._parse( value );
17480                         }
17481                 }
17482                 if ( key === "icons" ) {
17483                         first = this.buttons.first().find( ".ui-icon" );
17484                         this._removeClass( first, null, this.options.icons.up );
17485                         this._addClass( first, null, value.up );
17486                         last = this.buttons.last().find( ".ui-icon" );
17487                         this._removeClass( last, null, this.options.icons.down );
17488                         this._addClass( last, null, value.down );
17489                 }
17491                 this._super( key, value );
17492         },
17494         _setOptionDisabled: function( value ) {
17495                 this._super( value );
17497                 this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
17498                 this.element.prop( "disabled", !!value );
17499                 this.buttons.button( value ? "disable" : "enable" );
17500         },
17502         _setOptions: spinnerModifier( function( options ) {
17503                 this._super( options );
17504         } ),
17506         _parse: function( val ) {
17507                 if ( typeof val === "string" && val !== "" ) {
17508                         val = window.Globalize && this.options.numberFormat ?
17509                                 Globalize.parseFloat( val, 10, this.options.culture ) : +val;
17510                 }
17511                 return val === "" || isNaN( val ) ? null : val;
17512         },
17514         _format: function( value ) {
17515                 if ( value === "" ) {
17516                         return "";
17517                 }
17518                 return window.Globalize && this.options.numberFormat ?
17519                         Globalize.format( value, this.options.numberFormat, this.options.culture ) :
17520                         value;
17521         },
17523         _refresh: function() {
17524                 this.element.attr( {
17525                         "aria-valuemin": this.options.min,
17526                         "aria-valuemax": this.options.max,
17528                         // TODO: what should we do with values that can't be parsed?
17529                         "aria-valuenow": this._parse( this.element.val() )
17530                 } );
17531         },
17533         isValid: function() {
17534                 var value = this.value();
17536                 // Null is invalid
17537                 if ( value === null ) {
17538                         return false;
17539                 }
17541                 // If value gets adjusted, it's invalid
17542                 return value === this._adjustValue( value );
17543         },
17545         // Update the value without triggering change
17546         _value: function( value, allowAny ) {
17547                 var parsed;
17548                 if ( value !== "" ) {
17549                         parsed = this._parse( value );
17550                         if ( parsed !== null ) {
17551                                 if ( !allowAny ) {
17552                                         parsed = this._adjustValue( parsed );
17553                                 }
17554                                 value = this._format( parsed );
17555                         }
17556                 }
17557                 this.element.val( value );
17558                 this._refresh();
17559         },
17561         _destroy: function() {
17562                 this.element
17563                         .prop( "disabled", false )
17564                         .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
17566                 this.uiSpinner.replaceWith( this.element );
17567         },
17569         stepUp: spinnerModifier( function( steps ) {
17570                 this._stepUp( steps );
17571         } ),
17572         _stepUp: function( steps ) {
17573                 if ( this._start() ) {
17574                         this._spin( ( steps || 1 ) * this.options.step );
17575                         this._stop();
17576                 }
17577         },
17579         stepDown: spinnerModifier( function( steps ) {
17580                 this._stepDown( steps );
17581         } ),
17582         _stepDown: function( steps ) {
17583                 if ( this._start() ) {
17584                         this._spin( ( steps || 1 ) * -this.options.step );
17585                         this._stop();
17586                 }
17587         },
17589         pageUp: spinnerModifier( function( pages ) {
17590                 this._stepUp( ( pages || 1 ) * this.options.page );
17591         } ),
17593         pageDown: spinnerModifier( function( pages ) {
17594                 this._stepDown( ( pages || 1 ) * this.options.page );
17595         } ),
17597         value: function( newVal ) {
17598                 if ( !arguments.length ) {
17599                         return this._parse( this.element.val() );
17600                 }
17601                 spinnerModifier( this._value ).call( this, newVal );
17602         },
17604         widget: function() {
17605                 return this.uiSpinner;
17606         }
17607 } );
17609 // DEPRECATED
17610 // TODO: switch return back to widget declaration at top of file when this is removed
17611 if ( $.uiBackCompat !== false ) {
17613         // Backcompat for spinner html extension points
17614         $.widget( "ui.spinner", $.ui.spinner, {
17615                 _enhance: function() {
17616                         this.uiSpinner = this.element
17617                                 .attr( "autocomplete", "off" )
17618                                 .wrap( this._uiSpinnerHtml() )
17619                                 .parent()
17621                                         // Add buttons
17622                                         .append( this._buttonHtml() );
17623                 },
17624                 _uiSpinnerHtml: function() {
17625                         return "<span>";
17626                 },
17628                 _buttonHtml: function() {
17629                         return "<a></a><a></a>";
17630                 }
17631         } );
17634 var widgetsSpinner = $.ui.spinner;
17638  * jQuery UI Tabs 1.13.0
17639  * http://jqueryui.com
17641  * Copyright jQuery Foundation and other contributors
17642  * Released under the MIT license.
17643  * http://jquery.org/license
17644  */
17646 //>>label: Tabs
17647 //>>group: Widgets
17648 //>>description: Transforms a set of container elements into a tab structure.
17649 //>>docs: http://api.jqueryui.com/tabs/
17650 //>>demos: http://jqueryui.com/tabs/
17651 //>>css.structure: ../../themes/base/core.css
17652 //>>css.structure: ../../themes/base/tabs.css
17653 //>>css.theme: ../../themes/base/theme.css
17656 $.widget( "ui.tabs", {
17657         version: "1.13.0",
17658         delay: 300,
17659         options: {
17660                 active: null,
17661                 classes: {
17662                         "ui-tabs": "ui-corner-all",
17663                         "ui-tabs-nav": "ui-corner-all",
17664                         "ui-tabs-panel": "ui-corner-bottom",
17665                         "ui-tabs-tab": "ui-corner-top"
17666                 },
17667                 collapsible: false,
17668                 event: "click",
17669                 heightStyle: "content",
17670                 hide: null,
17671                 show: null,
17673                 // Callbacks
17674                 activate: null,
17675                 beforeActivate: null,
17676                 beforeLoad: null,
17677                 load: null
17678         },
17680         _isLocal: ( function() {
17681                 var rhash = /#.*$/;
17683                 return function( anchor ) {
17684                         var anchorUrl, locationUrl;
17686                         anchorUrl = anchor.href.replace( rhash, "" );
17687                         locationUrl = location.href.replace( rhash, "" );
17689                         // Decoding may throw an error if the URL isn't UTF-8 (#9518)
17690                         try {
17691                                 anchorUrl = decodeURIComponent( anchorUrl );
17692                         } catch ( error ) {}
17693                         try {
17694                                 locationUrl = decodeURIComponent( locationUrl );
17695                         } catch ( error ) {}
17697                         return anchor.hash.length > 1 && anchorUrl === locationUrl;
17698                 };
17699         } )(),
17701         _create: function() {
17702                 var that = this,
17703                         options = this.options;
17705                 this.running = false;
17707                 this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
17708                 this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
17710                 this._processTabs();
17711                 options.active = this._initialActive();
17713                 // Take disabling tabs via class attribute from HTML
17714                 // into account and update option properly.
17715                 if ( Array.isArray( options.disabled ) ) {
17716                         options.disabled = $.uniqueSort( options.disabled.concat(
17717                                 $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
17718                                         return that.tabs.index( li );
17719                                 } )
17720                         ) ).sort();
17721                 }
17723                 // Check for length avoids error when initializing empty list
17724                 if ( this.options.active !== false && this.anchors.length ) {
17725                         this.active = this._findActive( options.active );
17726                 } else {
17727                         this.active = $();
17728                 }
17730                 this._refresh();
17732                 if ( this.active.length ) {
17733                         this.load( options.active );
17734                 }
17735         },
17737         _initialActive: function() {
17738                 var active = this.options.active,
17739                         collapsible = this.options.collapsible,
17740                         locationHash = location.hash.substring( 1 );
17742                 if ( active === null ) {
17744                         // check the fragment identifier in the URL
17745                         if ( locationHash ) {
17746                                 this.tabs.each( function( i, tab ) {
17747                                         if ( $( tab ).attr( "aria-controls" ) === locationHash ) {
17748                                                 active = i;
17749                                                 return false;
17750                                         }
17751                                 } );
17752                         }
17754                         // Check for a tab marked active via a class
17755                         if ( active === null ) {
17756                                 active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
17757                         }
17759                         // No active tab, set to false
17760                         if ( active === null || active === -1 ) {
17761                                 active = this.tabs.length ? 0 : false;
17762                         }
17763                 }
17765                 // Handle numbers: negative, out of range
17766                 if ( active !== false ) {
17767                         active = this.tabs.index( this.tabs.eq( active ) );
17768                         if ( active === -1 ) {
17769                                 active = collapsible ? false : 0;
17770                         }
17771                 }
17773                 // Don't allow collapsible: false and active: false
17774                 if ( !collapsible && active === false && this.anchors.length ) {
17775                         active = 0;
17776                 }
17778                 return active;
17779         },
17781         _getCreateEventData: function() {
17782                 return {
17783                         tab: this.active,
17784                         panel: !this.active.length ? $() : this._getPanelForTab( this.active )
17785                 };
17786         },
17788         _tabKeydown: function( event ) {
17789                 var focusedTab = $( $.ui.safeActiveElement( this.document[ 0 ] ) ).closest( "li" ),
17790                         selectedIndex = this.tabs.index( focusedTab ),
17791                         goingForward = true;
17793                 if ( this._handlePageNav( event ) ) {
17794                         return;
17795                 }
17797                 switch ( event.keyCode ) {
17798                 case $.ui.keyCode.RIGHT:
17799                 case $.ui.keyCode.DOWN:
17800                         selectedIndex++;
17801                         break;
17802                 case $.ui.keyCode.UP:
17803                 case $.ui.keyCode.LEFT:
17804                         goingForward = false;
17805                         selectedIndex--;
17806                         break;
17807                 case $.ui.keyCode.END:
17808                         selectedIndex = this.anchors.length - 1;
17809                         break;
17810                 case $.ui.keyCode.HOME:
17811                         selectedIndex = 0;
17812                         break;
17813                 case $.ui.keyCode.SPACE:
17815                         // Activate only, no collapsing
17816                         event.preventDefault();
17817                         clearTimeout( this.activating );
17818                         this._activate( selectedIndex );
17819                         return;
17820                 case $.ui.keyCode.ENTER:
17822                         // Toggle (cancel delayed activation, allow collapsing)
17823                         event.preventDefault();
17824                         clearTimeout( this.activating );
17826                         // Determine if we should collapse or activate
17827                         this._activate( selectedIndex === this.options.active ? false : selectedIndex );
17828                         return;
17829                 default:
17830                         return;
17831                 }
17833                 // Focus the appropriate tab, based on which key was pressed
17834                 event.preventDefault();
17835                 clearTimeout( this.activating );
17836                 selectedIndex = this._focusNextTab( selectedIndex, goingForward );
17838                 // Navigating with control/command key will prevent automatic activation
17839                 if ( !event.ctrlKey && !event.metaKey ) {
17841                         // Update aria-selected immediately so that AT think the tab is already selected.
17842                         // Otherwise AT may confuse the user by stating that they need to activate the tab,
17843                         // but the tab will already be activated by the time the announcement finishes.
17844                         focusedTab.attr( "aria-selected", "false" );
17845                         this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
17847                         this.activating = this._delay( function() {
17848                                 this.option( "active", selectedIndex );
17849                         }, this.delay );
17850                 }
17851         },
17853         _panelKeydown: function( event ) {
17854                 if ( this._handlePageNav( event ) ) {
17855                         return;
17856                 }
17858                 // Ctrl+up moves focus to the current tab
17859                 if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
17860                         event.preventDefault();
17861                         this.active.trigger( "focus" );
17862                 }
17863         },
17865         // Alt+page up/down moves focus to the previous/next tab (and activates)
17866         _handlePageNav: function( event ) {
17867                 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
17868                         this._activate( this._focusNextTab( this.options.active - 1, false ) );
17869                         return true;
17870                 }
17871                 if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
17872                         this._activate( this._focusNextTab( this.options.active + 1, true ) );
17873                         return true;
17874                 }
17875         },
17877         _findNextTab: function( index, goingForward ) {
17878                 var lastTabIndex = this.tabs.length - 1;
17880                 function constrain() {
17881                         if ( index > lastTabIndex ) {
17882                                 index = 0;
17883                         }
17884                         if ( index < 0 ) {
17885                                 index = lastTabIndex;
17886                         }
17887                         return index;
17888                 }
17890                 while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
17891                         index = goingForward ? index + 1 : index - 1;
17892                 }
17894                 return index;
17895         },
17897         _focusNextTab: function( index, goingForward ) {
17898                 index = this._findNextTab( index, goingForward );
17899                 this.tabs.eq( index ).trigger( "focus" );
17900                 return index;
17901         },
17903         _setOption: function( key, value ) {
17904                 if ( key === "active" ) {
17906                         // _activate() will handle invalid values and update this.options
17907                         this._activate( value );
17908                         return;
17909                 }
17911                 this._super( key, value );
17913                 if ( key === "collapsible" ) {
17914                         this._toggleClass( "ui-tabs-collapsible", null, value );
17916                         // Setting collapsible: false while collapsed; open first panel
17917                         if ( !value && this.options.active === false ) {
17918                                 this._activate( 0 );
17919                         }
17920                 }
17922                 if ( key === "event" ) {
17923                         this._setupEvents( value );
17924                 }
17926                 if ( key === "heightStyle" ) {
17927                         this._setupHeightStyle( value );
17928                 }
17929         },
17931         _sanitizeSelector: function( hash ) {
17932                 return hash ? hash.replace( /[!"$%&'()*+,.\/:;<=>?@\[\]\^`{|}~]/g, "\\$&" ) : "";
17933         },
17935         refresh: function() {
17936                 var options = this.options,
17937                         lis = this.tablist.children( ":has(a[href])" );
17939                 // Get disabled tabs from class attribute from HTML
17940                 // this will get converted to a boolean if needed in _refresh()
17941                 options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
17942                         return lis.index( tab );
17943                 } );
17945                 this._processTabs();
17947                 // Was collapsed or no tabs
17948                 if ( options.active === false || !this.anchors.length ) {
17949                         options.active = false;
17950                         this.active = $();
17952                 // was active, but active tab is gone
17953                 } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
17955                         // all remaining tabs are disabled
17956                         if ( this.tabs.length === options.disabled.length ) {
17957                                 options.active = false;
17958                                 this.active = $();
17960                         // activate previous tab
17961                         } else {
17962                                 this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
17963                         }
17965                 // was active, active tab still exists
17966                 } else {
17968                         // make sure active index is correct
17969                         options.active = this.tabs.index( this.active );
17970                 }
17972                 this._refresh();
17973         },
17975         _refresh: function() {
17976                 this._setOptionDisabled( this.options.disabled );
17977                 this._setupEvents( this.options.event );
17978                 this._setupHeightStyle( this.options.heightStyle );
17980                 this.tabs.not( this.active ).attr( {
17981                         "aria-selected": "false",
17982                         "aria-expanded": "false",
17983                         tabIndex: -1
17984                 } );
17985                 this.panels.not( this._getPanelForTab( this.active ) )
17986                         .hide()
17987                         .attr( {
17988                                 "aria-hidden": "true"
17989                         } );
17991                 // Make sure one tab is in the tab order
17992                 if ( !this.active.length ) {
17993                         this.tabs.eq( 0 ).attr( "tabIndex", 0 );
17994                 } else {
17995                         this.active
17996                                 .attr( {
17997                                         "aria-selected": "true",
17998                                         "aria-expanded": "true",
17999                                         tabIndex: 0
18000                                 } );
18001                         this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
18002                         this._getPanelForTab( this.active )
18003                                 .show()
18004                                 .attr( {
18005                                         "aria-hidden": "false"
18006                                 } );
18007                 }
18008         },
18010         _processTabs: function() {
18011                 var that = this,
18012                         prevTabs = this.tabs,
18013                         prevAnchors = this.anchors,
18014                         prevPanels = this.panels;
18016                 this.tablist = this._getList().attr( "role", "tablist" );
18017                 this._addClass( this.tablist, "ui-tabs-nav",
18018                         "ui-helper-reset ui-helper-clearfix ui-widget-header" );
18020                 // Prevent users from focusing disabled tabs via click
18021                 this.tablist
18022                         .on( "mousedown" + this.eventNamespace, "> li", function( event ) {
18023                                 if ( $( this ).is( ".ui-state-disabled" ) ) {
18024                                         event.preventDefault();
18025                                 }
18026                         } )
18028                         // Support: IE <9
18029                         // Preventing the default action in mousedown doesn't prevent IE
18030                         // from focusing the element, so if the anchor gets focused, blur.
18031                         // We don't have to worry about focusing the previously focused
18032                         // element since clicking on a non-focusable element should focus
18033                         // the body anyway.
18034                         .on( "focus" + this.eventNamespace, ".ui-tabs-anchor", function() {
18035                                 if ( $( this ).closest( "li" ).is( ".ui-state-disabled" ) ) {
18036                                         this.blur();
18037                                 }
18038                         } );
18040                 this.tabs = this.tablist.find( "> li:has(a[href])" )
18041                         .attr( {
18042                                 role: "tab",
18043                                 tabIndex: -1
18044                         } );
18045                 this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
18047                 this.anchors = this.tabs.map( function() {
18048                         return $( "a", this )[ 0 ];
18049                 } )
18050                         .attr( {
18051                                 tabIndex: -1
18052                         } );
18053                 this._addClass( this.anchors, "ui-tabs-anchor" );
18055                 this.panels = $();
18057                 this.anchors.each( function( i, anchor ) {
18058                         var selector, panel, panelId,
18059                                 anchorId = $( anchor ).uniqueId().attr( "id" ),
18060                                 tab = $( anchor ).closest( "li" ),
18061                                 originalAriaControls = tab.attr( "aria-controls" );
18063                         // Inline tab
18064                         if ( that._isLocal( anchor ) ) {
18065                                 selector = anchor.hash;
18066                                 panelId = selector.substring( 1 );
18067                                 panel = that.element.find( that._sanitizeSelector( selector ) );
18069                         // remote tab
18070                         } else {
18072                                 // If the tab doesn't already have aria-controls,
18073                                 // generate an id by using a throw-away element
18074                                 panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
18075                                 selector = "#" + panelId;
18076                                 panel = that.element.find( selector );
18077                                 if ( !panel.length ) {
18078                                         panel = that._createPanel( panelId );
18079                                         panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
18080                                 }
18081                                 panel.attr( "aria-live", "polite" );
18082                         }
18084                         if ( panel.length ) {
18085                                 that.panels = that.panels.add( panel );
18086                         }
18087                         if ( originalAriaControls ) {
18088                                 tab.data( "ui-tabs-aria-controls", originalAriaControls );
18089                         }
18090                         tab.attr( {
18091                                 "aria-controls": panelId,
18092                                 "aria-labelledby": anchorId
18093                         } );
18094                         panel.attr( "aria-labelledby", anchorId );
18095                 } );
18097                 this.panels.attr( "role", "tabpanel" );
18098                 this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
18100                 // Avoid memory leaks (#10056)
18101                 if ( prevTabs ) {
18102                         this._off( prevTabs.not( this.tabs ) );
18103                         this._off( prevAnchors.not( this.anchors ) );
18104                         this._off( prevPanels.not( this.panels ) );
18105                 }
18106         },
18108         // Allow overriding how to find the list for rare usage scenarios (#7715)
18109         _getList: function() {
18110                 return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
18111         },
18113         _createPanel: function( id ) {
18114                 return $( "<div>" )
18115                         .attr( "id", id )
18116                         .data( "ui-tabs-destroy", true );
18117         },
18119         _setOptionDisabled: function( disabled ) {
18120                 var currentItem, li, i;
18122                 if ( Array.isArray( disabled ) ) {
18123                         if ( !disabled.length ) {
18124                                 disabled = false;
18125                         } else if ( disabled.length === this.anchors.length ) {
18126                                 disabled = true;
18127                         }
18128                 }
18130                 // Disable tabs
18131                 for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
18132                         currentItem = $( li );
18133                         if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
18134                                 currentItem.attr( "aria-disabled", "true" );
18135                                 this._addClass( currentItem, null, "ui-state-disabled" );
18136                         } else {
18137                                 currentItem.removeAttr( "aria-disabled" );
18138                                 this._removeClass( currentItem, null, "ui-state-disabled" );
18139                         }
18140                 }
18142                 this.options.disabled = disabled;
18144                 this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
18145                         disabled === true );
18146         },
18148         _setupEvents: function( event ) {
18149                 var events = {};
18150                 if ( event ) {
18151                         $.each( event.split( " " ), function( index, eventName ) {
18152                                 events[ eventName ] = "_eventHandler";
18153                         } );
18154                 }
18156                 this._off( this.anchors.add( this.tabs ).add( this.panels ) );
18158                 // Always prevent the default action, even when disabled
18159                 this._on( true, this.anchors, {
18160                         click: function( event ) {
18161                                 event.preventDefault();
18162                         }
18163                 } );
18164                 this._on( this.anchors, events );
18165                 this._on( this.tabs, { keydown: "_tabKeydown" } );
18166                 this._on( this.panels, { keydown: "_panelKeydown" } );
18168                 this._focusable( this.tabs );
18169                 this._hoverable( this.tabs );
18170         },
18172         _setupHeightStyle: function( heightStyle ) {
18173                 var maxHeight,
18174                         parent = this.element.parent();
18176                 if ( heightStyle === "fill" ) {
18177                         maxHeight = parent.height();
18178                         maxHeight -= this.element.outerHeight() - this.element.height();
18180                         this.element.siblings( ":visible" ).each( function() {
18181                                 var elem = $( this ),
18182                                         position = elem.css( "position" );
18184                                 if ( position === "absolute" || position === "fixed" ) {
18185                                         return;
18186                                 }
18187                                 maxHeight -= elem.outerHeight( true );
18188                         } );
18190                         this.element.children().not( this.panels ).each( function() {
18191                                 maxHeight -= $( this ).outerHeight( true );
18192                         } );
18194                         this.panels.each( function() {
18195                                 $( this ).height( Math.max( 0, maxHeight -
18196                                         $( this ).innerHeight() + $( this ).height() ) );
18197                         } )
18198                                 .css( "overflow", "auto" );
18199                 } else if ( heightStyle === "auto" ) {
18200                         maxHeight = 0;
18201                         this.panels.each( function() {
18202                                 maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
18203                         } ).height( maxHeight );
18204                 }
18205         },
18207         _eventHandler: function( event ) {
18208                 var options = this.options,
18209                         active = this.active,
18210                         anchor = $( event.currentTarget ),
18211                         tab = anchor.closest( "li" ),
18212                         clickedIsActive = tab[ 0 ] === active[ 0 ],
18213                         collapsing = clickedIsActive && options.collapsible,
18214                         toShow = collapsing ? $() : this._getPanelForTab( tab ),
18215                         toHide = !active.length ? $() : this._getPanelForTab( active ),
18216                         eventData = {
18217                                 oldTab: active,
18218                                 oldPanel: toHide,
18219                                 newTab: collapsing ? $() : tab,
18220                                 newPanel: toShow
18221                         };
18223                 event.preventDefault();
18225                 if ( tab.hasClass( "ui-state-disabled" ) ||
18227                                 // tab is already loading
18228                                 tab.hasClass( "ui-tabs-loading" ) ||
18230                                 // can't switch durning an animation
18231                                 this.running ||
18233                                 // click on active header, but not collapsible
18234                                 ( clickedIsActive && !options.collapsible ) ||
18236                                 // allow canceling activation
18237                                 ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
18238                         return;
18239                 }
18241                 options.active = collapsing ? false : this.tabs.index( tab );
18243                 this.active = clickedIsActive ? $() : tab;
18244                 if ( this.xhr ) {
18245                         this.xhr.abort();
18246                 }
18248                 if ( !toHide.length && !toShow.length ) {
18249                         $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
18250                 }
18252                 if ( toShow.length ) {
18253                         this.load( this.tabs.index( tab ), event );
18254                 }
18255                 this._toggle( event, eventData );
18256         },
18258         // Handles show/hide for selecting tabs
18259         _toggle: function( event, eventData ) {
18260                 var that = this,
18261                         toShow = eventData.newPanel,
18262                         toHide = eventData.oldPanel;
18264                 this.running = true;
18266                 function complete() {
18267                         that.running = false;
18268                         that._trigger( "activate", event, eventData );
18269                 }
18271                 function show() {
18272                         that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
18274                         if ( toShow.length && that.options.show ) {
18275                                 that._show( toShow, that.options.show, complete );
18276                         } else {
18277                                 toShow.show();
18278                                 complete();
18279                         }
18280                 }
18282                 // Start out by hiding, then showing, then completing
18283                 if ( toHide.length && this.options.hide ) {
18284                         this._hide( toHide, this.options.hide, function() {
18285                                 that._removeClass( eventData.oldTab.closest( "li" ),
18286                                         "ui-tabs-active", "ui-state-active" );
18287                                 show();
18288                         } );
18289                 } else {
18290                         this._removeClass( eventData.oldTab.closest( "li" ),
18291                                 "ui-tabs-active", "ui-state-active" );
18292                         toHide.hide();
18293                         show();
18294                 }
18296                 toHide.attr( "aria-hidden", "true" );
18297                 eventData.oldTab.attr( {
18298                         "aria-selected": "false",
18299                         "aria-expanded": "false"
18300                 } );
18302                 // If we're switching tabs, remove the old tab from the tab order.
18303                 // If we're opening from collapsed state, remove the previous tab from the tab order.
18304                 // If we're collapsing, then keep the collapsing tab in the tab order.
18305                 if ( toShow.length && toHide.length ) {
18306                         eventData.oldTab.attr( "tabIndex", -1 );
18307                 } else if ( toShow.length ) {
18308                         this.tabs.filter( function() {
18309                                 return $( this ).attr( "tabIndex" ) === 0;
18310                         } )
18311                                 .attr( "tabIndex", -1 );
18312                 }
18314                 toShow.attr( "aria-hidden", "false" );
18315                 eventData.newTab.attr( {
18316                         "aria-selected": "true",
18317                         "aria-expanded": "true",
18318                         tabIndex: 0
18319                 } );
18320         },
18322         _activate: function( index ) {
18323                 var anchor,
18324                         active = this._findActive( index );
18326                 // Trying to activate the already active panel
18327                 if ( active[ 0 ] === this.active[ 0 ] ) {
18328                         return;
18329                 }
18331                 // Trying to collapse, simulate a click on the current active header
18332                 if ( !active.length ) {
18333                         active = this.active;
18334                 }
18336                 anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
18337                 this._eventHandler( {
18338                         target: anchor,
18339                         currentTarget: anchor,
18340                         preventDefault: $.noop
18341                 } );
18342         },
18344         _findActive: function( index ) {
18345                 return index === false ? $() : this.tabs.eq( index );
18346         },
18348         _getIndex: function( index ) {
18350                 // meta-function to give users option to provide a href string instead of a numerical index.
18351                 if ( typeof index === "string" ) {
18352                         index = this.anchors.index( this.anchors.filter( "[href$='" +
18353                                 $.escapeSelector( index ) + "']" ) );
18354                 }
18356                 return index;
18357         },
18359         _destroy: function() {
18360                 if ( this.xhr ) {
18361                         this.xhr.abort();
18362                 }
18364                 this.tablist
18365                         .removeAttr( "role" )
18366                         .off( this.eventNamespace );
18368                 this.anchors
18369                         .removeAttr( "role tabIndex" )
18370                         .removeUniqueId();
18372                 this.tabs.add( this.panels ).each( function() {
18373                         if ( $.data( this, "ui-tabs-destroy" ) ) {
18374                                 $( this ).remove();
18375                         } else {
18376                                 $( this ).removeAttr( "role tabIndex " +
18377                                         "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
18378                         }
18379                 } );
18381                 this.tabs.each( function() {
18382                         var li = $( this ),
18383                                 prev = li.data( "ui-tabs-aria-controls" );
18384                         if ( prev ) {
18385                                 li
18386                                         .attr( "aria-controls", prev )
18387                                         .removeData( "ui-tabs-aria-controls" );
18388                         } else {
18389                                 li.removeAttr( "aria-controls" );
18390                         }
18391                 } );
18393                 this.panels.show();
18395                 if ( this.options.heightStyle !== "content" ) {
18396                         this.panels.css( "height", "" );
18397                 }
18398         },
18400         enable: function( index ) {
18401                 var disabled = this.options.disabled;
18402                 if ( disabled === false ) {
18403                         return;
18404                 }
18406                 if ( index === undefined ) {
18407                         disabled = false;
18408                 } else {
18409                         index = this._getIndex( index );
18410                         if ( Array.isArray( disabled ) ) {
18411                                 disabled = $.map( disabled, function( num ) {
18412                                         return num !== index ? num : null;
18413                                 } );
18414                         } else {
18415                                 disabled = $.map( this.tabs, function( li, num ) {
18416                                         return num !== index ? num : null;
18417                                 } );
18418                         }
18419                 }
18420                 this._setOptionDisabled( disabled );
18421         },
18423         disable: function( index ) {
18424                 var disabled = this.options.disabled;
18425                 if ( disabled === true ) {
18426                         return;
18427                 }
18429                 if ( index === undefined ) {
18430                         disabled = true;
18431                 } else {
18432                         index = this._getIndex( index );
18433                         if ( $.inArray( index, disabled ) !== -1 ) {
18434                                 return;
18435                         }
18436                         if ( Array.isArray( disabled ) ) {
18437                                 disabled = $.merge( [ index ], disabled ).sort();
18438                         } else {
18439                                 disabled = [ index ];
18440                         }
18441                 }
18442                 this._setOptionDisabled( disabled );
18443         },
18445         load: function( index, event ) {
18446                 index = this._getIndex( index );
18447                 var that = this,
18448                         tab = this.tabs.eq( index ),
18449                         anchor = tab.find( ".ui-tabs-anchor" ),
18450                         panel = this._getPanelForTab( tab ),
18451                         eventData = {
18452                                 tab: tab,
18453                                 panel: panel
18454                         },
18455                         complete = function( jqXHR, status ) {
18456                                 if ( status === "abort" ) {
18457                                         that.panels.stop( false, true );
18458                                 }
18460                                 that._removeClass( tab, "ui-tabs-loading" );
18461                                 panel.removeAttr( "aria-busy" );
18463                                 if ( jqXHR === that.xhr ) {
18464                                         delete that.xhr;
18465                                 }
18466                         };
18468                 // Not remote
18469                 if ( this._isLocal( anchor[ 0 ] ) ) {
18470                         return;
18471                 }
18473                 this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
18475                 // Support: jQuery <1.8
18476                 // jQuery <1.8 returns false if the request is canceled in beforeSend,
18477                 // but as of 1.8, $.ajax() always returns a jqXHR object.
18478                 if ( this.xhr && this.xhr.statusText !== "canceled" ) {
18479                         this._addClass( tab, "ui-tabs-loading" );
18480                         panel.attr( "aria-busy", "true" );
18482                         this.xhr
18483                                 .done( function( response, status, jqXHR ) {
18485                                         // support: jQuery <1.8
18486                                         // http://bugs.jquery.com/ticket/11778
18487                                         setTimeout( function() {
18488                                                 panel.html( response );
18489                                                 that._trigger( "load", event, eventData );
18491                                                 complete( jqXHR, status );
18492                                         }, 1 );
18493                                 } )
18494                                 .fail( function( jqXHR, status ) {
18496                                         // support: jQuery <1.8
18497                                         // http://bugs.jquery.com/ticket/11778
18498                                         setTimeout( function() {
18499                                                 complete( jqXHR, status );
18500                                         }, 1 );
18501                                 } );
18502                 }
18503         },
18505         _ajaxSettings: function( anchor, event, eventData ) {
18506                 var that = this;
18507                 return {
18509                         // Support: IE <11 only
18510                         // Strip any hash that exists to prevent errors with the Ajax request
18511                         url: anchor.attr( "href" ).replace( /#.*$/, "" ),
18512                         beforeSend: function( jqXHR, settings ) {
18513                                 return that._trigger( "beforeLoad", event,
18514                                         $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
18515                         }
18516                 };
18517         },
18519         _getPanelForTab: function( tab ) {
18520                 var id = $( tab ).attr( "aria-controls" );
18521                 return this.element.find( this._sanitizeSelector( "#" + id ) );
18522         }
18523 } );
18525 // DEPRECATED
18526 // TODO: Switch return back to widget declaration at top of file when this is removed
18527 if ( $.uiBackCompat !== false ) {
18529         // Backcompat for ui-tab class (now ui-tabs-tab)
18530         $.widget( "ui.tabs", $.ui.tabs, {
18531                 _processTabs: function() {
18532                         this._superApply( arguments );
18533                         this._addClass( this.tabs, "ui-tab" );
18534                 }
18535         } );
18538 var widgetsTabs = $.ui.tabs;
18542  * jQuery UI Tooltip 1.13.0
18543  * http://jqueryui.com
18545  * Copyright jQuery Foundation and other contributors
18546  * Released under the MIT license.
18547  * http://jquery.org/license
18548  */
18550 //>>label: Tooltip
18551 //>>group: Widgets
18552 //>>description: Shows additional information for any element on hover or focus.
18553 //>>docs: http://api.jqueryui.com/tooltip/
18554 //>>demos: http://jqueryui.com/tooltip/
18555 //>>css.structure: ../../themes/base/core.css
18556 //>>css.structure: ../../themes/base/tooltip.css
18557 //>>css.theme: ../../themes/base/theme.css
18560 $.widget( "ui.tooltip", {
18561         version: "1.13.0",
18562         options: {
18563                 classes: {
18564                         "ui-tooltip": "ui-corner-all ui-widget-shadow"
18565                 },
18566                 content: function() {
18567                         var title = $( this ).attr( "title" );
18569                         // Escape title, since we're going from an attribute to raw HTML
18570                         return $( "<a>" ).text( title ).html();
18571                 },
18572                 hide: true,
18574                 // Disabled elements have inconsistent behavior across browsers (#8661)
18575                 items: "[title]:not([disabled])",
18576                 position: {
18577                         my: "left top+15",
18578                         at: "left bottom",
18579                         collision: "flipfit flip"
18580                 },
18581                 show: true,
18582                 track: false,
18584                 // Callbacks
18585                 close: null,
18586                 open: null
18587         },
18589         _addDescribedBy: function( elem, id ) {
18590                 var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
18591                 describedby.push( id );
18592                 elem
18593                         .data( "ui-tooltip-id", id )
18594                         .attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) );
18595         },
18597         _removeDescribedBy: function( elem ) {
18598                 var id = elem.data( "ui-tooltip-id" ),
18599                         describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
18600                         index = $.inArray( id, describedby );
18602                 if ( index !== -1 ) {
18603                         describedby.splice( index, 1 );
18604                 }
18606                 elem.removeData( "ui-tooltip-id" );
18607                 describedby = String.prototype.trim.call( describedby.join( " " ) );
18608                 if ( describedby ) {
18609                         elem.attr( "aria-describedby", describedby );
18610                 } else {
18611                         elem.removeAttr( "aria-describedby" );
18612                 }
18613         },
18615         _create: function() {
18616                 this._on( {
18617                         mouseover: "open",
18618                         focusin: "open"
18619                 } );
18621                 // IDs of generated tooltips, needed for destroy
18622                 this.tooltips = {};
18624                 // IDs of parent tooltips where we removed the title attribute
18625                 this.parents = {};
18627                 // Append the aria-live region so tooltips announce correctly
18628                 this.liveRegion = $( "<div>" )
18629                         .attr( {
18630                                 role: "log",
18631                                 "aria-live": "assertive",
18632                                 "aria-relevant": "additions"
18633                         } )
18634                         .appendTo( this.document[ 0 ].body );
18635                 this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
18637                 this.disabledTitles = $( [] );
18638         },
18640         _setOption: function( key, value ) {
18641                 var that = this;
18643                 this._super( key, value );
18645                 if ( key === "content" ) {
18646                         $.each( this.tooltips, function( id, tooltipData ) {
18647                                 that._updateContent( tooltipData.element );
18648                         } );
18649                 }
18650         },
18652         _setOptionDisabled: function( value ) {
18653                 this[ value ? "_disable" : "_enable" ]();
18654         },
18656         _disable: function() {
18657                 var that = this;
18659                 // Close open tooltips
18660                 $.each( this.tooltips, function( id, tooltipData ) {
18661                         var event = $.Event( "blur" );
18662                         event.target = event.currentTarget = tooltipData.element[ 0 ];
18663                         that.close( event, true );
18664                 } );
18666                 // Remove title attributes to prevent native tooltips
18667                 this.disabledTitles = this.disabledTitles.add(
18668                         this.element.find( this.options.items ).addBack()
18669                                 .filter( function() {
18670                                         var element = $( this );
18671                                         if ( element.is( "[title]" ) ) {
18672                                                 return element
18673                                                         .data( "ui-tooltip-title", element.attr( "title" ) )
18674                                                         .removeAttr( "title" );
18675                                         }
18676                                 } )
18677                 );
18678         },
18680         _enable: function() {
18682                 // restore title attributes
18683                 this.disabledTitles.each( function() {
18684                         var element = $( this );
18685                         if ( element.data( "ui-tooltip-title" ) ) {
18686                                 element.attr( "title", element.data( "ui-tooltip-title" ) );
18687                         }
18688                 } );
18689                 this.disabledTitles = $( [] );
18690         },
18692         open: function( event ) {
18693                 var that = this,
18694                         target = $( event ? event.target : this.element )
18696                                 // we need closest here due to mouseover bubbling,
18697                                 // but always pointing at the same event target
18698                                 .closest( this.options.items );
18700                 // No element to show a tooltip for or the tooltip is already open
18701                 if ( !target.length || target.data( "ui-tooltip-id" ) ) {
18702                         return;
18703                 }
18705                 if ( target.attr( "title" ) ) {
18706                         target.data( "ui-tooltip-title", target.attr( "title" ) );
18707                 }
18709                 target.data( "ui-tooltip-open", true );
18711                 // Kill parent tooltips, custom or native, for hover
18712                 if ( event && event.type === "mouseover" ) {
18713                         target.parents().each( function() {
18714                                 var parent = $( this ),
18715                                         blurEvent;
18716                                 if ( parent.data( "ui-tooltip-open" ) ) {
18717                                         blurEvent = $.Event( "blur" );
18718                                         blurEvent.target = blurEvent.currentTarget = this;
18719                                         that.close( blurEvent, true );
18720                                 }
18721                                 if ( parent.attr( "title" ) ) {
18722                                         parent.uniqueId();
18723                                         that.parents[ this.id ] = {
18724                                                 element: this,
18725                                                 title: parent.attr( "title" )
18726                                         };
18727                                         parent.attr( "title", "" );
18728                                 }
18729                         } );
18730                 }
18732                 this._registerCloseHandlers( event, target );
18733                 this._updateContent( target, event );
18734         },
18736         _updateContent: function( target, event ) {
18737                 var content,
18738                         contentOption = this.options.content,
18739                         that = this,
18740                         eventType = event ? event.type : null;
18742                 if ( typeof contentOption === "string" || contentOption.nodeType ||
18743                                 contentOption.jquery ) {
18744                         return this._open( event, target, contentOption );
18745                 }
18747                 content = contentOption.call( target[ 0 ], function( response ) {
18749                         // IE may instantly serve a cached response for ajax requests
18750                         // delay this call to _open so the other call to _open runs first
18751                         that._delay( function() {
18753                                 // Ignore async response if tooltip was closed already
18754                                 if ( !target.data( "ui-tooltip-open" ) ) {
18755                                         return;
18756                                 }
18758                                 // JQuery creates a special event for focusin when it doesn't
18759                                 // exist natively. To improve performance, the native event
18760                                 // object is reused and the type is changed. Therefore, we can't
18761                                 // rely on the type being correct after the event finished
18762                                 // bubbling, so we set it back to the previous value. (#8740)
18763                                 if ( event ) {
18764                                         event.type = eventType;
18765                                 }
18766                                 this._open( event, target, response );
18767                         } );
18768                 } );
18769                 if ( content ) {
18770                         this._open( event, target, content );
18771                 }
18772         },
18774         _open: function( event, target, content ) {
18775                 var tooltipData, tooltip, delayedShow, a11yContent,
18776                         positionOption = $.extend( {}, this.options.position );
18778                 if ( !content ) {
18779                         return;
18780                 }
18782                 // Content can be updated multiple times. If the tooltip already
18783                 // exists, then just update the content and bail.
18784                 tooltipData = this._find( target );
18785                 if ( tooltipData ) {
18786                         tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
18787                         return;
18788                 }
18790                 // If we have a title, clear it to prevent the native tooltip
18791                 // we have to check first to avoid defining a title if none exists
18792                 // (we don't want to cause an element to start matching [title])
18793                 //
18794                 // We use removeAttr only for key events, to allow IE to export the correct
18795                 // accessible attributes. For mouse events, set to empty string to avoid
18796                 // native tooltip showing up (happens only when removing inside mouseover).
18797                 if ( target.is( "[title]" ) ) {
18798                         if ( event && event.type === "mouseover" ) {
18799                                 target.attr( "title", "" );
18800                         } else {
18801                                 target.removeAttr( "title" );
18802                         }
18803                 }
18805                 tooltipData = this._tooltip( target );
18806                 tooltip = tooltipData.tooltip;
18807                 this._addDescribedBy( target, tooltip.attr( "id" ) );
18808                 tooltip.find( ".ui-tooltip-content" ).html( content );
18810                 // Support: Voiceover on OS X, JAWS on IE <= 9
18811                 // JAWS announces deletions even when aria-relevant="additions"
18812                 // Voiceover will sometimes re-read the entire log region's contents from the beginning
18813                 this.liveRegion.children().hide();
18814                 a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
18815                 a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
18816                 a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
18817                 a11yContent.appendTo( this.liveRegion );
18819                 function position( event ) {
18820                         positionOption.of = event;
18821                         if ( tooltip.is( ":hidden" ) ) {
18822                                 return;
18823                         }
18824                         tooltip.position( positionOption );
18825                 }
18826                 if ( this.options.track && event && /^mouse/.test( event.type ) ) {
18827                         this._on( this.document, {
18828                                 mousemove: position
18829                         } );
18831                         // trigger once to override element-relative positioning
18832                         position( event );
18833                 } else {
18834                         tooltip.position( $.extend( {
18835                                 of: target
18836                         }, this.options.position ) );
18837                 }
18839                 tooltip.hide();
18841                 this._show( tooltip, this.options.show );
18843                 // Handle tracking tooltips that are shown with a delay (#8644). As soon
18844                 // as the tooltip is visible, position the tooltip using the most recent
18845                 // event.
18846                 // Adds the check to add the timers only when both delay and track options are set (#14682)
18847                 if ( this.options.track && this.options.show && this.options.show.delay ) {
18848                         delayedShow = this.delayedShow = setInterval( function() {
18849                                 if ( tooltip.is( ":visible" ) ) {
18850                                         position( positionOption.of );
18851                                         clearInterval( delayedShow );
18852                                 }
18853                         }, 13 );
18854                 }
18856                 this._trigger( "open", event, { tooltip: tooltip } );
18857         },
18859         _registerCloseHandlers: function( event, target ) {
18860                 var events = {
18861                         keyup: function( event ) {
18862                                 if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
18863                                         var fakeEvent = $.Event( event );
18864                                         fakeEvent.currentTarget = target[ 0 ];
18865                                         this.close( fakeEvent, true );
18866                                 }
18867                         }
18868                 };
18870                 // Only bind remove handler for delegated targets. Non-delegated
18871                 // tooltips will handle this in destroy.
18872                 if ( target[ 0 ] !== this.element[ 0 ] ) {
18873                         events.remove = function() {
18874                                 this._removeTooltip( this._find( target ).tooltip );
18875                         };
18876                 }
18878                 if ( !event || event.type === "mouseover" ) {
18879                         events.mouseleave = "close";
18880                 }
18881                 if ( !event || event.type === "focusin" ) {
18882                         events.focusout = "close";
18883                 }
18884                 this._on( true, target, events );
18885         },
18887         close: function( event ) {
18888                 var tooltip,
18889                         that = this,
18890                         target = $( event ? event.currentTarget : this.element ),
18891                         tooltipData = this._find( target );
18893                 // The tooltip may already be closed
18894                 if ( !tooltipData ) {
18896                         // We set ui-tooltip-open immediately upon open (in open()), but only set the
18897                         // additional data once there's actually content to show (in _open()). So even if the
18898                         // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
18899                         // the period between open() and _open().
18900                         target.removeData( "ui-tooltip-open" );
18901                         return;
18902                 }
18904                 tooltip = tooltipData.tooltip;
18906                 // Disabling closes the tooltip, so we need to track when we're closing
18907                 // to avoid an infinite loop in case the tooltip becomes disabled on close
18908                 if ( tooltipData.closing ) {
18909                         return;
18910                 }
18912                 // Clear the interval for delayed tracking tooltips
18913                 clearInterval( this.delayedShow );
18915                 // Only set title if we had one before (see comment in _open())
18916                 // If the title attribute has changed since open(), don't restore
18917                 if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
18918                         target.attr( "title", target.data( "ui-tooltip-title" ) );
18919                 }
18921                 this._removeDescribedBy( target );
18923                 tooltipData.hiding = true;
18924                 tooltip.stop( true );
18925                 this._hide( tooltip, this.options.hide, function() {
18926                         that._removeTooltip( $( this ) );
18927                 } );
18929                 target.removeData( "ui-tooltip-open" );
18930                 this._off( target, "mouseleave focusout keyup" );
18932                 // Remove 'remove' binding only on delegated targets
18933                 if ( target[ 0 ] !== this.element[ 0 ] ) {
18934                         this._off( target, "remove" );
18935                 }
18936                 this._off( this.document, "mousemove" );
18938                 if ( event && event.type === "mouseleave" ) {
18939                         $.each( this.parents, function( id, parent ) {
18940                                 $( parent.element ).attr( "title", parent.title );
18941                                 delete that.parents[ id ];
18942                         } );
18943                 }
18945                 tooltipData.closing = true;
18946                 this._trigger( "close", event, { tooltip: tooltip } );
18947                 if ( !tooltipData.hiding ) {
18948                         tooltipData.closing = false;
18949                 }
18950         },
18952         _tooltip: function( element ) {
18953                 var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
18954                         content = $( "<div>" ).appendTo( tooltip ),
18955                         id = tooltip.uniqueId().attr( "id" );
18957                 this._addClass( content, "ui-tooltip-content" );
18958                 this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
18960                 tooltip.appendTo( this._appendTo( element ) );
18962                 return this.tooltips[ id ] = {
18963                         element: element,
18964                         tooltip: tooltip
18965                 };
18966         },
18968         _find: function( target ) {
18969                 var id = target.data( "ui-tooltip-id" );
18970                 return id ? this.tooltips[ id ] : null;
18971         },
18973         _removeTooltip: function( tooltip ) {
18975                 // Clear the interval for delayed tracking tooltips
18976                 clearInterval( this.delayedShow );
18978                 tooltip.remove();
18979                 delete this.tooltips[ tooltip.attr( "id" ) ];
18980         },
18982         _appendTo: function( target ) {
18983                 var element = target.closest( ".ui-front, dialog" );
18985                 if ( !element.length ) {
18986                         element = this.document[ 0 ].body;
18987                 }
18989                 return element;
18990         },
18992         _destroy: function() {
18993                 var that = this;
18995                 // Close open tooltips
18996                 $.each( this.tooltips, function( id, tooltipData ) {
18998                         // Delegate to close method to handle common cleanup
18999                         var event = $.Event( "blur" ),
19000                                 element = tooltipData.element;
19001                         event.target = event.currentTarget = element[ 0 ];
19002                         that.close( event, true );
19004                         // Remove immediately; destroying an open tooltip doesn't use the
19005                         // hide animation
19006                         $( "#" + id ).remove();
19008                         // Restore the title
19009                         if ( element.data( "ui-tooltip-title" ) ) {
19011                                 // If the title attribute has changed since open(), don't restore
19012                                 if ( !element.attr( "title" ) ) {
19013                                         element.attr( "title", element.data( "ui-tooltip-title" ) );
19014                                 }
19015                                 element.removeData( "ui-tooltip-title" );
19016                         }
19017                 } );
19018                 this.liveRegion.remove();
19019         }
19020 } );
19022 // DEPRECATED
19023 // TODO: Switch return back to widget declaration at top of file when this is removed
19024 if ( $.uiBackCompat !== false ) {
19026         // Backcompat for tooltipClass option
19027         $.widget( "ui.tooltip", $.ui.tooltip, {
19028                 options: {
19029                         tooltipClass: null
19030                 },
19031                 _tooltip: function() {
19032                         var tooltipData = this._superApply( arguments );
19033                         if ( this.options.tooltipClass ) {
19034                                 tooltipData.tooltip.addClass( this.options.tooltipClass );
19035                         }
19036                         return tooltipData;
19037                 }
19038         } );
19041 var widgetsTooltip = $.ui.tooltip;
19046 } );