PageSourceSearch

https://www.hangeul.go.kr/js/user/jquery-ui.js

js hangeul.go.kr collected 2026-10-02 06:05:04 UTC 665,697 bytes, 18,819 lines download raw bytes

vendor: 575,188 bytes, lines 1-16243
1/*! jQuery UI - v1.14.1 - 2024-10-30
2* https://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 OpenJS Foundation and other contributors; Licensed MIT */
5
6( function( factory ) {
7    "use strict";
8
9    if ( typeof define === "function" && define.amd ) {
10
11        // AMD. Register as an anonymous module.
12        define( [ "jquery" ], factory );
13    } else {
14
15        // Browser globals
16        factory( jQuery );
17    }
18} )( function( $ ) {
19"use strict";
20
21$.ui = $.ui || {};
22
23var version = $.ui.version = "1.14.1";
24
25
26/*!
27 * jQuery UI Widget 1.14.1
28 * https://jqueryui.com
29 *
30 * Copyright OpenJS Foundation and other contributors
31 * Released under the MIT license.
32 * https://jquery.org/license
33 */
34
35//>>label: Widget
36//>>group: Core
37//>>description: Provides a factory for creating stateful widgets with a common API.
38//>>docs: https://api.jqueryui.com/jQuery.widget/
39//>>demos: https://jqueryui.com/widget/
40
41
42var widgetUuid = 0;
43var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
44var widgetSlice = Array.prototype.slice;
45
46$.cleanData = ( function( orig ) {
47    return function( elems ) {
48        var events, elem, i;
49        for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
50
51            // Only trigger remove when necessary to save time
52            events = $._data( elem, "events" );
53            if ( events && events.remove ) {
54                $( elem ).triggerHandler( "remove" );
55            }
56        }
57        orig( elems );
58    };
59} )( $.cleanData );
60
61$.widget = function( name, base, prototype ) {
62    var existingConstructor, constructor, basePrototype;
63
64    // ProxiedPrototype allows the provided prototype to remain unmodified
65    // so that it can be used as a mixin for multiple widgets (#8876)
66    var proxiedPrototype = {};
67
68    var namespace = name.split( "." )[ 0 ];
69    name = name.split( "." )[ 1 ];
70    if ( name === "__proto__" || name === "constructor" ) {
71        return $.error( "Invalid widget name: " + name );
72    }
73    var fullName = namespace + "-" + name;
74
75    if ( !prototype ) {
76        prototype = base;
77        base = $.Widget;
78    }
79
80    if ( Array.isArray( prototype ) ) {
81        prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
82    }
83
84    // Create selector for plugin
85    $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
86        return !!$.data( elem, fullName );
87    };
88
89    $[ namespace ] = $[ namespace ] || {};
90    existingConstructor = $[ namespace ][ name ];
91    constructor = $[ namespace ][ name ] = function( options, element ) {
92
93        // Allow instantiation without "new" keyword
94        if ( !this || !this._createWidget ) {
95            return new constructor( options, element );
96        }
97
98        // Allow instantiation without initializing for simple inheritance
99        // must use "new" keyword (the code above always passes args)
100        if ( arguments.length ) {
101            this._createWidget( options, element );
102        }
103    };
104
105    // Extend with the existing constructor to carry over any static properties
106    $.extend( constructor, existingConstructor, {
107        version: prototype.version,
108
109        // Copy the object used to create the prototype in case we need to
110        // redefine the widget later
111        _proto: $.extend( {}, prototype ),
112
113        // Track widgets that inherit from this widget in case this widget is
114        // redefined after a widget inherits from it
115        _childConstructors: []
116    } );
117
118    basePrototype = new base();
119
120    // We need to make the options hash a property directly on the new instance
121    // otherwise we'll modify the options hash on the prototype that we're
122    // inheriting from
123    basePrototype.options = $.widget.extend( {}, basePrototype.options );
124    $.each( prototype, function( prop, value ) {
125        if ( typeof value !== "function" ) {
126            proxiedPrototype[ prop ] = value;
127            return;
128        }
129        proxiedPrototype[ prop ] = ( function() {
130            function _super() {
131                return base.prototype[ prop ].apply( this, arguments );
132            }
133
134            function _superApply( args ) {
135                return base.prototype[ prop ].apply( this, args );
136            }
137
138            return function() {
139                var __super = this._super;
140                var __superApply = this._superApply;
141                var returnValue;
142
143                this._super = _super;
144                this._superApply = _superApply;
145
146                returnValue = value.apply( this, arguments );
147
148                this._super = __super;
149                this._superApply = __superApply;
150
151                return returnValue;
152            };
153        } )();
154    } );
155    constructor.prototype = $.widget.extend( basePrototype, {
156
157        // TODO: remove support for widgetEventPrefix
158        // always use the name + a colon as the prefix, e.g., draggable:start
159        // don't prefix for widgets that aren't DOM-based
160        widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
161    }, proxiedPrototype, {
162        constructor: constructor,
163        namespace: namespace,
164        widgetName: name,
165        widgetFullName: fullName
166    } );
167
168    // If this widget is being redefined then we need to find all widgets that
169    // are inheriting from it and redefine all of them so that they inherit from
170    // the new version of this widget. We're essentially trying to replace one
171    // level in the prototype chain.
172    if ( existingConstructor ) {
173        $.each( existingConstructor._childConstructors, function( i, child ) {
174            var childPrototype = child.prototype;
175
176            // Redefine the child widget using the same prototype that was
177            // originally used, but inherit from the new version of the base
178            $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
179                child._proto );
180        } );
181
182        // Remove the list of existing child constructors from the old constructor
183        // so the old child constructors can be garbage collected
184        delete existingConstructor._childConstructors;
185    } else {
186        base._childConstructors.push( constructor );
187    }
188
189    $.widget.bridge( name, constructor );
190
191    return constructor;
192};
193
194$.widget.extend = function( target ) {
195    var input = widgetSlice.call( arguments, 1 );
196    var inputIndex = 0;
197    var inputLength = input.length;
198    var key;
199    var value;
200
201    for ( ; inputIndex < inputLength; inputIndex++ ) {
202        for ( key in input[ inputIndex ] ) {
203            value = input[ inputIndex ][ key ];
204            if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
205
206                // Clone objects
207                if ( $.isPlainObject( value ) ) {
208                    target[ key ] = $.isPlainObject( target[ key ] ) ?
209                        $.widget.extend( {}, target[ key ], value ) :
210
211                        // Don't extend strings, arrays, etc. with objects
212                        $.widget.extend( {}, value );
213
214                // Copy everything else by reference
215                } else {
216                    target[ key ] = value;
217                }
218            }
219        }
220    }
221    return target;
222};
223
224$.widget.bridge = function( name, object ) {
225    var fullName = object.prototype.widgetFullName || name;
226    $.fn[ name ] = function( options ) {
227        var isMethodCall = typeof options === "string";
228        var args = widgetSlice.call( arguments, 1 );
229        var returnValue = this;
230
231        if ( isMethodCall ) {
232
233            // If this is an empty collection, we need to have the instance method
234            // return undefined instead of the jQuery instance
235            if ( !this.length && options === "instance" ) {
236                returnValue = undefined;
237            } else {
238                this.each( function() {
239                    var methodValue;
240                    var instance = $.data( this, fullName );
241
242                    if ( options === "instance" ) {
243                        returnValue = instance;
244                        return false;
245                    }
246
247                    if ( !instance ) {
248                        return $.error( "cannot call methods on " + name +
249                            " prior to initialization; " +
250                            "attempted to call method '" + options + "'" );
251                    }
252
253                    if ( typeof instance[ options ] !== "function" ||
254                        options.charAt( 0 ) === "_" ) {
255                        return $.error( "no such method '" + options + "' for " + name +
256                            " widget instance" );
257                    }
258
259                    methodValue = instance[ options ].apply( instance, args );
260
261                    if ( methodValue !== instance && methodValue !== undefined ) {
262                        returnValue = methodValue && methodValue.jquery ?
263                            returnValue.pushStack( methodValue.get() ) :
264                            methodValue;
265                        return false;
266                    }
267                } );
268            }
269        } else {
270
271            // Allow multiple hashes to be passed on init
272            if ( args.length ) {
273                options = $.widget.extend.apply( null, [ options ].concat( args ) );
274            }
275
276            this.each( function() {
277                var instance = $.data( this, fullName );
278                if ( instance ) {
279                    instance.option( options || {} );
280                    if ( instance._init ) {
281                        instance._init();
282                    }
283                } else {
284                    $.data( this, fullName, new object( options, this ) );
285                }
286            } );
287        }
288
289        return returnValue;
290    };
291};
292
293$.Widget = function( /* options, element */ ) {};
294$.Widget._childConstructors = [];
295
296$.Widget.prototype = {
297    widgetName: "widget",
298    widgetEventPrefix: "",
299    defaultElement: "<div>",
300
301    options: {
302        classes: {},
303        disabled: false,
304
305        // Callbacks
306        create: null
307    },
308
309    _createWidget: function( options, element ) {
310        element = $( element || this.defaultElement || this )[ 0 ];
311        this.element = $( element );
312        this.uuid = widgetUuid++;
313        this.eventNamespace = "." + this.widgetName + this.uuid;
314
315        this.bindings = $();
316        this.hoverable = $();
317        this.focusable = $();
318        this.classesElementLookup = {};
319
320        if ( element !== this ) {
321            $.data( element, this.widgetFullName, this );
322            this._on( true, this.element, {
323                remove: function( event ) {
324                    if ( event.target === element ) {
325                        this.destroy();
326                    }
327                }
328            } );
329            this.document = $( element.style ?
330
331                // Element within the document
332                element.ownerDocument :
333
334                // Element is window or document
335                element.document || element );
336            this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
337        }
338
339        this.options = $.widget.extend( {},
340            this.options,
341            this._getCreateOptions(),
342            options );
343
344        this._create();
345
346        if ( this.options.disabled ) {
347            this._setOptionDisabled( this.options.disabled );
348        }
349
350        this._trigger( "create", null, this._getCreateEventData() );
351        this._init();
352    },
353
354    _getCreateOptions: function() {
355        return {};
356    },
357
358    _getCreateEventData: $.noop,
359
360    _create: $.noop,
361
362    _init: $.noop,
363
364    destroy: function() {
365        var that = this;
366
367        this._destroy();
368        $.each( this.classesElementLookup, function( key, value ) {
369            that._removeClass( value, key );
370        } );
371
372        // We can probably remove the unbind calls in 2.0
373        // all event bindings should go through this._on()
374        this.element
375            .off( this.eventNamespace )
376            .removeData( this.widgetFullName );
377        this.widget()
378            .off( this.eventNamespace )
379            .removeAttr( "aria-disabled" );
380
381        // Clean up events and states
382        this.bindings.off( this.eventNamespace );
383    },
384
385    _destroy: $.noop,
386
387    widget: function() {
388        return this.element;
389    },
390
391    option: function( key, value ) {
392        var options = key;
393        var parts;
394        var curOption;
395        var i;
396
397        if ( arguments.length === 0 ) {
398
399            // Don't return a reference to the internal hash
400            return $.widget.extend( {}, this.options );
401        }
402
403        if ( typeof key === "string" ) {
404
405            // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
406            options = {};
407            parts = key.split( "." );
408            key = parts.shift();
409            if ( parts.length ) {
410                curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
411                for ( i = 0; i < parts.length - 1; i++ ) {
412                    curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
413                    curOption = curOption[ parts[ i ] ];
414                }
415                key = parts.pop();
416                if ( arguments.length === 1 ) {
417                    return curOption[ key ] === undefined ? null : curOption[ key ];
418                }
419                curOption[ key ] = value;
420            } else {
421                if ( arguments.length === 1 ) {
422                    return this.options[ key ] === undefined ? null : this.options[ key ];
423                }
424                options[ key ] = value;
425            }
426        }
427
428        this._setOptions( options );
429
430        return this;
431    },
432
433    _setOptions: function( options ) {
434        var key;
435
436        for ( key in options ) {
437            this._setOption( key, options[ key ] );
438        }
439
440        return this;
441    },
442
443    _setOption: function( key, value ) {
444        if ( key === "classes" ) {
445            this._setOptionClasses( value );
446        }
447
448        this.options[ key ] = value;
449
450        if ( key === "disabled" ) {
451            this._setOptionDisabled( value );
452        }
453
454        return this;
455    },
456
457    _setOptionClasses: function( value ) {
458        var classKey, elements, currentElements;
459
460        for ( classKey in value ) {
461            currentElements = this.classesElementLookup[ classKey ];
462            if ( value[ classKey ] === this.options.classes[ classKey ] ||
463                    !currentElements ||
464                    !currentElements.length ) {
465                continue;
466            }
467
468            // We are doing this to create a new jQuery object because the _removeClass() call
469            // on the next line is going to destroy the reference to the current elements being
470            // tracked. We need to save a copy of this collection so that we can add the new classes
471            // below.
472            elements = $( currentElements.get() );
473            this._removeClass( currentElements, classKey );
474
475            // We don't use _addClass() here, because that uses this.options.classes
476            // for generating the string of classes. We want to use the value passed in from
477            // _setOption(), this is the new value of the classes option which was passed to
478            // _setOption(). We pass this value directly to _classes().
479            elements.addClass( this._classes( {
480                element: elements,
481                keys: classKey,
482                classes: value,
483                add: true
484            } ) );
485        }
486    },
487
488    _setOptionDisabled: function( value ) {
489        this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
490
491        // If the widget is becoming disabled, then nothing is interactive
492        if ( value ) {
493            this._removeClass( this.hoverable, null, "ui-state-hover" );
494            this._removeClass( this.focusable, null, "ui-state-focus" );
495        }
496    },
497
498    enable: function() {
499        return this._setOptions( { disabled: false } );
500    },
501
502    disable: function() {
503        return this._setOptions( { disabled: true } );
504    },
505
506    _classes: function( options ) {
507        var full = [];
508        var that = this;
509
510        options = $.extend( {
511            element: this.element,
512            classes: this.options.classes || {}
513        }, options );
514
515        function bindRemoveEvent() {
516            var nodesToBind = [];
517
518            options.element.each( function( _, element ) {
519                var isTracked = $.map( that.classesElementLookup, function( elements ) {
520                    return elements;
521                } )
522                    .some( function( elements ) {
523                        return elements.is( element );
524                    } );
525
526                if ( !isTracked ) {
527                    nodesToBind.push( element );
528                }
529            } );
530
531            that._on( $( nodesToBind ), {
532                remove: "_untrackClassesElement"
533            } );
534        }
535
536        function processClassString( classes, checkOption ) {
537            var current, i;
538            for ( i = 0; i < classes.length; i++ ) {
539                current = that.classesElementLookup[ classes[ i ] ] || $();
540                if ( options.add ) {
541                    bindRemoveEvent();
542                    current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
543                } else {
544                    current = $( current.not( options.element ).get() );
545                }
546                that.classesElementLookup[ classes[ i ] ] = current;
547                full.push( classes[ i ] );
548                if ( checkOption && options.classes[ classes[ i ] ] ) {
549                    full.push( options.classes[ classes[ i ] ] );
550                }
551            }
552        }
553
554        if ( options.keys ) {
555            processClassString( options.keys.match( /\S+/g ) || [], true );
556        }
557        if ( options.extra ) {
558            processClassString( options.extra.match( /\S+/g ) || [] );
559        }
560
561        return full.join( " " );
562    },
563
564    _untrackClassesElement: function( event ) {
565        var that = this;
566        $.each( that.classesElementLookup, function( key, value ) {
567            if ( $.inArray( event.target, value ) !== -1 ) {
568                that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
569            }
570        } );
571
572        this._off( $( event.target ) );
573    },
574
575    _removeClass: function( element, keys, extra ) {
576        return this._toggleClass( element, keys, extra, false );
577    },
578
579    _addClass: function( element, keys, extra ) {
580        return this._toggleClass( element, keys, extra, true );
581    },
582
583    _toggleClass: function( element, keys, extra, add ) {
584        add = ( typeof add === "boolean" ) ? add : extra;
585        var shift = ( typeof element === "string" || element === null ),
586            options = {
587                extra: shift ? keys : extra,
588                keys: shift ? element : keys,
589                element: shift ? this.element : element,
590                add: add
591            };
592        options.element.toggleClass( this._classes( options ), add );
593        return this;
594    },
595
596    _on: function( suppressDisabledCheck, element, handlers ) {
597        var delegateElement;
598        var instance = this;
599
600        // No suppressDisabledCheck flag, shuffle arguments
601        if ( typeof suppressDisabledCheck !== "boolean" ) {
602            handlers = element;
603            element = suppressDisabledCheck;
604            suppressDisabledCheck = false;
605        }
606
607        // No element argument, shuffle and use this.element
608        if ( !handlers ) {
609            handlers = element;
610            element = this.element;
611            delegateElement = this.widget();
612        } else {
613            element = delegateElement = $( element );
614            this.bindings = this.bindings.add( element );
615        }
616
617        $.each( handlers, function( event, handler ) {
618            function handlerProxy() {
619
620                // Allow widgets to customize the disabled handling
621                // - disabled as an array instead of boolean
622                // - disabled class as method for disabling individual parts
623                if ( !suppressDisabledCheck &&
624                        ( instance.options.disabled === true ||
625                        $( this ).hasClass( "ui-state-disabled" ) ) ) {
626                    return;
627                }
628                return ( typeof handler === "string" ? instance[ handler ] : handler )
629                    .apply( instance, arguments );
630            }
631
632            // Copy the guid so direct unbinding works
633            if ( typeof handler !== "string" ) {
634                handlerProxy.guid = handler.guid =
635                    handler.guid || handlerProxy.guid || $.guid++;
636            }
637
638            var match = event.match( /^([\w:-]*)\s*(.*)$/ );
639            var eventName = match[ 1 ] + instance.eventNamespace;
640            var selector = match[ 2 ];
641
642            if ( selector ) {
643                delegateElement.on( eventName, selector, handlerProxy );
644            } else {
645                element.on( eventName, handlerProxy );
646            }
647        } );
648    },
649
650    _off: function( element, eventName ) {
651        eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
652            this.eventNamespace;
653        element.off( eventName );
654
655        // Clear the stack to avoid memory leaks (#10056)
656        this.bindings = $( this.bindings.not( element ).get() );
657        this.focusable = $( this.focusable.not( element ).get() );
658        this.hoverable = $( this.hoverable.not( element ).get() );
659    },
660
661    _delay: function( handler, delay ) {
662        function handlerProxy() {
663            return ( typeof handler === "string" ? instance[ handler ] : handler )
664                .apply( instance, arguments );
665        }
666        var instance = this;
667        return setTimeout( handlerProxy, delay || 0 );
668    },
669
670    _hoverable: function( element ) {
671        this.hoverable = this.hoverable.add( element );
672        this._on( element, {
673            mouseenter: function( event ) {
674                this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
675            },
676            mouseleave: function( event ) {
677                this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
678            }
679        } );
680    },
681
682    _focusable: function( element ) {
683        this.focusable = this.focusable.add( element );
684        this._on( element, {
685            focusin: function( event ) {
686                this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
687            },
688            focusout: function( event ) {
689                this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
690            }
691        } );
692    },
693
694    _trigger: function( type, event, data ) {
695        var prop, orig;
696        var callback = this.options[ type ];
697
698        data = data || {};
699        event = $.Event( event );
700        event.type = ( type === this.widgetEventPrefix ?
701            type :
702            this.widgetEventPrefix + type ).toLowerCase();
703
704        // The original event may come from any element
705        // so we need to reset the target on the new event
706        event.target = this.element[ 0 ];
707
708        // Copy original event properties over to the new event
709        orig = event.originalEvent;
710        if ( orig ) {
711            for ( prop in orig ) {
712                if ( !( prop in event ) ) {
713                    event[ prop ] = orig[ prop ];
714                }
715            }
716        }
717
718        this.element.trigger( event, data );
719        return !( typeof callback === "function" &&
720            callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
721            event.isDefaultPrevented() );
722    }
723};
724
725$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
726    $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
727        if ( typeof options === "string" ) {
728            options = { effect: options };
729        }
730
731        var hasOptions;
732        var effectName = !options ?
733            method :
734            options === true || typeof options === "number" ?
735                defaultEffect :
736                options.effect || defaultEffect;
737
738        options = options || {};
739        if ( typeof options === "number" ) {
740            options = { duration: options };
741        } else if ( options === true ) {
742            options = {};
743        }
744
745        hasOptions = !$.isEmptyObject( options );
746        options.complete = callback;
747
748        if ( options.delay ) {
749            element.delay( options.delay );
750        }
751
752        if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
753            element[ method ]( options );
754        } else if ( effectName !== method && element[ effectName ] ) {
755            element[ effectName ]( options.duration, options.easing, callback );
756        } else {
757            element.queue( function( next ) {
758                $( this )[ method ]();
759                if ( callback ) {
760                    callback.call( element[ 0 ] );
761                }
762                next();
763            } );
764        }
765    };
766} );
767
768var widget = $.widget;
769
770
771/*!
772 * jQuery UI Position 1.14.1
773 * https://jqueryui.com
774 *
775 * Copyright OpenJS Foundation and other contributors
776 * Released under the MIT license.
777 * https://jquery.org/license
778 *
779 * https://api.jqueryui.com/position/
780 */
781
782//>>label: Position
783//>>group: Core
784//>>description: Positions elements relative to other elements.
785//>>docs: https://api.jqueryui.com/position/
786//>>demos: https://jqueryui.com/position/
787
788
789( function() {
790var cachedScrollbarWidth,
791    max = Math.max,
792    abs = Math.abs,
793    rhorizontal = /left|center|right/,
794    rvertical = /top|center|bottom/,
795    roffset = /[\+\-]\d+(\.[\d]+)?%?/,
796    rposition = /^\w+/,
797    rpercent = /%$/,
798    _position = $.fn.position;
799
800function getOffsets( offsets, width, height ) {
801    return [
802        parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
803        parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
804    ];
805}
806
807function parseCss( element, property ) {
808    return parseInt( $.css( element, property ), 10 ) || 0;
809}
810
811function isWindow( obj ) {
812    return obj != null && obj === obj.window;
813}
814
815function getDimensions( elem ) {
816    var raw = elem[ 0 ];
817    if ( raw.nodeType === 9 ) {
818        return {
819            width: elem.width(),
820            height: elem.height(),
821            offset: { top: 0, left: 0 }
822        };
823    }
824    if ( isWindow( raw ) ) {
825        return {
826            width: elem.width(),
827            height: elem.height(),
828            offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
829        };
830    }
831    if ( raw.preventDefault ) {
832        return {
833            width: 0,
834            height: 0,
835            offset: { top: raw.pageY, left: raw.pageX }
836        };
837    }
838    return {
839        width: elem.outerWidth(),
840        height: elem.outerHeight(),
841        offset: elem.offset()
842    };
843}
844
845$.position = {
846    scrollbarWidth: function() {
847        if ( cachedScrollbarWidth !== undefined ) {
848            return cachedScrollbarWidth;
849        }
850        var w1, w2,
851            div = $( "<div style=" +
852                "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
853                "<div style='height:300px;width:auto;'></div></div>" ),
854            innerDiv = div.children()[ 0 ];
855
856        $( "body" ).append( div );
857        w1 = innerDiv.offsetWidth;
858        div.css( "overflow", "scroll" );
859
860        w2 = innerDiv.offsetWidth;
861
862        if ( w1 === w2 ) {
863            w2 = div[ 0 ].clientWidth;
864        }
865
866        div.remove();
867
868        return ( cachedScrollbarWidth = w1 - w2 );
869    },
870    getScrollInfo: function( within ) {
871        var overflowX = within.isWindow || within.isDocument ? "" :
872                within.element.css( "overflow-x" ),
873            overflowY = within.isWindow || within.isDocument ? "" :
874                within.element.css( "overflow-y" ),
875            hasOverflowX = overflowX === "scroll" ||
876                ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
877            hasOverflowY = overflowY === "scroll" ||
878                ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
879        return {
880            width: hasOverflowY ? $.position.scrollbarWidth() : 0,
881            height: hasOverflowX ? $.position.scrollbarWidth() : 0
882        };
883    },
884    getWithinInfo: function( element ) {
885        var withinElement = $( element || window ),
886            isElemWindow = isWindow( withinElement[ 0 ] ),
887            isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
888            hasOffset = !isElemWindow && !isDocument;
889        return {
890            element: withinElement,
891            isWindow: isElemWindow,
892            isDocument: isDocument,
893            offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
894            scrollLeft: withinElement.scrollLeft(),
895            scrollTop: withinElement.scrollTop(),
896            width: withinElement.outerWidth(),
897            height: withinElement.outerHeight()
898        };
899    }
900};
901
902$.fn.position = function( options ) {
903    if ( !options || !options.of ) {
904        return _position.apply( this, arguments );
905    }
906
907    // Make a copy, we don't want to modify arguments
908    options = $.extend( {}, options );
909
910    var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
911
912        // Make sure string options are treated as CSS selectors
913        target = typeof options.of === "string" ?
914            $( document ).find( options.of ) :
915            $( options.of ),
916
917        within = $.position.getWithinInfo( options.within ),
918        scrollInfo = $.position.getScrollInfo( within ),
919        collision = ( options.collision || "flip" ).split( " " ),
920        offsets = {};
921
922    dimensions = getDimensions( target );
923    if ( target[ 0 ].preventDefault ) {
924
925        // Force left top to allow flipping
926        options.at = "left top";
927    }
928    targetWidth = dimensions.width;
929    targetHeight = dimensions.height;
930    targetOffset = dimensions.offset;
931
932    // Clone to reuse original targetOffset later
933    basePosition = $.extend( {}, targetOffset );
934
935    // Force my and at to have valid horizontal and vertical positions
936    // if a value is missing or invalid, it will be converted to center
937    $.each( [ "my", "at" ], function() {
938        var pos = ( options[ this ] || "" ).split( " " ),
939            horizontalOffset,
940            verticalOffset;
941
942        if ( pos.length === 1 ) {
943            pos = rhorizontal.test( pos[ 0 ] ) ?
944                pos.concat( [ "center" ] ) :
945                rvertical.test( pos[ 0 ] ) ?
946                    [ "center" ].concat( pos ) :
947                    [ "center", "center" ];
948        }
949        pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
950        pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
951
952        // Calculate offsets
953        horizontalOffset = roffset.exec( pos[ 0 ] );
954        verticalOffset = roffset.exec( pos[ 1 ] );
955        offsets[ this ] = [
956            horizontalOffset ? horizontalOffset[ 0 ] : 0,
957            verticalOffset ? verticalOffset[ 0 ] : 0
958        ];
959
960        // Reduce to just the positions without the offsets
961        options[ this ] = [
962            rposition.exec( pos[ 0 ] )[ 0 ],
963            rposition.exec( pos[ 1 ] )[ 0 ]
964        ];
965    } );
966
967    // Normalize collision option
968    if ( collision.length === 1 ) {
969        collision[ 1 ] = collision[ 0 ];
970    }
971
972    if ( options.at[ 0 ] === "right" ) {
973        basePosition.left += targetWidth;
974    } else if ( options.at[ 0 ] === "center" ) {
975        basePosition.left += targetWidth / 2;
976    }
977
978    if ( options.at[ 1 ] === "bottom" ) {
979        basePosition.top += targetHeight;
980    } else if ( options.at[ 1 ] === "center" ) {
981        basePosition.top += targetHeight / 2;
982    }
983
984    atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
985    basePosition.left += atOffset[ 0 ];
986    basePosition.top += atOffset[ 1 ];
987
988    return this.each( function() {
989        var collisionPosition, using,
990            elem = $( this ),
991            elemWidth = elem.outerWidth(),
992            elemHeight = elem.outerHeight(),
993            marginLeft = parseCss( this, "marginLeft" ),
994            marginTop = parseCss( this, "marginTop" ),
995            collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
996                scrollInfo.width,
997            collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
998                scrollInfo.height,
999            position = $.extend( {}, basePosition ),
1000            myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1001
1002        if ( options.my[ 0 ] === "right" ) {
1003            position.left -= elemWidth;
1004        } else if ( options.my[ 0 ] === "center" ) {
1005            position.left -= elemWidth / 2;
1006        }
1007
1008        if ( options.my[ 1 ] === "bottom" ) {
1009            position.top -= elemHeight;
1010        } else if ( options.my[ 1 ] === "center" ) {
1011            position.top -= elemHeight / 2;
1012        }
1013
1014        position.left += myOffset[ 0 ];
1015        position.top += myOffset[ 1 ];
1016
1017        collisionPosition = {
1018            marginLeft: marginLeft,
1019            marginTop: marginTop
1020        };
1021
1022        $.each( [ "left", "top" ], function( i, dir ) {
1023            if ( $.ui.position[ collision[ i ] ] ) {
1024                $.ui.position[ collision[ i ] ][ dir ]( position, {
1025                    targetWidth: targetWidth,
1026                    targetHeight: targetHeight,
1027                    elemWidth: elemWidth,
1028                    elemHeight: elemHeight,
1029                    collisionPosition: collisionPosition,
1030                    collisionWidth: collisionWidth,
1031                    collisionHeight: collisionHeight,
1032                    offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1033                    my: options.my,
1034                    at: options.at,
1035                    within: within,
1036                    elem: elem
1037                } );
1038            }
1039        } );
1040
1041        if ( options.using ) {
1042
1043            // Adds feedback as second argument to using callback, if present
1044            using = function( props ) {
1045                var left = targetOffset.left - position.left,
1046                    right = left + targetWidth - elemWidth,
1047                    top = targetOffset.top - position.top,
1048                    bottom = top + targetHeight - elemHeight,
1049                    feedback = {
1050                        target: {
1051                            element: target,
1052                            left: targetOffset.left,
1053                            top: targetOffset.top,
1054                            width: targetWidth,
1055                            height: targetHeight
1056                        },
1057                        element: {
1058                            element: elem,
1059                            left: position.left,
1060                            top: position.top,
1061                            width: elemWidth,
1062                            height: elemHeight
1063                        },
1064                        horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1065                        vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1066                    };
1067                if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1068                    feedback.horizontal = "center";
1069                }
1070                if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1071                    feedback.vertical = "middle";
1072                }
1073                if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1074                    feedback.important = "horizontal";
1075                } else {
1076                    feedback.important = "vertical";
1077                }
1078                options.using.call( this, props, feedback );
1079            };
1080        }
1081
1082        elem.offset( $.extend( position, { using: using } ) );
1083    } );
1084};
1085
1086$.ui.position = {
1087    fit: {
1088        left: function( position, data ) {
1089            var within = data.within,
1090                withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1091                outerWidth = within.width,
1092                collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1093                overLeft = withinOffset - collisionPosLeft,
1094                overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1095                newOverRight;
1096
1097            // Element is wider than within
1098            if ( data.collisionWidth > outerWidth ) {
1099
1100                // Element is initially over the left side of within
1101                if ( overLeft > 0 && overRight <= 0 ) {
1102                    newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1103                        withinOffset;
1104                    position.left += overLeft - newOverRight;
1105
1106                // Element is initially over right side of within
1107                } else if ( overRight > 0 && overLeft <= 0 ) {
1108                    position.left = withinOffset;
1109
1110                // Element is initially over both left and right sides of within
1111                } else {
1112                    if ( overLeft > overRight ) {
1113                        position.left = withinOffset + outerWidth - data.collisionWidth;
1114                    } else {
1115                        position.left = withinOffset;
1116                    }
1117                }
1118
1119            // Too far left -> align with left edge
1120            } else if ( overLeft > 0 ) {
1121                position.left += overLeft;
1122
1123            // Too far right -> align with right edge
1124            } else if ( overRight > 0 ) {
1125                position.left -= overRight;
1126
1127            // Adjust based on position and margin
1128            } else {
1129                position.left = max( position.left - collisionPosLeft, position.left );
1130            }
1131        },
1132        top: function( position, data ) {
1133            var within = data.within,
1134                withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1135                outerHeight = data.within.height,
1136                collisionPosTop = position.top - data.collisionPosition.marginTop,
1137                overTop = withinOffset - collisionPosTop,
1138                overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1139                newOverBottom;
1140
1141            // Element is taller than within
1142            if ( data.collisionHeight > outerHeight ) {
1143
1144                // Element is initially over the top of within
1145                if ( overTop > 0 && overBottom <= 0 ) {
1146                    newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1147                        withinOffset;
1148                    position.top += overTop - newOverBottom;
1149
1150                // Element is initially over bottom of within
1151                } else if ( overBottom > 0 && overTop <= 0 ) {
1152                    position.top = withinOffset;
1153
1154                // Element is initially over both top and bottom of within
1155                } else {
1156                    if ( overTop > overBottom ) {
1157                        position.top = withinOffset + outerHeight - data.collisionHeight;
1158                    } else {
1159                        position.top = withinOffset;
1160                    }
1161                }
1162
1163            // Too far up -> align with top
1164            } else if ( overTop > 0 ) {
1165                position.top += overTop;
1166
1167            // Too far down -> align with bottom edge
1168            } else if ( overBottom > 0 ) {
1169                position.top -= overBottom;
1170
1171            // Adjust based on position and margin
1172            } else {
1173                position.top = max( position.top - collisionPosTop, position.top );
1174            }
1175        }
1176    },
1177    flip: {
1178        left: function( position, data ) {
1179            var within = data.within,
1180                withinOffset = within.offset.left + within.scrollLeft,
1181                outerWidth = within.width,
1182                offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1183                collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1184                overLeft = collisionPosLeft - offsetLeft,
1185                overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1186                myOffset = data.my[ 0 ] === "left" ?
1187                    -data.elemWidth :
1188                    data.my[ 0 ] === "right" ?
1189                        data.elemWidth :
1190                        0,
1191                atOffset = data.at[ 0 ] === "left" ?
1192                    data.targetWidth :
1193                    data.at[ 0 ] === "right" ?
1194                        -data.targetWidth :
1195                        0,
1196                offset = -2 * data.offset[ 0 ],
1197                newOverRight,
1198                newOverLeft;
1199
1200            if ( overLeft < 0 ) {
1201                newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1202                    outerWidth - withinOffset;
1203                if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1204                    position.left += myOffset + atOffset + offset;
1205                }
1206            } else if ( overRight > 0 ) {
1207                newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1208                    atOffset + offset - offsetLeft;
1209                if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1210                    position.left += myOffset + atOffset + offset;
1211                }
1212            }
1213        },
1214        top: function( position, data ) {
1215            var within = data.within,
1216                withinOffset = within.offset.top + within.scrollTop,
1217                outerHeight = within.height,
1218                offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1219                collisionPosTop = position.top - data.collisionPosition.marginTop,
1220                overTop = collisionPosTop - offsetTop,
1221                overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1222                top = data.my[ 1 ] === "top",
1223                myOffset = top ?
1224                    -data.elemHeight :
1225                    data.my[ 1 ] === "bottom" ?
1226                        data.elemHeight :
1227                        0,
1228                atOffset = data.at[ 1 ] === "top" ?
1229                    data.targetHeight :
1230                    data.at[ 1 ] === "bottom" ?
1231                        -data.targetHeight :
1232                        0,
1233                offset = -2 * data.offset[ 1 ],
1234                newOverTop,
1235                newOverBottom;
1236            if ( overTop < 0 ) {
1237                newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1238                    outerHeight - withinOffset;
1239                if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1240                    position.top += myOffset + atOffset + offset;
1241                }
1242            } else if ( overBottom > 0 ) {
1243                newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1244                    offset - offsetTop;
1245                if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1246                    position.top += myOffset + atOffset + offset;
1247                }
1248            }
1249        }
1250    },
1251    flipfit: {
1252        left: function() {
1253            $.ui.position.flip.left.apply( this, arguments );
1254            $.ui.position.fit.left.apply( this, arguments );
1255        },
1256        top: function() {
1257            $.ui.position.flip.top.apply( this, arguments );
1258            $.ui.position.fit.top.apply( this, arguments );
1259        }
1260    }
1261};
1262
1263} )();
1264
1265var position = $.ui.position;
1266
1267
1268/*!
1269 * jQuery UI :data 1.14.1
1270 * https://jqueryui.com
1271 *
1272 * Copyright OpenJS Foundation and other contributors
1273 * Released under the MIT license.
1274 * https://jquery.org/license
1275 */
1276
1277//>>label: :data Selector
1278//>>group: Core
1279//>>description: Selects elements which have data stored under the specified key.
1280//>>docs: https://api.jqueryui.com/data-selector/
1281
1282
1283var data = $.extend( $.expr.pseudos, {
1284    data: $.expr.createPseudo( function( dataName ) {
1285        return function( elem ) {
1286            return !!$.data( elem, dataName );
1287        };
1288    } )
1289} );
1290
1291/*!
1292 * jQuery UI Disable Selection 1.14.1
1293 * https://jqueryui.com
1294 *
1295 * Copyright OpenJS Foundation and other contributors
1296 * Released under the MIT license.
1297 * https://jquery.org/license
1298 */
1299
1300//>>label: disableSelection
1301//>>group: Core
1302//>>description: Disable selection of text content within the set of matched elements.
1303//>>docs: https://api.jqueryui.com/disableSelection/
1304
1305// This file is deprecated
1306
1307var disableSelection = $.fn.extend( {
1308    disableSelection: ( function() {
1309        var eventType = "onselectstart" in document.createElement( "div" ) ?
1310            "selectstart" :
1311            "mousedown";
1312
1313        return function() {
1314            return this.on( eventType + ".ui-disableSelection", function( event ) {
1315                event.preventDefault();
1316            } );
1317        };
1318    } )(),
1319
1320    enableSelection: function() {
1321        return this.off( ".ui-disableSelection" );
1322    }
1323} );
1324
1325
1326
1327// Create a local jQuery because jQuery Color relies on it and the
1328// global may not exist with AMD and a custom build (#10199).
1329// This module is a noop if used as a regular AMD module.
1330// eslint-disable-next-line no-unused-vars
1331var jQuery = $;
1332
1333
1334/*!
1335 * jQuery Color Animations v3.0.0
1336 * https://github.com/jquery/jquery-color
1337 *
1338 * Copyright OpenJS Foundation and other contributors
1339 * Released under the MIT license.
1340 * https://jquery.org/license
1341 *
1342 * Date: Wed May 15 16:49:44 2024 +0200
1343 */
1344
1345
1346    var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
1347        "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
1348
1349    class2type = {},
1350    toString = class2type.toString,
1351
1352    // plusequals test for += 100 -= 100
1353    rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
1354
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        }, {
1377
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        }, {
1391
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        } ],
1417
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        },
1439
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
1471    // colors = jQuery.Color.names
1472    colors,
1473
1474    // local aliases of functions called often
1475    each = jQuery.each;
1476
1477// define cache name and alpha properties
1478// for rgba and hsla spaces
1479each( spaces, function( spaceName, space ) {
1480    space.cache = "_" + spaceName;
1481    space.props.alpha = {
1482        idx: 3,
1483        type: "percent",
1484        def: 1
1485    };
1486} );
1487
1488// Populate the class2type map
1489jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
1490    function( _i, name ) {
1491        class2type[ "[object " + name + "]" ] = name.toLowerCase();
1492    } );
1493
1494function getType( obj ) {
1495    if ( obj == null ) {
1496        return obj + "";
1497    }
1498
1499    return typeof obj === "object" ?
1500        class2type[ toString.call( obj ) ] || "object" :
1501        typeof obj;
1502}
1503
1504function clamp( value, prop, allowEmpty ) {
1505    var type = propTypes[ prop.type ] || {};
1506
1507    if ( value == null ) {
1508        return ( allowEmpty || !prop.def ) ? null : prop.def;
1509    }
1510
1511    // ~~ is an short way of doing floor for positive numbers
1512    value = type.floor ? ~~value : parseFloat( value );
1513
1514    if ( type.mod ) {
1515
1516        // we add mod before modding to make sure that negatives values
1517        // get converted properly: -10 -> 350
1518        return ( value + type.mod ) % type.mod;
1519    }
1520
1521    // for now all property types without mod have min and max
1522    return Math.min( type.max, Math.max( 0, value ) );
1523}
1524
1525function stringParse( string ) {
1526    var inst = color(),
1527        rgba = inst._rgba = [];
1528
1529    string = string.toLowerCase();
1530
1531    each( stringParsers, function( _i, parser ) {
1532        var parsed,
1533            match = parser.re.exec( string ),
1534            values = match && parser.parse( match ),
1535            spaceName = parser.space || "rgba";
1536
1537        if ( values ) {
1538            parsed = inst[ spaceName ]( values );
1539
1540            // if this was an rgba parse the assignment might happen twice
1541            // oh well....
1542            inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
1543            rgba = inst._rgba = parsed._rgba;
1544
1545            // exit each( stringParsers ) here because we matched
1546            return false;
1547        }
1548    } );
1549
1550    // Found a stringParser that handled it
1551    if ( rgba.length ) {
1552
1553        // if this came from a parsed string, force "transparent" when alpha is 0
1554        // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
1555        if ( rgba.join() === "0,0,0,0" ) {
1556            jQuery.extend( rgba, colors.transparent );
1557        }
1558        return inst;
1559    }
1560
1561    // named colors
1562    return colors[ string ];
1563}
1564
1565color.fn = jQuery.extend( color.prototype, {
1566    parse: function( red, green, blue, alpha ) {
1567        if ( red === undefined ) {
1568            this._rgba = [ null, null, null, null ];
1569            return this;
1570        }
1571        if ( red.jquery || red.nodeType ) {
1572            red = jQuery( red ).css( green );
1573            green = undefined;
1574        }
1575
1576        var inst = this,
1577            type = getType( red ),
1578            rgba = this._rgba = [];
1579
1580        // more than 1 argument specified - assume ( red, green, blue, alpha )
1581        if ( green !== undefined ) {
1582            red = [ red, green, blue, alpha ];
1583            type = "array";
1584        }
1585
1586        if ( type === "string" ) {
1587            return this.parse( stringParse( red ) || colors._default );
1588        }
1589
1590        if ( type === "array" ) {
1591            each( spaces.rgba.props, function( _key, prop ) {
1592                rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
1593            } );
1594            return this;
1595        }
1596
1597        if ( type === "object" ) {
1598            if ( red instanceof color ) {
1599                each( spaces, function( _spaceName, space ) {
1600                    if ( red[ space.cache ] ) {
1601                        inst[ space.cache ] = red[ space.cache ].slice();
1602                    }
1603                } );
1604            } else {
1605                each( spaces, function( _spaceName, space ) {
1606                    var cache = space.cache;
1607                    each( space.props, function( key, prop ) {
1608
1609                        // if the cache doesn't exist, and we know how to convert
1610                        if ( !inst[ cache ] && space.to ) {
1611
1612                            // if the value was null, we don't need to copy it
1613                            // if the key was alpha, we don't need to copy it either
1614                            if ( key === "alpha" || red[ key ] == null ) {
1615                                return;
1616                            }
1617                            inst[ cache ] = space.to( inst._rgba );
1618                        }
1619
1620                        // this is the only case where we allow nulls for ALL properties.
1621                        // call clamp with alwaysAllowEmpty
1622                        inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
1623                    } );
1624
1625                    // everything defined but alpha?
1626                    if ( inst[ cache ] && jQuery.inArray(
1627                        null,
1628                        inst[ cache ].slice( 0, 3 )
1629                    ) < 0 ) {
1630
1631                        // use the default of 1
1632                        if ( inst[ cache ][ 3 ] == null ) {
1633                            inst[ cache ][ 3 ] = 1;
1634                        }
1635
1636                        if ( space.from ) {
1637                            inst._rgba = space.from( inst[ cache ] );
1638                        }
1639                    }
1640                } );
1641            }
1642            return this;
1643        }
1644    },
1645    is: function( compare ) {
1646        var is = color( compare ),
1647            same = true,
1648            inst = this;
1649
1650        each( spaces, function( _, space ) {
1651            var localCache,
1652                isCache = is[ space.cache ];
1653            if ( isCache ) {
1654                localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
1655                each( space.props, function( _, prop ) {
1656                    if ( isCache[ prop.idx ] != null ) {
1657                        same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
1658                        return same;
1659                    }
1660                } );
1661            }
1662            return same;
1663        } );
1664        return same;
1665    },
1666    _space: function() {
1667        var used = [],
1668            inst = this;
1669        each( spaces, function( spaceName, space ) {
1670            if ( inst[ space.cache ] ) {
1671                used.push( spaceName );
1672            }
1673        } );
1674        return used.pop();
1675    },
1676    transition: function( other, distance ) {
1677        var end = color( other ),
1678            spaceName = end._space(),
1679            space = spaces[ spaceName ],
1680            startColor = this.alpha() === 0 ? color( "transparent" ) : this,
1681            start = startColor[ space.cache ] || space.to( startColor._rgba ),
1682            result = start.slice();
1683
1684        end = end[ space.cache ];
1685        each( space.props, function( _key, prop ) {
1686            var index = prop.idx,
1687                startValue = start[ index ],
1688                endValue = end[ index ],
1689                type = propTypes[ prop.type ] || {};
1690
1691            // if null, don't override start value
1692            if ( endValue === null ) {
1693                return;
1694            }
1695
1696            // if null - use end
1697            if ( startValue === null ) {
1698                result[ index ] = endValue;
1699            } else {
1700                if ( type.mod ) {
1701                    if ( endValue - startValue > type.mod / 2 ) {
1702                        startValue += type.mod;
1703                    } else if ( startValue - endValue > type.mod / 2 ) {
1704                        startValue -= type.mod;
1705                    }
1706                }
1707                result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
1708            }
1709        } );
1710        return this[ spaceName ]( result );
1711    },
1712    blend: function( opaque ) {
1713
1714        // if we are already opaque - return ourself
1715        if ( this._rgba[ 3 ] === 1 ) {
1716            return this;
1717        }
1718
1719        var rgb = this._rgba.slice(),
1720            a = rgb.pop(),
1721            blend = color( opaque )._rgba;
1722
1723        return color( jQuery.map( rgb, function( v, i ) {
1724            return ( 1 - a ) * blend[ i ] + a * v;
1725        } ) );
1726    },
1727    toRgbaString: function() {
1728        var prefix = "rgba(",
1729            rgba = jQuery.map( this._rgba, function( v, i ) {
1730                if ( v != null ) {
1731                    return v;
1732                }
1733                return i > 2 ? 1 : 0;
1734            } );
1735
1736        if ( rgba[ 3 ] === 1 ) {
1737            rgba.pop();
1738            prefix = "rgb(";
1739        }
1740
1741        return prefix + rgba.join( ", " ) + ")";
1742    },
1743    toHslaString: function() {
1744        var prefix = "hsla(",
1745            hsla = jQuery.map( this.hsla(), function( v, i ) {
1746                if ( v == null ) {
1747                    v = i > 2 ? 1 : 0;
1748                }
1749
1750                // catch 1 and 2
1751                if ( i && i < 3 ) {
1752                    v = Math.round( v * 100 ) + "%";
1753                }
1754                return v;
1755            } );
1756
1757        if ( hsla[ 3 ] === 1 ) {
1758            hsla.pop();
1759            prefix = "hsl(";
1760        }
1761        return prefix + hsla.join( ", " ) + ")";
1762    },
1763    toHexString: function( includeAlpha ) {
1764        var rgba = this._rgba.slice(),
1765            alpha = rgba.pop();
1766
1767        if ( includeAlpha ) {
1768            rgba.push( ~~( alpha * 255 ) );
1769        }
1770
1771        return "#" + jQuery.map( rgba, function( v ) {
1772
1773            // default to 0 when nulls exist
1774            return ( "0" + ( v || 0 ).toString( 16 ) ).substr( -2 );
1775        } ).join( "" );
1776    },
1777    toString: function() {
1778        return this.toRgbaString();
1779    }
1780} );
1781color.fn.parse.prototype = color.fn;
1782
1783// hsla conversions adapted from:
1784// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
1785
1786function hue2rgb( p, q, h ) {
1787    h = ( h + 1 ) % 1;
1788    if ( h * 6 < 1 ) {
1789        return p + ( q - p ) * h * 6;
1790    }
1791    if ( h * 2 < 1 ) {
1792        return q;
1793    }
1794    if ( h * 3 < 2 ) {
1795        return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
1796    }
1797    return p;
1798}
1799
1800spaces.hsla.to = function( rgba ) {
1801    if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
1802        return [ null, null, null, rgba[ 3 ] ];
1803    }
1804    var r = rgba[ 0 ] / 255,
1805        g = rgba[ 1 ] / 255,
1806        b = rgba[ 2 ] / 255,
1807        a = rgba[ 3 ],
1808        max = Math.max( r, g, b ),
1809        min = Math.min( r, g, b ),
1810        diff = max - min,
1811        add = max + min,
1812        l = add * 0.5,
1813        h, s;
1814
1815    if ( min === max ) {
1816        h = 0;
1817    } else if ( r === max ) {
1818        h = ( 60 * ( g - b ) / diff ) + 360;
1819    } else if ( g === max ) {
1820        h = ( 60 * ( b - r ) / diff ) + 120;
1821    } else {
1822        h = ( 60 * ( r - g ) / diff ) + 240;
1823    }
1824
1825    // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
1826    // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
1827    if ( diff === 0 ) {
1828        s = 0;
1829    } else if ( l <= 0.5 ) {
1830        s = diff / add;
1831    } else {
1832        s = diff / ( 2 - add );
1833    }
1834    return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
1835};
1836
1837spaces.hsla.from = function( hsla ) {
1838    if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
1839        return [ null, null, null, hsla[ 3 ] ];
1840    }
1841    var h = hsla[ 0 ] / 360,
1842        s = hsla[ 1 ],
1843        l = hsla[ 2 ],
1844        a = hsla[ 3 ],
1845        q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
1846        p = 2 * l - q;
1847
1848    return [
1849        Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
1850        Math.round( hue2rgb( p, q, h ) * 255 ),
1851        Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
1852        a
1853    ];
1854};
1855
1856
1857each( spaces, function( spaceName, space ) {
1858    var props = space.props,
1859        cache = space.cache,
1860        to = space.to,
1861        from = space.from;
1862
1863    // makes rgba() and hsla()
1864    color.fn[ spaceName ] = function( value ) {
1865
1866        // generate a cache for this space if it doesn't exist
1867        if ( to && !this[ cache ] ) {
1868            this[ cache ] = to( this._rgba );
1869        }
1870        if ( value === undefined ) {
1871            return this[ cache ].slice();
1872        }
1873
1874        var ret,
1875            type = getType( value ),
1876            arr = ( type === "array" || type === "object" ) ? value : arguments,
1877            local = this[ cache ].slice();
1878
1879        each( props, function( key, prop ) {
1880            var val = arr[ type === "object" ? key : prop.idx ];
1881            if ( val == null ) {
1882                val = local[ prop.idx ];
1883            }
1884            local[ prop.idx ] = clamp( val, prop );
1885        } );
1886
1887        if ( from ) {
1888            ret = color( from( local ) );
1889            ret[ cache ] = local;
1890            return ret;
1891        } else {
1892            return color( local );
1893        }
1894    };
1895
1896    // makes red() green() blue() alpha() hue() saturation() lightness()
1897    each( props, function( key, prop ) {
1898
1899        // alpha is included in more than one space
1900        if ( color.fn[ key ] ) {
1901            return;
1902        }
1903        color.fn[ key ] = function( value ) {
1904            var local, cur, match, fn,
1905                vtype = getType( value );
1906
1907            if ( key === "alpha" ) {
1908                fn = this._hsla ? "hsla" : "rgba";
1909            } else {
1910                fn = spaceName;
1911            }
1912            local = this[ fn ]();
1913            cur = local[ prop.idx ];
1914
1915            if ( vtype === "undefined" ) {
1916                return cur;
1917            }
1918
1919            if ( vtype === "function" ) {
1920                value = value.call( this, cur );
1921                vtype = getType( value );
1922            }
1923            if ( value == null && prop.empty ) {
1924                return this;
1925            }
1926            if ( vtype === "string" ) {
1927                match = rplusequals.exec( value );
1928                if ( match ) {
1929                    value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
1930                }
1931            }
1932            local[ prop.idx ] = value;
1933            return this[ fn ]( local );
1934        };
1935    } );
1936} );
1937
1938// add cssHook and .fx.step function for each named hook.
1939// accept a space separated string of properties
1940color.hook = function( hook ) {
1941    var hooks = hook.split( " " );
1942    each( hooks, function( _i, hook ) {
1943        jQuery.cssHooks[ hook ] = {
1944            set: function( elem, value ) {
1945                var parsed;
1946
1947                if ( value !== "transparent" &&
1948                    ( getType( value ) !== "string" ||
1949                        ( parsed = stringParse( value ) ) ) ) {
1950                    value = color( parsed || value );
1951                    value = value.toRgbaString();
1952                }
1953                elem.style[ hook ] = value;
1954            }
1955        };
1956        jQuery.fx.step[ hook ] = function( fx ) {
1957            if ( !fx.colorInit ) {
1958                fx.start = color( fx.elem, hook );
1959                fx.end = color( fx.end );
1960                fx.colorInit = true;
1961            }
1962            jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
1963        };
1964    } );
1965
1966};
1967
1968color.hook( stepHooks );
1969
1970jQuery.cssHooks.borderColor = {
1971    expand: function( value ) {
1972        var expanded = {};
1973
1974        each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) {
1975            expanded[ "border" + part + "Color" ] = value;
1976        } );
1977        return expanded;
1978    }
1979};
1980
1981// Basic color names only.
1982// Usage of any of the other color names requires adding yourself or including
1983// jquery.color.svg-names.js.
1984colors = jQuery.Color.names = {
1985
1986    // 4.1. Basic color keywords
1987    aqua: "#00ffff",
1988    black: "#000000",
1989    blue: "#0000ff",
1990    fuchsia: "#ff00ff",
1991    gray: "#808080",
1992    green: "#008000",
1993    lime: "#00ff00",
1994    maroon: "#800000",
1995    navy: "#000080",
1996    olive: "#808000",
1997    purple: "#800080",
1998    red: "#ff0000",
1999    silver: "#c0c0c0",
2000    teal: "#008080",
2001    white: "#ffffff",
2002    yellow: "#ffff00",
2003
2004    // 4.2.3. "transparent" color keyword
2005    transparent: [ null, null, null, 0 ],
2006
2007    _default: "#ffffff"
2008};
2009
2010
2011/*!
2012 * jQuery UI Effects 1.14.1
2013 * https://jqueryui.com
2014 *
2015 * Copyright OpenJS Foundation and other contributors
2016 * Released under the MIT license.
2017 * https://jquery.org/license
2018 */
2019
2020//>>label: Effects Core
2021//>>group: Effects
2022/* eslint-disable max-len */
2023//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
2024/* eslint-enable max-len */
2025//>>docs: https://api.jqueryui.com/category/effects-core/
2026//>>demos: https://jqueryui.com/effect/
2027
2028
2029var dataSpace = "ui-effects-",
2030    dataSpaceStyle = "ui-effects-style",
2031    dataSpaceAnimated = "ui-effects-animated";
2032
2033$.effects = {
2034    effect: {}
2035};
2036
2037/******************************************************************************/
2038/****************************** CLASS ANIMATIONS ******************************/
2039/******************************************************************************/
2040( function() {
2041
2042var classAnimationActions = [ "add", "remove", "toggle" ],
2043    shorthandStyles = {
2044        border: 1,
2045        borderBottom: 1,
2046        borderColor: 1,
2047        borderLeft: 1,
2048        borderRight: 1,
2049        borderTop: 1,
2050        borderWidth: 1,
2051        margin: 1,
2052        padding: 1
2053    };
2054
2055$.each(
2056    [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
2057    function( _, prop ) {
2058        $.fx.step[ prop ] = function( fx ) {
2059            if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
2060                jQuery.style( fx.elem, prop, fx.end );
2061                fx.setAttr = true;
2062            }
2063        };
2064    }
2065);
2066
2067function camelCase( string ) {
2068    return string.replace( /-([\da-z])/gi, function( all, letter ) {
2069        return letter.toUpperCase();
2070    } );
2071}
2072
2073function getElementStyles( elem ) {
2074    var key, len,
2075        style = elem.ownerDocument.defaultView.getComputedStyle( elem ),
2076        styles = {};
2077
2078    len = style.length;
2079    while ( len-- ) {
2080        key = style[ len ];
2081        if ( typeof style[ key ] === "string" ) {
2082            styles[ camelCase( key ) ] = style[ key ];
2083        }
2084    }
2085
2086    return styles;
2087}
2088
2089function styleDifference( oldStyle, newStyle ) {
2090    var diff = {},
2091        name, value;
2092
2093    for ( name in newStyle ) {
2094        value = newStyle[ name ];
2095        if ( oldStyle[ name ] !== value ) {
2096            if ( !shorthandStyles[ name ] ) {
2097                if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
2098                    diff[ name ] = value;
2099                }
2100            }
2101        }
2102    }
2103
2104    return diff;
2105}
2106
2107$.effects.animateClass = function( value, duration, easing, callback ) {
2108    var o = $.speed( duration, easing, callback );
2109
2110    return this.queue( function() {
2111        var animated = $( this ),
2112            baseClass = animated.attr( "class" ) || "",
2113            applyClassChange,
2114            allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
2115
2116        // Map the animated objects to store the original styles.
2117        allAnimations = allAnimations.map( function() {
2118            var el = $( this );
2119            return {
2120                el: el,
2121                start: getElementStyles( this )
2122            };
2123        } );
2124
2125        // Apply class change
2126        applyClassChange = function() {
2127            $.each( classAnimationActions, function( i, action ) {
2128                if ( value[ action ] ) {
2129                    animated[ action + "Class" ]( value[ action ] );
2130                }
2131            } );
2132        };
2133        applyClassChange();
2134
2135        // Map all animated objects again - calculate new styles and diff
2136        allAnimations = allAnimations.map( function() {
2137            this.end = getElementStyles( this.el[ 0 ] );
2138            this.diff = styleDifference( this.start, this.end );
2139            return this;
2140        } );
2141
2142        // Apply original class
2143        animated.attr( "class", baseClass );
2144
2145        // Map all animated objects again - this time collecting a promise
2146        allAnimations = allAnimations.map( function() {
2147            var styleInfo = this,
2148                dfd = $.Deferred(),
2149                opts = $.extend( {}, o, {
2150                    queue: false,
2151                    complete: function() {
2152                        dfd.resolve( styleInfo );
2153                    }
2154                } );
2155
2156            this.el.animate( this.diff, opts );
2157            return dfd.promise();
2158        } );
2159
2160        // Once all animations have completed:
2161        $.when.apply( $, allAnimations.get() ).done( function() {
2162
2163            // Set the final class
2164            applyClassChange();
2165
2166            // For each animated element,
2167            // clear all css properties that were animated
2168            $.each( arguments, function() {
2169                var el = this.el;
2170                $.each( this.diff, function( key ) {
2171                    el.css( key, "" );
2172                } );
2173            } );
2174
2175            // This is guarnteed to be there if you use jQuery.speed()
2176            // it also handles dequeuing the next anim...
2177            o.complete.call( animated[ 0 ] );
2178        } );
2179    } );
2180};
2181
2182$.fn.extend( {
2183    addClass: ( function( orig ) {
2184        return function( classNames, speed, easing, callback ) {
2185            return speed ?
2186                $.effects.animateClass.call( this,
2187                    { add: classNames }, speed, easing, callback ) :
2188                orig.apply( this, arguments );
2189        };
2190    } )( $.fn.addClass ),
2191
2192    removeClass: ( function( orig ) {
2193        return function( classNames, speed, easing, callback ) {
2194            return arguments.length > 1 ?
2195                $.effects.animateClass.call( this,
2196                    { remove: classNames }, speed, easing, callback ) :
2197                orig.apply( this, arguments );
2198        };
2199    } )( $.fn.removeClass ),
2200
2201    toggleClass: ( function( orig ) {
2202        return function( classNames, force, speed, easing, callback ) {
2203            if ( typeof force === "boolean" || force === undefined ) {
2204                if ( !speed ) {
2205
2206                    // Without speed parameter
2207                    return orig.apply( this, arguments );
2208                } else {
2209                    return $.effects.animateClass.call( this,
2210                        ( force ? { add: classNames } : { remove: classNames } ),
2211                        speed, easing, callback );
2212                }
2213            } else {
2214
2215                // Without force parameter
2216                return $.effects.animateClass.call( this,
2217                    { toggle: classNames }, force, speed, easing );
2218            }
2219        };
2220    } )( $.fn.toggleClass ),
2221
2222    switchClass: function( remove, add, speed, easing, callback ) {
2223        return $.effects.animateClass.call( this, {
2224            add: add,
2225            remove: remove
2226        }, speed, easing, callback );
2227    }
2228} );
2229
2230} )();
2231
2232/******************************************************************************/
2233/*********************************** EFFECTS **********************************/
2234/******************************************************************************/
2235
2236( function() {
2237
2238if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) {
2239    $.expr.pseudos.animated = ( function( orig ) {
2240        return function( elem ) {
2241            return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
2242        };
2243    } )( $.expr.pseudos.animated );
2244}
2245
2246if ( $.uiBackCompat === true ) {
2247    $.extend( $.effects, {
2248
2249        // Saves a set of properties in a data storage
2250        save: function( element, set ) {
2251            var i = 0, length = set.length;
2252            for ( ; i < length; i++ ) {
2253                if ( set[ i ] !== null ) {
2254                    element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
2255                }
2256            }
2257        },
2258
2259        // Restores a set of previously saved properties from a data storage
2260        restore: function( element, set ) {
2261            var val, i = 0, length = set.length;
2262            for ( ; i < length; i++ ) {
2263                if ( set[ i ] !== null ) {
2264                    val = element.data( dataSpace + set[ i ] );
2265                    element.css( set[ i ], val );
2266                }
2267            }
2268        },
2269
2270        setMode: function( el, mode ) {
2271            if ( mode === "toggle" ) {
2272                mode = el.is( ":hidden" ) ? "show" : "hide";
2273            }
2274            return mode;
2275        },
2276
2277        // Wraps the element around a wrapper that copies position properties
2278        createWrapper: function( element ) {
2279
2280            // If the element is already wrapped, return it
2281            if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2282                return element.parent();
2283            }
2284
2285            // Wrap the element
2286            var props = {
2287                    width: element.outerWidth( true ),
2288                    height: element.outerHeight( true ),
2289                    "float": element.css( "float" )
2290                },
2291                wrapper = $( "<div></div>" )
2292                    .addClass( "ui-effects-wrapper" )
2293                    .css( {
2294                        fontSize: "100%",
2295                        background: "transparent",
2296                        border: "none",
2297                        margin: 0,
2298                        padding: 0
2299                    } ),
2300
2301                // Store the size in case width/height are defined in % - Fixes #5245
2302                size = {
2303                    width: element.width(),
2304                    height: element.height()
2305                },
2306                active = document.activeElement;
2307
2308            // Support: Firefox
2309            // Firefox incorrectly exposes anonymous content
2310            // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
2311            try {
2312                // eslint-disable-next-line no-unused-expressions
2313                active.id;
2314            } catch ( e ) {
2315                active = document.body;
2316            }
2317
2318            element.wrap( wrapper );
2319
2320            // Fixes #7595 - Elements lose focus when wrapped.
2321            if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2322                $( active ).trigger( "focus" );
2323            }
2324
2325            // Hotfix for jQuery 1.4 since some change in wrap() seems to actually
2326            // lose the reference to the wrapped element
2327            wrapper = element.parent();
2328
2329            // Transfer positioning properties to the wrapper
2330            if ( element.css( "position" ) === "static" ) {
2331                wrapper.css( { position: "relative" } );
2332                element.css( { position: "relative" } );
2333            } else {
2334                $.extend( props, {
2335                    position: element.css( "position" ),
2336                    zIndex: element.css( "z-index" )
2337                } );
2338                $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
2339                    props[ pos ] = element.css( pos );
2340                    if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
2341                        props[ pos ] = "auto";
2342                    }
2343                } );
2344                element.css( {
2345                    position: "relative",
2346                    top: 0,
2347                    left: 0,
2348                    right: "auto",
2349                    bottom: "auto"
2350                } );
2351            }
2352            element.css( size );
2353
2354            return wrapper.css( props ).show();
2355        },
2356
2357        removeWrapper: function( element ) {
2358            var active = document.activeElement;
2359
2360            if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2361                element.parent().replaceWith( element );
2362
2363                // Fixes #7595 - Elements lose focus when wrapped.
2364                if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2365                    $( active ).trigger( "focus" );
2366                }
2367            }
2368
2369            return element;
2370        }
2371    } );
2372}
2373
2374$.extend( $.effects, {
2375    version: "1.14.1",
2376
2377    define: function( name, mode, effect ) {
2378        if ( !effect ) {
2379            effect = mode;
2380            mode = "effect";
2381        }
2382
2383        $.effects.effect[ name ] = effect;
2384        $.effects.effect[ name ].mode = mode;
2385
2386        return effect;
2387    },
2388
2389    scaledDimensions: function( element, percent, direction ) {
2390        if ( percent === 0 ) {
2391            return {
2392                height: 0,
2393                width: 0,
2394                outerHeight: 0,
2395                outerWidth: 0
2396            };
2397        }
2398
2399        var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
2400            y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
2401
2402        return {
2403            height: element.height() * y,
2404            width: element.width() * x,
2405            outerHeight: element.outerHeight() * y,
2406            outerWidth: element.outerWidth() * x
2407        };
2408
2409    },
2410
2411    clipToBox: function( animation ) {
2412        return {
2413            width: animation.clip.right - animation.clip.left,
2414            height: animation.clip.bottom - animation.clip.top,
2415            left: animation.clip.left,
2416            top: animation.clip.top
2417        };
2418    },
2419
2420    // Injects recently queued functions to be first in line (after "inprogress")
2421    unshift: function( element, queueLength, count ) {
2422        var queue = element.queue();
2423
2424        if ( queueLength > 1 ) {
2425            queue.splice.apply( queue,
2426                [ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
2427        }
2428        element.dequeue();
2429    },
2430
2431    saveStyle: function( element ) {
2432        element.data( dataSpaceStyle, element[ 0 ].style.cssText );
2433    },
2434
2435    restoreStyle: function( element ) {
2436        element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
2437        element.removeData( dataSpaceStyle );
2438    },
2439
2440    mode: function( element, mode ) {
2441        var hidden = element.is( ":hidden" );
2442
2443        if ( mode === "toggle" ) {
2444            mode = hidden ? "show" : "hide";
2445        }
2446        if ( hidden ? mode === "hide" : mode === "show" ) {
2447            mode = "none";
2448        }
2449        return mode;
2450    },
2451
2452    // Translates a [top,left] array into a baseline value
2453    getBaseline: function( origin, original ) {
2454        var y, x;
2455
2456        switch ( origin[ 0 ] ) {
2457        case "top":
2458            y = 0;
2459            break;
2460        case "middle":
2461            y = 0.5;
2462            break;
2463        case "bottom":
2464            y = 1;
2465            break;
2466        default:
2467            y = origin[ 0 ] / original.height;
2468        }
2469
2470        switch ( origin[ 1 ] ) {
2471        case "left":
2472            x = 0;
2473            break;
2474        case "center":
2475            x = 0.5;
2476            break;
2477        case "right":
2478            x = 1;
2479            break;
2480        default:
2481            x = origin[ 1 ] / original.width;
2482        }
2483
2484        return {
2485            x: x,
2486            y: y
2487        };
2488    },
2489
2490    // Creates a placeholder element so that the original element can be made absolute
2491    createPlaceholder: function( element ) {
2492        var placeholder,
2493            cssPosition = element.css( "position" ),
2494            position = element.position();
2495
2496        // Lock in margins first to account for form elements, which
2497        // will change margin if you explicitly set height
2498        // see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
2499        // Support: Safari
2500        element.css( {
2501            marginTop: element.css( "marginTop" ),
2502            marginBottom: element.css( "marginBottom" ),
2503            marginLeft: element.css( "marginLeft" ),
2504            marginRight: element.css( "marginRight" )
2505        } )
2506        .outerWidth( element.outerWidth() )
2507        .outerHeight( element.outerHeight() );
2508
2509        if ( /^(static|relative)/.test( cssPosition ) ) {
2510            cssPosition = "absolute";
2511
2512            placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
2513
2514                // Convert inline to inline block to account for inline elements
2515                // that turn to inline block based on content (like img)
2516                display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
2517                    "inline-block" :
2518                    "block",
2519                visibility: "hidden",
2520
2521                // Margins need to be set to account for margin collapse
2522                marginTop: element.css( "marginTop" ),
2523                marginBottom: element.css( "marginBottom" ),
2524                marginLeft: element.css( "marginLeft" ),
2525                marginRight: element.css( "marginRight" ),
2526                "float": element.css( "float" )
2527            } )
2528            .outerWidth( element.outerWidth() )
2529            .outerHeight( element.outerHeight() )
2530            .addClass( "ui-effects-placeholder" );
2531
2532            element.data( dataSpace + "placeholder", placeholder );
2533        }
2534
2535        element.css( {
2536            position: cssPosition,
2537            left: position.left,
2538            top: position.top
2539        } );
2540
2541        return placeholder;
2542    },
2543
2544    removePlaceholder: function( element ) {
2545        var dataKey = dataSpace + "placeholder",
2546                placeholder = element.data( dataKey );
2547
2548        if ( placeholder ) {
2549            placeholder.remove();
2550            element.removeData( dataKey );
2551        }
2552    },
2553
2554    // Removes a placeholder if it exists and restores
2555    // properties that were modified during placeholder creation
2556    cleanUp: function( element ) {
2557        $.effects.restoreStyle( element );
2558        $.effects.removePlaceholder( element );
2559    },
2560
2561    setTransition: function( element, list, factor, value ) {
2562        value = value || {};
2563        $.each( list, function( i, x ) {
2564            var unit = element.cssUnit( x );
2565            if ( unit[ 0 ] > 0 ) {
2566                value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
2567            }
2568        } );
2569        return value;
2570    }
2571} );
2572
2573// Return an effect options object for the given parameters:
2574function _normalizeArguments( effect, options, speed, callback ) {
2575
2576    // Allow passing all options as the first parameter
2577    if ( $.isPlainObject( effect ) ) {
2578        options = effect;
2579        effect = effect.effect;
2580    }
2581
2582    // Convert to an object
2583    effect = { effect: effect };
2584
2585    // Catch (effect, null, ...)
2586    if ( options == null ) {
2587        options = {};
2588    }
2589
2590    // Catch (effect, callback)
2591    if ( typeof options === "function" ) {
2592        callback = options;
2593        speed = null;
2594        options = {};
2595    }
2596
2597    // Catch (effect, speed, ?)
2598    if ( typeof options === "number" || $.fx.speeds[ options ] ) {
2599        callback = speed;
2600        speed = options;
2601        options = {};
2602    }
2603
2604    // Catch (effect, options, callback)
2605    if ( typeof speed === "function" ) {
2606        callback = speed;
2607        speed = null;
2608    }
2609
2610    // Add options to effect
2611    if ( options ) {
2612        $.extend( effect, options );
2613    }
2614
2615    speed = speed || options.duration;
2616    effect.duration = $.fx.off ? 0 :
2617        typeof speed === "number" ? speed :
2618        speed in $.fx.speeds ? $.fx.speeds[ speed ] :
2619        $.fx.speeds._default;
2620
2621    effect.complete = callback || options.complete;
2622
2623    return effect;
2624}
2625
2626function standardAnimationOption( option ) {
2627
2628    // Valid standard speeds (nothing, number, named speed)
2629    if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
2630        return true;
2631    }
2632
2633    // Invalid strings - treat as "normal" speed
2634    if ( typeof option === "string" && !$.effects.effect[ option ] ) {
2635        return true;
2636    }
2637
2638    // Complete callback
2639    if ( typeof option === "function" ) {
2640        return true;
2641    }
2642
2643    // Options hash (but not naming an effect)
2644    if ( typeof option === "object" && !option.effect ) {
2645        return true;
2646    }
2647
2648    // Didn't match any standard API
2649    return false;
2650}
2651
2652$.fn.extend( {
2653    effect: function( /* effect, options, speed, callback */ ) {
2654        var args = _normalizeArguments.apply( this, arguments ),
2655            effectMethod = $.effects.effect[ args.effect ],
2656            defaultMode = effectMethod.mode,
2657            queue = args.queue,
2658            queueName = queue || "fx",
2659            complete = args.complete,
2660            mode = args.mode,
2661            modes = [],
2662            prefilter = function( next ) {
2663                var el = $( this ),
2664                    normalizedMode = $.effects.mode( el, mode ) || defaultMode;
2665
2666                // Sentinel for duck-punching the :animated pseudo-selector
2667                el.data( dataSpaceAnimated, true );
2668
2669                // Save effect mode for later use,
2670                // we can't just call $.effects.mode again later,
2671                // as the .show() below destroys the initial state
2672                modes.push( normalizedMode );
2673
2674                // See $.uiBackCompat inside of run() for removal of defaultMode in 1.14
2675                if ( defaultMode && ( normalizedMode === "show" ||
2676                        ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
2677                    el.show();
2678                }
2679
2680                if ( !defaultMode || normalizedMode !== "none" ) {
2681                    $.effects.saveStyle( el );
2682                }
2683
2684                if ( typeof next === "function" ) {
2685                    next();
2686                }
2687            };
2688
2689        if ( $.fx.off || !effectMethod ) {
2690
2691            // Delegate to the original method (e.g., .show()) if possible
2692            if ( mode ) {
2693                return this[ mode ]( args.duration, complete );
2694            } else {
2695                return this.each( function() {
2696                    if ( complete ) {
2697                        complete.call( this );
2698                    }
2699                } );
2700            }
2701        }
2702
2703        function run( next ) {
2704            var elem = $( this );
2705
2706            function cleanup() {
2707                elem.removeData( dataSpaceAnimated );
2708
2709                $.effects.cleanUp( elem );
2710
2711                if ( args.mode === "hide" ) {
2712                    elem.hide();
2713                }
2714
2715                done();
2716            }
2717
2718            function done() {
2719                if ( typeof complete === "function" ) {
2720                    complete.call( elem[ 0 ] );
2721                }
2722
2723                if ( typeof next === "function" ) {
2724                    next();
2725                }
2726            }
2727
2728            // Override mode option on a per element basis,
2729            // as toggle can be either show or hide depending on element state
2730            args.mode = modes.shift();
2731
2732            if ( $.uiBackCompat === true && !defaultMode ) {
2733                if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
2734
2735                    // Call the core method to track "olddisplay" properly
2736                    elem[ mode ]();
2737                    done();
2738                } else {
2739                    effectMethod.call( elem[ 0 ], args, done );
2740                }
2741            } else {
2742                if ( args.mode === "none" ) {
2743
2744                    // Call the core method to track "olddisplay" properly
2745                    elem[ mode ]();
2746                    done();
2747                } else {
2748                    effectMethod.call( elem[ 0 ], args, cleanup );
2749                }
2750            }
2751        }
2752
2753        // Run prefilter on all elements first to ensure that
2754        // any showing or hiding happens before placeholder creation,
2755        // which ensures that any layout changes are correctly captured.
2756        return queue === false ?
2757            this.each( prefilter ).each( run ) :
2758            this.queue( queueName, prefilter ).queue( queueName, run );
2759    },
2760
2761    show: ( function( orig ) {
2762        return function( option ) {
2763            if ( standardAnimationOption( option ) ) {
2764                return orig.apply( this, arguments );
2765            } else {
2766                var args = _normalizeArguments.apply( this, arguments );
2767                args.mode = "show";
2768                return this.effect.call( this, args );
2769            }
2770        };
2771    } )( $.fn.show ),
2772
2773    hide: ( function( orig ) {
2774        return function( option ) {
2775            if ( standardAnimationOption( option ) ) {
2776                return orig.apply( this, arguments );
2777            } else {
2778                var args = _normalizeArguments.apply( this, arguments );
2779                args.mode = "hide";
2780                return this.effect.call( this, args );
2781            }
2782        };
2783    } )( $.fn.hide ),
2784
2785    toggle: ( function( orig ) {
2786        return function( option ) {
2787            if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
2788                return orig.apply( this, arguments );
2789            } else {
2790                var args = _normalizeArguments.apply( this, arguments );
2791                args.mode = "toggle";
2792                return this.effect.call( this, args );
2793            }
2794        };
2795    } )( $.fn.toggle ),
2796
2797    cssUnit: function( key ) {
2798        var style = this.css( key ),
2799            val = [];
2800
2801        $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
2802            if ( style.indexOf( unit ) > 0 ) {
2803                val = [ parseFloat( style ), unit ];
2804            }
2805        } );
2806        return val;
2807    },
2808
2809    cssClip: function( clipObj ) {
2810        if ( clipObj ) {
2811            return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
2812                clipObj.bottom + "px " + clipObj.left + "px)" );
2813        }
2814        return parseClip( this.css( "clip" ), this );
2815    },
2816
2817    transfer: function( options, done ) {
2818        var element = $( this ),
2819            target = $( options.to ),
2820            targetFixed = target.css( "position" ) === "fixed",
2821            body = $( "body" ),
2822            fixTop = targetFixed ? body.scrollTop() : 0,
2823            fixLeft = targetFixed ? body.scrollLeft() : 0,
2824            endPosition = target.offset(),
2825            animation = {
2826                top: endPosition.top - fixTop,
2827                left: endPosition.left - fixLeft,
2828                height: target.innerHeight(),
2829                width: target.innerWidth()
2830            },
2831            startPosition = element.offset(),
2832            transfer = $( "<div class='ui-effects-transfer'></div>" );
2833
2834        transfer
2835            .appendTo( "body" )
2836            .addClass( options.className )
2837            .css( {
2838                top: startPosition.top - fixTop,
2839                left: startPosition.left - fixLeft,
2840                height: element.innerHeight(),
2841                width: element.innerWidth(),
2842                position: targetFixed ? "fixed" : "absolute"
2843            } )
2844            .animate( animation, options.duration, options.easing, function() {
2845                transfer.remove();
2846                if ( typeof done === "function" ) {
2847                    done();
2848                }
2849            } );
2850    }
2851} );
2852
2853function parseClip( str, element ) {
2854        var outerWidth = element.outerWidth(),
2855            outerHeight = element.outerHeight(),
2856            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)\)$/,
2857            values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
2858
2859        return {
2860            top: parseFloat( values[ 1 ] ) || 0,
2861            right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
2862            bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
2863            left: parseFloat( values[ 4 ] ) || 0
2864        };
2865}
2866
2867$.fx.step.clip = function( fx ) {
2868    if ( !fx.clipInit ) {
2869        fx.start = $( fx.elem ).cssClip();
2870        if ( typeof fx.end === "string" ) {
2871            fx.end = parseClip( fx.end, fx.elem );
2872        }
2873        fx.clipInit = true;
2874    }
2875
2876    $( fx.elem ).cssClip( {
2877        top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
2878        right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
2879        bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
2880        left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
2881    } );
2882};
2883
2884} )();
2885
2886/******************************************************************************/
2887/*********************************** EASING ***********************************/
2888/******************************************************************************/
2889
2890( function() {
2891
2892// Based on easing equations from Robert Penner (http://robertpenner.com/easing)
2893
2894var baseEasings = {};
2895
2896$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
2897    baseEasings[ name ] = function( p ) {
2898        return Math.pow( p, i + 2 );
2899    };
2900} );
2901
2902$.extend( baseEasings, {
2903    Sine: function( p ) {
2904        return 1 - Math.cos( p * Math.PI / 2 );
2905    },
2906    Circ: function( p ) {
2907        return 1 - Math.sqrt( 1 - p * p );
2908    },
2909    Elastic: function( p ) {
2910        return p === 0 || p === 1 ? p :
2911            -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
2912    },
2913    Back: function( p ) {
2914        return p * p * ( 3 * p - 2 );
2915    },
2916    Bounce: function( p ) {
2917        var pow2,
2918            bounce = 4;
2919
2920        while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
2921        return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
2922    }
2923} );
2924
2925$.each( baseEasings, function( name, easeIn ) {
2926    $.easing[ "easeIn" + name ] = easeIn;
2927    $.easing[ "easeOut" + name ] = function( p ) {
2928        return 1 - easeIn( 1 - p );
2929    };
2930    $.easing[ "easeInOut" + name ] = function( p ) {
2931        return p < 0.5 ?
2932            easeIn( p * 2 ) / 2 :
2933            1 - easeIn( p * -2 + 2 ) / 2;
2934    };
2935} );
2936
2937} )();
2938
2939var effect = $.effects;
2940
2941
2942/*!
2943 * jQuery UI Effects Blind 1.14.1
2944 * https://jqueryui.com
2945 *
2946 * Copyright OpenJS Foundation and other contributors
2947 * Released under the MIT license.
2948 * https://jquery.org/license
2949 */
2950
2951//>>label: Blind Effect
2952//>>group: Effects
2953//>>description: Blinds the element.
2954//>>docs: https://api.jqueryui.com/blind-effect/
2955//>>demos: https://jqueryui.com/effect/
2956
2957
2958var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
2959    var map = {
2960            up: [ "bottom", "top" ],
2961            vertical: [ "bottom", "top" ],
2962            down: [ "top", "bottom" ],
2963            left: [ "right", "left" ],
2964            horizontal: [ "right", "left" ],
2965            right: [ "left", "right" ]
2966        },
2967        element = $( this ),
2968        direction = options.direction || "up",
2969        start = element.cssClip(),
2970        animate = { clip: $.extend( {}, start ) },
2971        placeholder = $.effects.createPlaceholder( element );
2972
2973    animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
2974
2975    if ( options.mode === "show" ) {
2976        element.cssClip( animate.clip );
2977        if ( placeholder ) {
2978            placeholder.css( $.effects.clipToBox( animate ) );
2979        }
2980
2981        animate.clip = start;
2982    }
2983
2984    if ( placeholder ) {
2985        placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
2986    }
2987
2988    element.animate( animate, {
2989        queue: false,
2990        duration: options.duration,
2991        easing: options.easing,
2992        complete: done
2993    } );
2994} );
2995
2996
2997/*!
2998 * jQuery UI Effects Bounce 1.14.1
2999 * https://jqueryui.com
3000 *
3001 * Copyright OpenJS Foundation and other contributors
3002 * Released under the MIT license.
3003 * https://jquery.org/license
3004 */
3005
3006//>>label: Bounce Effect
3007//>>group: Effects
3008//>>description: Bounces an element horizontally or vertically n times.
3009//>>docs: https://api.jqueryui.com/bounce-effect/
3010//>>demos: https://jqueryui.com/effect/
3011
3012
3013var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
3014    var upAnim, downAnim, refValue,
3015        element = $( this ),
3016
3017        // Defaults:
3018        mode = options.mode,
3019        hide = mode === "hide",
3020        show = mode === "show",
3021        direction = options.direction || "up",
3022        distance = options.distance,
3023        times = options.times || 5,
3024
3025        // Number of internal animations
3026        anims = times * 2 + ( show || hide ? 1 : 0 ),
3027        speed = options.duration / anims,
3028        easing = options.easing,
3029
3030        // Utility:
3031        ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3032        motion = ( direction === "up" || direction === "left" ),
3033        i = 0,
3034
3035        queuelen = element.queue().length;
3036
3037    $.effects.createPlaceholder( element );
3038
3039    refValue = element.css( ref );
3040
3041    // Default distance for the BIGGEST bounce is the outer Distance / 3
3042    if ( !distance ) {
3043        distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
3044    }
3045
3046    if ( show ) {
3047        downAnim = { opacity: 1 };
3048        downAnim[ ref ] = refValue;
3049
3050        // If we are showing, force opacity 0 and set the initial position
3051        // then do the "first" animation
3052        element
3053            .css( "opacity", 0 )
3054            .css( ref, motion ? -distance * 2 : distance * 2 )
3055            .animate( downAnim, speed, easing );
3056    }
3057
3058    // Start at the smallest distance if we are hiding
3059    if ( hide ) {
3060        distance = distance / Math.pow( 2, times - 1 );
3061    }
3062
3063    downAnim = {};
3064    downAnim[ ref ] = refValue;
3065
3066    // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
3067    for ( ; i < times; i++ ) {
3068        upAnim = {};
3069        upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3070
3071        element
3072            .animate( upAnim, speed, easing )
3073            .animate( downAnim, speed, easing );
3074
3075        distance = hide ? distance * 2 : distance / 2;
3076    }
3077
3078    // Last Bounce when Hiding
3079    if ( hide ) {
3080        upAnim = { opacity: 0 };
3081        upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3082
3083        element.animate( upAnim, speed, easing );
3084    }
3085
3086    element.queue( done );
3087
3088    $.effects.unshift( element, queuelen, anims + 1 );
3089} );
3090
3091
3092/*!
3093 * jQuery UI Effects Clip 1.14.1
3094 * https://jqueryui.com
3095 *
3096 * Copyright OpenJS Foundation and other contributors
3097 * Released under the MIT license.
3098 * https://jquery.org/license
3099 */
3100
3101//>>label: Clip Effect
3102//>>group: Effects
3103//>>description: Clips the element on and off like an old TV.
3104//>>docs: https://api.jqueryui.com/clip-effect/
3105//>>demos: https://jqueryui.com/effect/
3106
3107
3108var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
3109    var start,
3110        animate = {},
3111        element = $( this ),
3112        direction = options.direction || "vertical",
3113        both = direction === "both",
3114        horizontal = both || direction === "horizontal",
3115        vertical = both || direction === "vertical";
3116
3117    start = element.cssClip();
3118    animate.clip = {
3119        top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
3120        right: horizontal ? ( start.right - start.left ) / 2 : start.right,
3121        bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
3122        left: horizontal ? ( start.right - start.left ) / 2 : start.left
3123    };
3124
3125    $.effects.createPlaceholder( element );
3126
3127    if ( options.mode === "show" ) {
3128        element.cssClip( animate.clip );
3129        animate.clip = start;
3130    }
3131
3132    element.animate( animate, {
3133        queue: false,
3134        duration: options.duration,
3135        easing: options.easing,
3136        complete: done
3137    } );
3138
3139} );
3140
3141
3142/*!
3143 * jQuery UI Effects Drop 1.14.1
3144 * https://jqueryui.com
3145 *
3146 * Copyright OpenJS Foundation and other contributors
3147 * Released under the MIT license.
3148 * https://jquery.org/license
3149 */
3150
3151//>>label: Drop Effect
3152//>>group: Effects
3153//>>description: Moves an element in one direction and hides it at the same time.
3154//>>docs: https://api.jqueryui.com/drop-effect/
3155//>>demos: https://jqueryui.com/effect/
3156
3157
3158var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
3159
3160    var distance,
3161        element = $( this ),
3162        mode = options.mode,
3163        show = mode === "show",
3164        direction = options.direction || "left",
3165        ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3166        motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
3167        oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
3168        animation = {
3169            opacity: 0
3170        };
3171
3172    $.effects.createPlaceholder( element );
3173
3174    distance = options.distance ||
3175        element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
3176
3177    animation[ ref ] = motion + distance;
3178
3179    if ( show ) {
3180        element.css( animation );
3181
3182        animation[ ref ] = oppositeMotion + distance;
3183        animation.opacity = 1;
3184    }
3185
3186    // Animate
3187    element.animate( animation, {
3188        queue: false,
3189        duration: options.duration,
3190        easing: options.easing,
3191        complete: done
3192    } );
3193} );
3194
3195
3196/*!
3197 * jQuery UI Effects Explode 1.14.1
3198 * https://jqueryui.com
3199 *
3200 * Copyright OpenJS Foundation and other contributors
3201 * Released under the MIT license.
3202 * https://jquery.org/license
3203 */
3204
3205//>>label: Explode Effect
3206//>>group: Effects
3207/* eslint-disable max-len */
3208//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
3209/* eslint-enable max-len */
3210//>>docs: https://api.jqueryui.com/explode-effect/
3211//>>demos: https://jqueryui.com/effect/
3212
3213
3214var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
3215
3216    var i, j, left, top, mx, my,
3217        rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
3218        cells = rows,
3219        element = $( this ),
3220        mode = options.mode,
3221        show = mode === "show",
3222
3223        // Show and then visibility:hidden the element before calculating offset
3224        offset = element.show().css( "visibility", "hidden" ).offset(),
3225
3226        // Width and height of a piece
3227        width = Math.ceil( element.outerWidth() / cells ),
3228        height = Math.ceil( element.outerHeight() / rows ),
3229        pieces = [];
3230
3231    // Children animate complete:
3232    function childComplete() {
3233        pieces.push( this );
3234        if ( pieces.length === rows * cells ) {
3235            animComplete();
3236        }
3237    }
3238
3239    // Clone the element for each row and cell.
3240    for ( i = 0; i < rows; i++ ) { // ===>
3241        top = offset.top + i * height;
3242        my = i - ( rows - 1 ) / 2;
3243
3244        for ( j = 0; j < cells; j++ ) { // |||
3245            left = offset.left + j * width;
3246            mx = j - ( cells - 1 ) / 2;
3247
3248            // Create a clone of the now hidden main element that will be absolute positioned
3249            // within a wrapper div off the -left and -top equal to size of our pieces
3250            element
3251                .clone()
3252                .appendTo( "body" )
3253                .wrap( "<div></div>" )
3254                .css( {
3255                    position: "absolute",
3256                    visibility: "visible",
3257                    left: -j * width,
3258                    top: -i * height
3259                } )
3260
3261                // Select the wrapper - make it overflow: hidden and absolute positioned based on
3262                // where the original was located +left and +top equal to the size of pieces
3263                .parent()
3264                    .addClass( "ui-effects-explode" )
3265                    .css( {
3266                        position: "absolute",
3267                        overflow: "hidden",
3268                        width: width,
3269                        height: height,
3270                        left: left + ( show ? mx * width : 0 ),
3271                        top: top + ( show ? my * height : 0 ),
3272                        opacity: show ? 0 : 1
3273                    } )
3274                    .animate( {
3275                        left: left + ( show ? 0 : mx * width ),
3276                        top: top + ( show ? 0 : my * height ),
3277                        opacity: show ? 1 : 0
3278                    }, options.duration || 500, options.easing, childComplete );
3279        }
3280    }
3281
3282    function animComplete() {
3283        element.css( {
3284            visibility: "visible"
3285        } );
3286        $( pieces ).remove();
3287        done();
3288    }
3289} );
3290
3291
3292/*!
3293 * jQuery UI Effects Fade 1.14.1
3294 * https://jqueryui.com
3295 *
3296 * Copyright OpenJS Foundation and other contributors
3297 * Released under the MIT license.
3298 * https://jquery.org/license
3299 */
3300
3301//>>label: Fade Effect
3302//>>group: Effects
3303//>>description: Fades the element.
3304//>>docs: https://api.jqueryui.com/fade-effect/
3305//>>demos: https://jqueryui.com/effect/
3306
3307
3308var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
3309    var show = options.mode === "show";
3310
3311    $( this )
3312        .css( "opacity", show ? 0 : 1 )
3313        .animate( {
3314            opacity: show ? 1 : 0
3315        }, {
3316            queue: false,
3317            duration: options.duration,
3318            easing: options.easing,
3319            complete: done
3320        } );
3321} );
3322
3323
3324/*!
3325 * jQuery UI Effects Fold 1.14.1
3326 * https://jqueryui.com
3327 *
3328 * Copyright OpenJS Foundation and other contributors
3329 * Released under the MIT license.
3330 * https://jquery.org/license
3331 */
3332
3333//>>label: Fold Effect
3334//>>group: Effects
3335//>>description: Folds an element first horizontally and then vertically.
3336//>>docs: https://api.jqueryui.com/fold-effect/
3337//>>demos: https://jqueryui.com/effect/
3338
3339
3340var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
3341
3342    // Create element
3343    var element = $( this ),
3344        mode = options.mode,
3345        show = mode === "show",
3346        hide = mode === "hide",
3347        size = options.size || 15,
3348        percent = /([0-9]+)%/.exec( size ),
3349        horizFirst = !!options.horizFirst,
3350        ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
3351        duration = options.duration / 2,
3352
3353        placeholder = $.effects.createPlaceholder( element ),
3354
3355        start = element.cssClip(),
3356        animation1 = { clip: $.extend( {}, start ) },
3357        animation2 = { clip: $.extend( {}, start ) },
3358
3359        distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
3360
3361        queuelen = element.queue().length;
3362
3363    if ( percent ) {
3364        size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
3365    }
3366    animation1.clip[ ref[ 0 ] ] = size;
3367    animation2.clip[ ref[ 0 ] ] = size;
3368    animation2.clip[ ref[ 1 ] ] = 0;
3369
3370    if ( show ) {
3371        element.cssClip( animation2.clip );
3372        if ( placeholder ) {
3373            placeholder.css( $.effects.clipToBox( animation2 ) );
3374        }
3375
3376        animation2.clip = start;
3377    }
3378
3379    // Animate
3380    element
3381        .queue( function( next ) {
3382            if ( placeholder ) {
3383                placeholder
3384                    .animate( $.effects.clipToBox( animation1 ), duration, options.easing )
3385                    .animate( $.effects.clipToBox( animation2 ), duration, options.easing );
3386            }
3387
3388            next();
3389        } )
3390        .animate( animation1, duration, options.easing )
3391        .animate( animation2, duration, options.easing )
3392        .queue( done );
3393
3394    $.effects.unshift( element, queuelen, 4 );
3395} );
3396
3397
3398/*!
3399 * jQuery UI Effects Highlight 1.14.1
3400 * https://jqueryui.com
3401 *
3402 * Copyright OpenJS Foundation and other contributors
3403 * Released under the MIT license.
3404 * https://jquery.org/license
3405 */
3406
3407//>>label: Highlight Effect
3408//>>group: Effects
3409//>>description: Highlights the background of an element in a defined color for a custom duration.
3410//>>docs: https://api.jqueryui.com/highlight-effect/
3411//>>demos: https://jqueryui.com/effect/
3412
3413
3414var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
3415    var element = $( this ),
3416        animation = {
3417            backgroundColor: element.css( "backgroundColor" )
3418        };
3419
3420    if ( options.mode === "hide" ) {
3421        animation.opacity = 0;
3422    }
3423
3424    $.effects.saveStyle( element );
3425
3426    element
3427        .css( {
3428            backgroundImage: "none",
3429            backgroundColor: options.color || "#ffff99"
3430        } )
3431        .animate( animation, {
3432            queue: false,
3433            duration: options.duration,
3434            easing: options.easing,
3435            complete: done
3436        } );
3437} );
3438
3439
3440/*!
3441 * jQuery UI Effects Size 1.14.1
3442 * https://jqueryui.com
3443 *
3444 * Copyright OpenJS Foundation and other contributors
3445 * Released under the MIT license.
3446 * https://jquery.org/license
3447 */
3448
3449//>>label: Size Effect
3450//>>group: Effects
3451//>>description: Resize an element to a specified width and height.
3452//>>docs: https://api.jqueryui.com/size-effect/
3453//>>demos: https://jqueryui.com/effect/
3454
3455
3456var effectsEffectSize = $.effects.define( "size", function( options, done ) {
3457
3458    // Create element
3459    var baseline, factor, temp,
3460        element = $( this ),
3461
3462        // Copy for children
3463        cProps = [ "fontSize" ],
3464        vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
3465        hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
3466
3467        // Set options
3468        mode = options.mode,
3469        restore = mode !== "effect",
3470        scale = options.scale || "both",
3471        origin = options.origin || [ "middle", "center" ],
3472        position = element.css( "position" ),
3473        pos = element.position(),
3474        original = $.effects.scaledDimensions( element ),
3475        from = options.from || original,
3476        to = options.to || $.effects.scaledDimensions( element, 0 );
3477
3478    $.effects.createPlaceholder( element );
3479
3480    if ( mode === "show" ) {
3481        temp = from;
3482        from = to;
3483        to = temp;
3484    }
3485
3486    // Set scaling factor
3487    factor = {
3488        from: {
3489            y: from.height / original.height,
3490            x: from.width / original.width
3491        },
3492        to: {
3493            y: to.height / original.height,
3494            x: to.width / original.width
3495        }
3496    };
3497
3498    // Scale the css box
3499    if ( scale === "box" || scale === "both" ) {
3500
3501        // Vertical props scaling
3502        if ( factor.from.y !== factor.to.y ) {
3503            from = $.effects.setTransition( element, vProps, factor.from.y, from );
3504            to = $.effects.setTransition( element, vProps, factor.to.y, to );
3505        }
3506
3507        // Horizontal props scaling
3508        if ( factor.from.x !== factor.to.x ) {
3509            from = $.effects.setTransition( element, hProps, factor.from.x, from );
3510            to = $.effects.setTransition( element, hProps, factor.to.x, to );
3511        }
3512    }
3513
3514    // Scale the content
3515    if ( scale === "content" || scale === "both" ) {
3516
3517        // Vertical props scaling
3518        if ( factor.from.y !== factor.to.y ) {
3519            from = $.effects.setTransition( element, cProps, factor.from.y, from );
3520            to = $.effects.setTransition( element, cProps, factor.to.y, to );
3521        }
3522    }
3523
3524    // Adjust the position properties based on the provided origin points
3525    if ( origin ) {
3526        baseline = $.effects.getBaseline( origin, original );
3527        from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
3528        from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
3529        to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
3530        to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
3531    }
3532    delete from.outerHeight;
3533    delete from.outerWidth;
3534    element.css( from );
3535
3536    // Animate the children if desired
3537    if ( scale === "content" || scale === "both" ) {
3538
3539        vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
3540        hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
3541
3542        // Only animate children with width attributes specified
3543        // TODO: is this right? should we include anything with css width specified as well
3544        element.find( "*[width]" ).each( function() {
3545            var child = $( this ),
3546                childOriginal = $.effects.scaledDimensions( child ),
3547                childFrom = {
3548                    height: childOriginal.height * factor.from.y,
3549                    width: childOriginal.width * factor.from.x,
3550                    outerHeight: childOriginal.outerHeight * factor.from.y,
3551                    outerWidth: childOriginal.outerWidth * factor.from.x
3552                },
3553                childTo = {
3554                    height: childOriginal.height * factor.to.y,
3555                    width: childOriginal.width * factor.to.x,
3556                    outerHeight: childOriginal.height * factor.to.y,
3557                    outerWidth: childOriginal.width * factor.to.x
3558                };
3559
3560            // Vertical props scaling
3561            if ( factor.from.y !== factor.to.y ) {
3562                childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
3563                childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
3564            }
3565
3566            // Horizontal props scaling
3567            if ( factor.from.x !== factor.to.x ) {
3568                childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
3569                childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
3570            }
3571
3572            if ( restore ) {
3573                $.effects.saveStyle( child );
3574            }
3575
3576            // Animate children
3577            child.css( childFrom );
3578            child.animate( childTo, options.duration, options.easing, function() {
3579
3580                // Restore children
3581                if ( restore ) {
3582                    $.effects.restoreStyle( child );
3583                }
3584            } );
3585        } );
3586    }
3587
3588    // Animate
3589    element.animate( to, {
3590        queue: false,
3591        duration: options.duration,
3592        easing: options.easing,
3593        complete: function() {
3594
3595            var offset = element.offset();
3596
3597            if ( to.opacity === 0 ) {
3598                element.css( "opacity", from.opacity );
3599            }
3600
3601            if ( !restore ) {
3602                element
3603                    .css( "position", position === "static" ? "relative" : position )
3604                    .offset( offset );
3605
3606                // Need to save style here so that automatic style restoration
3607                // doesn't restore to the original styles from before the animation.
3608                $.effects.saveStyle( element );
3609            }
3610
3611            done();
3612        }
3613    } );
3614
3615} );
3616
3617
3618/*!
3619 * jQuery UI Effects Scale 1.14.1
3620 * https://jqueryui.com
3621 *
3622 * Copyright OpenJS Foundation and other contributors
3623 * Released under the MIT license.
3624 * https://jquery.org/license
3625 */
3626
3627//>>label: Scale Effect
3628//>>group: Effects
3629//>>description: Grows or shrinks an element and its content.
3630//>>docs: https://api.jqueryui.com/scale-effect/
3631//>>demos: https://jqueryui.com/effect/
3632
3633
3634var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
3635
3636    // Create element
3637    var el = $( this ),
3638        mode = options.mode,
3639        percent = parseInt( options.percent, 10 ) ||
3640            ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
3641
3642        newOptions = $.extend( true, {
3643            from: $.effects.scaledDimensions( el ),
3644            to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
3645            origin: options.origin || [ "middle", "center" ]
3646        }, options );
3647
3648    // Fade option to support puff
3649    if ( options.fade ) {
3650        newOptions.from.opacity = 1;
3651        newOptions.to.opacity = 0;
3652    }
3653
3654    $.effects.effect.size.call( this, newOptions, done );
3655} );
3656
3657
3658/*!
3659 * jQuery UI Effects Puff 1.14.1
3660 * https://jqueryui.com
3661 *
3662 * Copyright OpenJS Foundation and other contributors
3663 * Released under the MIT license.
3664 * https://jquery.org/license
3665 */
3666
3667//>>label: Puff Effect
3668//>>group: Effects
3669//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
3670//>>docs: https://api.jqueryui.com/puff-effect/
3671//>>demos: https://jqueryui.com/effect/
3672
3673
3674var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
3675    var newOptions = $.extend( true, {}, options, {
3676        fade: true,
3677        percent: parseInt( options.percent, 10 ) || 150
3678    } );
3679
3680    $.effects.effect.scale.call( this, newOptions, done );
3681} );
3682
3683
3684/*!
3685 * jQuery UI Effects Pulsate 1.14.1
3686 * https://jqueryui.com
3687 *
3688 * Copyright OpenJS Foundation and other contributors
3689 * Released under the MIT license.
3690 * https://jquery.org/license
3691 */
3692
3693//>>label: Pulsate Effect
3694//>>group: Effects
3695//>>description: Pulsates an element n times by changing the opacity to zero and back.
3696//>>docs: https://api.jqueryui.com/pulsate-effect/
3697//>>demos: https://jqueryui.com/effect/
3698
3699
3700var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
3701    var element = $( this ),
3702        mode = options.mode,
3703        show = mode === "show",
3704        hide = mode === "hide",
3705        showhide = show || hide,
3706
3707        // Showing or hiding leaves off the "last" animation
3708        anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
3709        duration = options.duration / anims,
3710        animateTo = 0,
3711        i = 1,
3712        queuelen = element.queue().length;
3713
3714    if ( show || !element.is( ":visible" ) ) {
3715        element.css( "opacity", 0 ).show();
3716        animateTo = 1;
3717    }
3718
3719    // Anims - 1 opacity "toggles"
3720    for ( ; i < anims; i++ ) {
3721        element.animate( { opacity: animateTo }, duration, options.easing );
3722        animateTo = 1 - animateTo;
3723    }
3724
3725    element.animate( { opacity: animateTo }, duration, options.easing );
3726
3727    element.queue( done );
3728
3729    $.effects.unshift( element, queuelen, anims + 1 );
3730} );
3731
3732
3733/*!
3734 * jQuery UI Effects Shake 1.14.1
3735 * https://jqueryui.com
3736 *
3737 * Copyright OpenJS Foundation and other contributors
3738 * Released under the MIT license.
3739 * https://jquery.org/license
3740 */
3741
3742//>>label: Shake Effect
3743//>>group: Effects
3744//>>description: Shakes an element horizontally or vertically n times.
3745//>>docs: https://api.jqueryui.com/shake-effect/
3746//>>demos: https://jqueryui.com/effect/
3747
3748
3749var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
3750
3751    var i = 1,
3752        element = $( this ),
3753        direction = options.direction || "left",
3754        distance = options.distance || 20,
3755        times = options.times || 3,
3756        anims = times * 2 + 1,
3757        speed = Math.round( options.duration / anims ),
3758        ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3759        positiveMotion = ( direction === "up" || direction === "left" ),
3760        animation = {},
3761        animation1 = {},
3762        animation2 = {},
3763
3764        queuelen = element.queue().length;
3765
3766    $.effects.createPlaceholder( element );
3767
3768    // Animation
3769    animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
3770    animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
3771    animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
3772
3773    // Animate
3774    element.animate( animation, speed, options.easing );
3775
3776    // Shakes
3777    for ( ; i < times; i++ ) {
3778        element
3779            .animate( animation1, speed, options.easing )
3780            .animate( animation2, speed, options.easing );
3781    }
3782
3783    element
3784        .animate( animation1, speed, options.easing )
3785        .animate( animation, speed / 2, options.easing )
3786        .queue( done );
3787
3788    $.effects.unshift( element, queuelen, anims + 1 );
3789} );
3790
3791
3792/*!
3793 * jQuery UI Effects Slide 1.14.1
3794 * https://jqueryui.com
3795 *
3796 * Copyright OpenJS Foundation and other contributors
3797 * Released under the MIT license.
3798 * https://jquery.org/license
3799 */
3800
3801//>>label: Slide Effect
3802//>>group: Effects
3803//>>description: Slides an element in and out of the viewport.
3804//>>docs: https://api.jqueryui.com/slide-effect/
3805//>>demos: https://jqueryui.com/effect/
3806
3807
3808var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
3809    var startClip, startRef,
3810        element = $( this ),
3811        map = {
3812            up: [ "bottom", "top" ],
3813            down: [ "top", "bottom" ],
3814            left: [ "right", "left" ],
3815            right: [ "left", "right" ]
3816        },
3817        mode = options.mode,
3818        direction = options.direction || "left",
3819        ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3820        positiveMotion = ( direction === "up" || direction === "left" ),
3821        distance = options.distance ||
3822            element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
3823        animation = {};
3824
3825    $.effects.createPlaceholder( element );
3826
3827    startClip = element.cssClip();
3828    startRef = element.position()[ ref ];
3829
3830    // Define hide animation
3831    animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
3832    animation.clip = element.cssClip();
3833    animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
3834
3835    // Reverse the animation if we're showing
3836    if ( mode === "show" ) {
3837        element.cssClip( animation.clip );
3838        element.css( ref, animation[ ref ] );
3839        animation.clip = startClip;
3840        animation[ ref ] = startRef;
3841    }
3842
3843    // Actually animate
3844    element.animate( animation, {
3845        queue: false,
3846        duration: options.duration,
3847        easing: options.easing,
3848        complete: done
3849    } );
3850} );
3851
3852
3853/*!
3854 * jQuery UI Effects Transfer 1.14.1
3855 * https://jqueryui.com
3856 *
3857 * Copyright OpenJS Foundation and other contributors
3858 * Released under the MIT license.
3859 * https://jquery.org/license
3860 */
3861
3862//>>label: Transfer Effect
3863//>>group: Effects
3864//>>description: Displays a transfer effect from one element to another.
3865//>>docs: https://api.jqueryui.com/transfer-effect/
3866//>>demos: https://jqueryui.com/effect/
3867
3868
3869var effect;
3870if ( $.uiBackCompat === true ) {
3871    effect = $.effects.define( "transfer", function( options, done ) {
3872        $( this ).transfer( options, done );
3873    } );
3874}
3875var effectsEffectTransfer = effect;
3876
3877
3878/*!
3879 * jQuery UI Focusable 1.14.1
3880 * https://jqueryui.com
3881 *
3882 * Copyright OpenJS Foundation and other contributors
3883 * Released under the MIT license.
3884 * https://jquery.org/license
3885 */
3886
3887//>>label: :focusable Selector
3888//>>group: Core
3889//>>description: Selects elements which can be focused.
3890//>>docs: https://api.jqueryui.com/focusable-selector/
3891
3892
3893// Selectors
3894$.ui.focusable = function( element, hasTabindex ) {
3895    var map, mapName, img, focusableIfVisible, fieldset,
3896        nodeName = element.nodeName.toLowerCase();
3897
3898    if ( "area" === nodeName ) {
3899        map = element.parentNode;
3900        mapName = map.name;
3901        if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
3902            return false;
3903        }
3904        img = $( "img[usemap='#" + mapName + "']" );
3905        return img.length > 0 && img.is( ":visible" );
3906    }
3907
3908    if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
3909        focusableIfVisible = !element.disabled;
3910
3911        if ( focusableIfVisible ) {
3912
3913            // Form controls within a disabled fieldset are disabled.
3914            // However, controls within the fieldset's legend do not get disabled.
3915            // Since controls generally aren't placed inside legends, we skip
3916            // this portion of the check.
3917            fieldset = $( element ).closest( "fieldset" )[ 0 ];
3918            if ( fieldset ) {
3919                focusableIfVisible = !fieldset.disabled;
3920            }
3921        }
3922    } else if ( "a" === nodeName ) {
3923        focusableIfVisible = element.href || hasTabindex;
3924    } else {
3925        focusableIfVisible = hasTabindex;
3926    }
3927
3928    return focusableIfVisible && $( element ).is( ":visible" ) &&
3929        $( element ).css( "visibility" ) === "visible";
3930};
3931
3932$.extend( $.expr.pseudos, {
3933    focusable: function( element ) {
3934        return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
3935    }
3936} );
3937
3938var focusable = $.ui.focusable;
3939
3940
3941/*!
3942 * jQuery UI Form Reset Mixin 1.14.1
3943 * https://jqueryui.com
3944 *
3945 * Copyright OpenJS Foundation and other contributors
3946 * Released under the MIT license.
3947 * https://jquery.org/license
3948 */
3949
3950//>>label: Form Reset Mixin
3951//>>group: Core
3952//>>description: Refresh input widgets when their form is reset
3953//>>docs: https://api.jqueryui.com/form-reset-mixin/
3954
3955
3956var formResetMixin = $.ui.formResetMixin = {
3957    _formResetHandler: function() {
3958        var form = $( this );
3959
3960        // Wait for the form reset to actually happen before refreshing
3961        setTimeout( function() {
3962            var instances = form.data( "ui-form-reset-instances" );
3963            $.each( instances, function() {
3964                this.refresh();
3965            } );
3966        } );
3967    },
3968
3969    _bindFormResetHandler: function() {
3970        this.form = $( this.element.prop( "form" ) );
3971        if ( !this.form.length ) {
3972            return;
3973        }
3974
3975        var instances = this.form.data( "ui-form-reset-instances" ) || [];
3976        if ( !instances.length ) {
3977
3978            // We don't use _on() here because we use a single event handler per form
3979            this.form.on( "reset.ui-form-reset", this._formResetHandler );
3980        }
3981        instances.push( this );
3982        this.form.data( "ui-form-reset-instances", instances );
3983    },
3984
3985    _unbindFormResetHandler: function() {
3986        if ( !this.form.length ) {
3987            return;
3988        }
3989
3990        var instances = this.form.data( "ui-form-reset-instances" );
3991        instances.splice( $.inArray( this, instances ), 1 );
3992        if ( instances.length ) {
3993            this.form.data( "ui-form-reset-instances", instances );
3994        } else {
3995            this.form
3996                .removeData( "ui-form-reset-instances" )
3997                .off( "reset.ui-form-reset" );
3998        }
3999    }
4000};
4001
4002
4003/*!
4004 * jQuery UI Legacy jQuery Core patches 1.14.1
4005 * https://jqueryui.com
4006 *
4007 * Copyright OpenJS Foundation and other contributors
4008 * Released under the MIT license.
4009 * https://jquery.org/license
4010 *
4011 */
4012
4013//>>label: Legacy jQuery Core patches
4014//>>group: Core
4015//>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated)
4016
4017
4018// Support: jQuery 2.2.x or older.
4019// This method has been defined in jQuery 3.0.0.
4020// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
4021if ( !$.escapeSelector ) {
4022    $.escapeSelector = function( id ) {
4023        return CSS.escape( id + "" );
4024    };
4025}
4026
4027// Support: jQuery 3.4.x or older
4028// These methods have been defined in jQuery 3.5.0.
4029if ( !$.fn.even || !$.fn.odd ) {
4030    $.fn.extend( {
4031        even: function() {
4032            return this.filter( function( i ) {
4033                return i % 2 === 0;
4034            } );
4035        },
4036        odd: function() {
4037            return this.filter( function( i ) {
4038                return i % 2 === 1;
4039            } );
4040        }
4041    } );
4042}
4043
4044;
4045/*!
4046 * jQuery UI Keycode 1.14.1
4047 * https://jqueryui.com
4048 *
4049 * Copyright OpenJS Foundation and other contributors
4050 * Released under the MIT license.
4051 * https://jquery.org/license
4052 */
4053
4054//>>label: Keycode
4055//>>group: Core
4056//>>description: Provide keycodes as keynames
4057//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/
4058
4059
4060var keycode = $.ui.keyCode = {
4061    BACKSPACE: 8,
4062    COMMA: 188,
4063    DELETE: 46,
4064    DOWN: 40,
4065    END: 35,
4066    ENTER: 13,
4067    ESCAPE: 27,
4068    HOME: 36,
4069    LEFT: 37,
4070    PAGE_DOWN: 34,
4071    PAGE_UP: 33,
4072    PERIOD: 190,
4073    RIGHT: 39,
4074    SPACE: 32,
4075    TAB: 9,
4076    UP: 38
4077};
4078
4079
4080/*!
4081 * jQuery UI Labels 1.14.1
4082 * https://jqueryui.com
4083 *
4084 * Copyright OpenJS Foundation and other contributors
4085 * Released under the MIT license.
4086 * https://jquery.org/license
4087 */
4088
4089//>>label: labels
4090//>>group: Core
4091//>>description: Find all the labels associated with a given input
4092//>>docs: https://api.jqueryui.com/labels/
4093
4094
4095var labels = $.fn.labels = function() {
4096    var ancestor, selector, id, labels, ancestors;
4097
4098    if ( !this.length ) {
4099        return this.pushStack( [] );
4100    }
4101
4102    // Check control.labels first
4103    if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
4104        return this.pushStack( this[ 0 ].labels );
4105    }
4106
4107    // If `control.labels` is empty - e.g. inside of document fragments - find
4108    // the labels manually
4109    labels = this.eq( 0 ).parents( "label" );
4110
4111    // Look for the label based on the id
4112    id = this.attr( "id" );
4113    if ( id ) {
4114
4115        // We don't search against the document in case the element
4116        // is disconnected from the DOM
4117        ancestor = this.eq( 0 ).parents().last();
4118
4119        // Get a full set of top level ancestors
4120        ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
4121
4122        // Create a selector for the label based on the id
4123        selector = "label[for='" + CSS.escape( id ) + "']";
4124
4125        labels = labels.add( ancestors.find( selector ).addBack( selector ) );
4126
4127    }
4128
4129    // Return whatever we have found for labels
4130    return this.pushStack( labels );
4131};
4132
4133
4134/*!
4135 * jQuery UI Scroll Parent 1.14.1
4136 * https://jqueryui.com
4137 *
4138 * Copyright OpenJS Foundation and other contributors
4139 * Released under the MIT license.
4140 * https://jquery.org/license
4141 */
4142
4143//>>label: scrollParent
4144//>>group: Core
4145//>>description: Get the closest ancestor element that is scrollable.
4146//>>docs: https://api.jqueryui.com/scrollParent/
4147
4148
4149var scrollParent = $.fn.scrollParent = function( includeHidden ) {
4150    var position = this.css( "position" ),
4151        excludeStaticParent = position === "absolute",
4152        overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
4153        scrollParent = this.parents().filter( function() {
4154            var parent = $( this );
4155            if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
4156                return false;
4157            }
4158            return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
4159                parent.css( "overflow-x" ) );
4160        } ).eq( 0 );
4161
4162    return position === "fixed" || !scrollParent.length ?
4163        $( this[ 0 ].ownerDocument || document ) :
4164        scrollParent;
4165};
4166
4167
4168/*!
4169 * jQuery UI Tabbable 1.14.1
4170 * https://jqueryui.com
4171 *
4172 * Copyright OpenJS Foundation and other contributors
4173 * Released under the MIT license.
4174 * https://jquery.org/license
4175 */
4176
4177//>>label: :tabbable Selector
4178//>>group: Core
4179//>>description: Selects elements which can be tabbed to.
4180//>>docs: https://api.jqueryui.com/tabbable-selector/
4181
4182
4183var tabbable = $.extend( $.expr.pseudos, {
4184    tabbable: function( element ) {
4185        var tabIndex = $.attr( element, "tabindex" ),
4186            hasTabindex = tabIndex != null;
4187        return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
4188    }
4189} );
4190
4191
4192/*!
4193 * jQuery UI Unique ID 1.14.1
4194 * https://jqueryui.com
4195 *
4196 * Copyright OpenJS Foundation and other contributors
4197 * Released under the MIT license.
4198 * https://jquery.org/license
4199 */
4200
4201//>>label: uniqueId
4202//>>group: Core
4203//>>description: Functions to generate and remove uniqueId's
4204//>>docs: https://api.jqueryui.com/uniqueId/
4205
4206
4207var uniqueId = $.fn.extend( {
4208    uniqueId: ( function() {
4209        var uuid = 0;
4210
4211        return function() {
4212            return this.each( function() {
4213                if ( !this.id ) {
4214                    this.id = "ui-id-" + ( ++uuid );
4215                }
4216            } );
4217        };
4218    } )(),
4219
4220    removeUniqueId: function() {
4221        return this.each( function() {
4222            if ( /^ui-id-\d+$/.test( this.id ) ) {
4223                $( this ).removeAttr( "id" );
4224            }
4225        } );
4226    }
4227} );
4228
4229
4230/*!
4231 * jQuery UI Accordion 1.14.1
4232 * https://jqueryui.com
4233 *
4234 * Copyright OpenJS Foundation and other contributors
4235 * Released under the MIT license.
4236 * https://jquery.org/license
4237 */
4238
4239//>>label: Accordion
4240//>>group: Widgets
4241/* eslint-disable max-len */
4242//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
4243/* eslint-enable max-len */
4244//>>docs: https://api.jqueryui.com/accordion/
4245//>>demos: https://jqueryui.com/accordion/
4246//>>css.structure: ../../themes/base/core.css
4247//>>css.structure: ../../themes/base/accordion.css
4248//>>css.theme: ../../themes/base/theme.css
4249
4250
4251var widgetsAccordion = $.widget( "ui.accordion", {
4252    version: "1.14.1",
4253    options: {
4254        active: 0,
4255        animate: {},
4256        classes: {
4257            "ui-accordion-header": "ui-corner-top",
4258            "ui-accordion-header-collapsed": "ui-corner-all",
4259            "ui-accordion-content": "ui-corner-bottom"
4260        },
4261        collapsible: false,
4262        event: "click",
4263        header: function( elem ) {
4264            return elem
4265                .find( "> li > :first-child" )
4266                .add(
4267                    elem.find( "> :not(li)" )
4268
4269                        // Support: jQuery <3.5 only
4270                        // We could use `.even()` but that's unavailable in older jQuery.
4271                        .filter( function( i ) {
4272                            return i % 2 === 0;
4273                        } )
4274                );
4275        },
4276        heightStyle: "auto",
4277        icons: {
4278            activeHeader: "ui-icon-triangle-1-s",
4279            header: "ui-icon-triangle-1-e"
4280        },
4281
4282        // Callbacks
4283        activate: null,
4284        beforeActivate: null
4285    },
4286
4287    hideProps: {
4288        borderTopWidth: "hide",
4289        borderBottomWidth: "hide",
4290        paddingTop: "hide",
4291        paddingBottom: "hide",
4292        height: "hide"
4293    },
4294
4295    showProps: {
4296        borderTopWidth: "show",
4297        borderBottomWidth: "show",
4298        paddingTop: "show",
4299        paddingBottom: "show",
4300        height: "show"
4301    },
4302
4303    _create: function() {
4304        var options = this.options;
4305
4306        this.prevShow = this.prevHide = $();
4307        this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
4308        this.element.attr( "role", "tablist" );
4309
4310        // Don't allow collapsible: false and active: false / null
4311        if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
4312            options.active = 0;
4313        }
4314
4315        this._processPanels();
4316
4317        // handle negative values
4318        if ( options.active < 0 ) {
4319            options.active += this.headers.length;
4320        }
4321        this._refresh();
4322    },
4323
4324    _getCreateEventData: function() {
4325        return {
4326            header: this.active,
4327            panel: !this.active.length ? $() : this.active.next()
4328        };
4329    },
4330
4331    _createIcons: function() {
4332        var icon, children,
4333            icons = this.options.icons;
4334
4335        if ( icons ) {
4336            icon = $( "<span>" );
4337            this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
4338            icon.prependTo( this.headers );
4339            children = this.active.children( ".ui-accordion-header-icon" );
4340            this._removeClass( children, icons.header )
4341                ._addClass( children, null, icons.activeHeader )
4342                ._addClass( this.headers, "ui-accordion-icons" );
4343        }
4344    },
4345
4346    _destroyIcons: function() {
4347        this._removeClass( this.headers, "ui-accordion-icons" );
4348        this.headers.children( ".ui-accordion-header-icon" ).remove();
4349    },
4350
4351    _destroy: function() {
4352        var contents;
4353
4354        // Clean up main element
4355        this.element.removeAttr( "role" );
4356
4357        // Clean up headers
4358        this.headers
4359            .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
4360            .removeUniqueId();
4361
4362        this._destroyIcons();
4363
4364        // Clean up content panels
4365        contents = this.headers.next()
4366            .css( "display", "" )
4367            .removeAttr( "role aria-hidden aria-labelledby" )
4368            .removeUniqueId();
4369
4370        if ( this.options.heightStyle !== "content" ) {
4371            contents.css( "height", "" );
4372        }
4373    },
4374
4375    _setOption: function( key, value ) {
4376        if ( key === "active" ) {
4377
4378            // _activate() will handle invalid values and update this.options
4379            this._activate( value );
4380            return;
4381        }
4382
4383        if ( key === "event" ) {
4384            if ( this.options.event ) {
4385                this._off( this.headers, this.options.event );
4386            }
4387            this._setupEvents( value );
4388        }
4389
4390        this._super( key, value );
4391
4392        // Setting collapsible: false while collapsed; open first panel
4393        if ( key === "collapsible" && !value && this.options.active === false ) {
4394            this._activate( 0 );
4395        }
4396
4397        if ( key === "icons" ) {
4398            this._destroyIcons();
4399            if ( value ) {
4400                this._createIcons();
4401            }
4402        }
4403    },
4404
4405    _setOptionDisabled: function( value ) {
4406        this._super( value );
4407
4408        this.element.attr( "aria-disabled", value );
4409        this._toggleClass( null, "ui-state-disabled", !!value );
4410    },
4411
4412    _keydown: function( event ) {
4413        if ( event.altKey || event.ctrlKey ) {
4414            return;
4415        }
4416
4417        var keyCode = $.ui.keyCode,
4418            length = this.headers.length,
4419            currentIndex = this.headers.index( event.target ),
4420            toFocus = false;
4421
4422        switch ( event.keyCode ) {
4423        case keyCode.RIGHT:
4424        case keyCode.DOWN:
4425            toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4426            break;
4427        case keyCode.LEFT:
4428        case keyCode.UP:
4429            toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4430            break;
4431        case keyCode.SPACE:
4432        case keyCode.ENTER:
4433            this._eventHandler( event );
4434            break;
4435        case keyCode.HOME:
4436            toFocus = this.headers[ 0 ];
4437            break;
4438        case keyCode.END:
4439            toFocus = this.headers[ length - 1 ];
4440            break;
4441        }
4442
4443        if ( toFocus ) {
4444            $( event.target ).attr( "tabIndex", -1 );
4445            $( toFocus ).attr( "tabIndex", 0 );
4446            $( toFocus ).trigger( "focus" );
4447            event.preventDefault();
4448        }
4449    },
4450
4451    _panelKeyDown: function( event ) {
4452        if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
4453            $( event.currentTarget ).prev().trigger( "focus" );
4454        }
4455    },
4456
4457    refresh: function() {
4458        var options = this.options;
4459        this._processPanels();
4460
4461        // Was collapsed or no panel
4462        if ( ( options.active === false && options.collapsible === true ) ||
4463                !this.headers.length ) {
4464            options.active = false;
4465            this.active = $();
4466
4467        // active false only when collapsible is true
4468        } else if ( options.active === false ) {
4469            this._activate( 0 );
4470
4471        // was active, but active panel is gone
4472        } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
4473
4474            // all remaining panel are disabled
4475            if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
4476                options.active = false;
4477                this.active = $();
4478
4479            // activate previous panel
4480            } else {
4481                this._activate( Math.max( 0, options.active - 1 ) );
4482            }
4483
4484        // was active, active panel still exists
4485        } else {
4486
4487            // make sure active index is correct
4488            options.active = this.headers.index( this.active );
4489        }
4490
4491        this._destroyIcons();
4492
4493        this._refresh();
4494    },
4495
4496    _processPanels: function() {
4497        var prevHeaders = this.headers,
4498            prevPanels = this.panels;
4499
4500        if ( typeof this.options.header === "function" ) {
4501            this.headers = this.options.header( this.element );
4502        } else {
4503            this.headers = this.element.find( this.options.header );
4504        }
4505        this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
4506            "ui-state-default" );
4507
4508        this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
4509        this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
4510
4511        // Avoid memory leaks (#10056)
4512        if ( prevPanels ) {
4513            this._off( prevHeaders.not( this.headers ) );
4514            this._off( prevPanels.not( this.panels ) );
4515        }
4516    },
4517
4518    _refresh: function() {
4519        var maxHeight,
4520            options = this.options,
4521            heightStyle = options.heightStyle,
4522            parent = this.element.parent();
4523
4524        this.active = this._findActive( options.active );
4525        this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
4526            ._removeClass( this.active, "ui-accordion-header-collapsed" );
4527        this._addClass( this.active.next(), "ui-accordion-content-active" );
4528        this.active.next().show();
4529
4530        this.headers
4531            .attr( "role", "tab" )
4532            .each( function() {
4533                var header = $( this ),
4534                    headerId = header.uniqueId().attr( "id" ),
4535                    panel = header.next(),
4536                    panelId = panel.uniqueId().attr( "id" );
4537                header.attr( "aria-controls", panelId );
4538                panel.attr( "aria-labelledby", headerId );
4539            } )
4540            .next()
4541                .attr( "role", "tabpanel" );
4542
4543        this.headers
4544            .not( this.active )
4545                .attr( {
4546                    "aria-selected": "false",
4547                    "aria-expanded": "false",
4548                    tabIndex: -1
4549                } )
4550                .next()
4551                    .attr( {
4552                        "aria-hidden": "true"
4553                    } )
4554                    .hide();
4555
4556        // Make sure at least one header is in the tab order
4557        if ( !this.active.length ) {
4558            this.headers.eq( 0 ).attr( "tabIndex", 0 );
4559        } else {
4560            this.active.attr( {
4561                "aria-selected": "true",
4562                "aria-expanded": "true",
4563                tabIndex: 0
4564            } )
4565                .next()
4566                    .attr( {
4567                        "aria-hidden": "false"
4568                    } );
4569        }
4570
4571        this._createIcons();
4572
4573        this._setupEvents( options.event );
4574
4575        if ( heightStyle === "fill" ) {
4576            maxHeight = parent.height();
4577            this.element.siblings( ":visible" ).each( function() {
4578                var elem = $( this ),
4579                    position = elem.css( "position" );
4580
4581                if ( position === "absolute" || position === "fixed" ) {
4582                    return;
4583                }
4584                maxHeight -= elem.outerHeight( true );
4585            } );
4586
4587            this.headers.each( function() {
4588                maxHeight -= $( this ).outerHeight( true );
4589            } );
4590
4591            this.headers.next()
4592                .each( function() {
4593                    $( this ).height( Math.max( 0, maxHeight -
4594                        $( this ).innerHeight() + $( this ).height() ) );
4595                } )
4596                .css( "overflow", "auto" );
4597        } else if ( heightStyle === "auto" ) {
4598            maxHeight = 0;
4599            this.headers.next()
4600                .each( function() {
4601                    var isVisible = $( this ).is( ":visible" );
4602                    if ( !isVisible ) {
4603                        $( this ).show();
4604                    }
4605                    maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
4606                    if ( !isVisible ) {
4607                        $( this ).hide();
4608                    }
4609                } )
4610                .height( maxHeight );
4611        }
4612    },
4613
4614    _activate: function( index ) {
4615        var active = this._findActive( index )[ 0 ];
4616
4617        // Trying to activate the already active panel
4618        if ( active === this.active[ 0 ] ) {
4619            return;
4620        }
4621
4622        // Trying to collapse, simulate a click on the currently active header
4623        active = active || this.active[ 0 ];
4624
4625        this._eventHandler( {
4626            target: active,
4627            currentTarget: active,
4628            preventDefault: $.noop
4629        } );
4630    },
4631
4632    _findActive: function( selector ) {
4633        return typeof selector === "number" ? this.headers.eq( selector ) : $();
4634    },
4635
4636    _setupEvents: function( event ) {
4637        var events = {
4638            keydown: "_keydown"
4639        };
4640        if ( event ) {
4641            $.each( event.split( " " ), function( index, eventName ) {
4642                events[ eventName ] = "_eventHandler";
4643            } );
4644        }
4645
4646        this._off( this.headers.add( this.headers.next() ) );
4647        this._on( this.headers, events );
4648        this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
4649        this._hoverable( this.headers );
4650        this._focusable( this.headers );
4651    },
4652
4653    _eventHandler: function( event ) {
4654        var activeChildren, clickedChildren,
4655            options = this.options,
4656            active = this.active,
4657            clicked = $( event.currentTarget ),
4658            clickedIsActive = clicked[ 0 ] === active[ 0 ],
4659            collapsing = clickedIsActive && options.collapsible,
4660            toShow = collapsing ? $() : clicked.next(),
4661            toHide = active.next(),
4662            eventData = {
4663                oldHeader: active,
4664                oldPanel: toHide,
4665                newHeader: collapsing ? $() : clicked,
4666                newPanel: toShow
4667            };
4668
4669        event.preventDefault();
4670
4671        if (
4672
4673                // click on active header, but not collapsible
4674                ( clickedIsActive && !options.collapsible ) ||
4675
4676                // allow canceling activation
4677                ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
4678            return;
4679        }
4680
4681        options.active = collapsing ? false : this.headers.index( clicked );
4682
4683        // When the call to ._toggle() comes after the class changes
4684        // it causes a very odd bug in IE 8 (see #6720)
4685        this.active = clickedIsActive ? $() : clicked;
4686        this._toggle( eventData );
4687
4688        // Switch classes
4689        // corner classes on the previously active header stay after the animation
4690        this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
4691        if ( options.icons ) {
4692            activeChildren = active.children( ".ui-accordion-header-icon" );
4693            this._removeClass( activeChildren, null, options.icons.activeHeader )
4694                ._addClass( activeChildren, null, options.icons.header );
4695        }
4696
4697        if ( !clickedIsActive ) {
4698            this._removeClass( clicked, "ui-accordion-header-collapsed" )
4699                ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
4700            if ( options.icons ) {
4701                clickedChildren = clicked.children( ".ui-accordion-header-icon" );
4702                this._removeClass( clickedChildren, null, options.icons.header )
4703                    ._addClass( clickedChildren, null, options.icons.activeHeader );
4704            }
4705
4706            this._addClass( clicked.next(), "ui-accordion-content-active" );
4707        }
4708    },
4709
4710    _toggle: function( data ) {
4711        var toShow = data.newPanel,
4712            toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
4713
4714        // Handle activating a panel during the animation for another activation
4715        this.prevShow.add( this.prevHide ).stop( true, true );
4716        this.prevShow = toShow;
4717        this.prevHide = toHide;
4718
4719        if ( this.options.animate ) {
4720            this._animate( toShow, toHide, data );
4721        } else {
4722            toHide.hide();
4723            toShow.show();
4724            this._toggleComplete( data );
4725        }
4726
4727        toHide.attr( {
4728            "aria-hidden": "true"
4729        } );
4730        toHide.prev().attr( {
4731            "aria-selected": "false",
4732            "aria-expanded": "false"
4733        } );
4734
4735        // if we're switching panels, remove the old header from the tab order
4736        // if we're opening from collapsed state, remove the previous header from the tab order
4737        // if we're collapsing, then keep the collapsing header in the tab order
4738        if ( toShow.length && toHide.length ) {
4739            toHide.prev().attr( {
4740                "tabIndex": -1,
4741                "aria-expanded": "false"
4742            } );
4743        } else if ( toShow.length ) {
4744            this.headers.filter( function() {
4745                return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
4746            } )
4747                .attr( "tabIndex", -1 );
4748        }
4749
4750        toShow
4751            .attr( "aria-hidden", "false" )
4752            .prev()
4753                .attr( {
4754                    "aria-selected": "true",
4755                    "aria-expanded": "true",
4756                    tabIndex: 0
4757                } );
4758    },
4759
4760    _animate: function( toShow, toHide, data ) {
4761        var total, easing, duration,
4762            that = this,
4763            adjust = 0,
4764            boxSizing = toShow.css( "box-sizing" ),
4765            down = toShow.length &&
4766                ( !toHide.length || ( toShow.index() < toHide.index() ) ),
4767            animate = this.options.animate || {},
4768            options = down && animate.down || animate,
4769            complete = function() {
4770                that._toggleComplete( data );
4771            };
4772
4773        if ( typeof options === "number" ) {
4774            duration = options;
4775        }
4776        if ( typeof options === "string" ) {
4777            easing = options;
4778        }
4779
4780        // fall back from options to animation in case of partial down settings
4781        easing = easing || options.easing || animate.easing;
4782        duration = duration || options.duration || animate.duration;
4783
4784        if ( !toHide.length ) {
4785            return toShow.animate( this.showProps, duration, easing, complete );
4786        }
4787        if ( !toShow.length ) {
4788            return toHide.animate( this.hideProps, duration, easing, complete );
4789        }
4790
4791        total = toShow.show().outerHeight();
4792        toHide.animate( this.hideProps, {
4793            duration: duration,
4794            easing: easing,
4795            step: function( now, fx ) {
4796                fx.now = Math.round( now );
4797            }
4798        } );
4799        toShow
4800            .hide()
4801            .animate( this.showProps, {
4802                duration: duration,
4803                easing: easing,
4804                complete: complete,
4805                step: function( now, fx ) {
4806                    fx.now = Math.round( now );
4807                    if ( fx.prop !== "height" ) {
4808                        if ( boxSizing === "content-box" ) {
4809                            adjust += fx.now;
4810                        }
4811                    } else if ( that.options.heightStyle !== "content" ) {
4812                        fx.now = Math.round( total - toHide.outerHeight() - adjust );
4813                        adjust = 0;
4814                    }
4815                }
4816            } );
4817    },
4818
4819    _toggleComplete: function( data ) {
4820        var toHide = data.oldPanel,
4821            prev = toHide.prev();
4822
4823        this._removeClass( toHide, "ui-accordion-content-active" );
4824        this._removeClass( prev, "ui-accordion-header-active" )
4825            ._addClass( prev, "ui-accordion-header-collapsed" );
4826
4827        this._trigger( "activate", null, data );
4828    }
4829} );
4830
4831
4832/*!
4833 * jQuery UI Menu 1.14.1
4834 * https://jqueryui.com
4835 *
4836 * Copyright OpenJS Foundation and other contributors
4837 * Released under the MIT license.
4838 * https://jquery.org/license
4839 */
4840
4841//>>label: Menu
4842//>>group: Widgets
4843//>>description: Creates nestable menus.
4844//>>docs: https://api.jqueryui.com/menu/
4845//>>demos: https://jqueryui.com/menu/
4846//>>css.structure: ../../themes/base/core.css
4847//>>css.structure: ../../themes/base/menu.css
4848//>>css.theme: ../../themes/base/theme.css
4849
4850
4851var widgetsMenu = $.widget( "ui.menu", {
4852    version: "1.14.1",
4853    defaultElement: "<ul>",
4854    delay: 300,
4855    options: {
4856        icons: {
4857            submenu: "ui-icon-caret-1-e"
4858        },
4859        items: "> *",
4860        menus: "ul",
4861        position: {
4862            my: "left top",
4863            at: "right top"
4864        },
4865        role: "menu",
4866
4867        // Callbacks
4868        blur: null,
4869        focus: null,
4870        select: null
4871    },
4872
4873    _create: function() {
4874        this.activeMenu = this.element;
4875
4876        // Flag used to prevent firing of the click handler
4877        // as the event bubbles up through nested menus
4878        this.mouseHandled = false;
4879        this.lastMousePosition = { x: null, y: null };
4880        this.element
4881            .uniqueId()
4882            .attr( {
4883                role: this.options.role,
4884                tabIndex: 0
4885            } );
4886
4887        this._addClass( "ui-menu", "ui-widget ui-widget-content" );
4888        this._on( {
4889
4890            // Prevent focus from sticking to links inside menu after clicking
4891            // them (focus should always stay on UL during navigation).
4892            "mousedown .ui-menu-item": function( event ) {
4893                event.preventDefault();
4894
4895                this._activateItem( event );
4896            },
4897            "click .ui-menu-item": function( event ) {
4898                var target = $( event.target );
4899                var active = $( this.document[ 0 ].activeElement );
4900                if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
4901                    this.select( event );
4902
4903                    // Only set the mouseHandled flag if the event will bubble, see #9469.
4904                    if ( !event.isPropagationStopped() ) {
4905                        this.mouseHandled = true;
4906                    }
4907
4908                    // Open submenu on click
4909                    if ( target.has( ".ui-menu" ).length ) {
4910                        this.expand( event );
4911                    } else if ( !this.element.is( ":focus" ) &&
4912                            active.closest( ".ui-menu" ).length ) {
4913
4914                        // Redirect focus to the menu
4915                        this.element.trigger( "focus", [ true ] );
4916
4917                        // If the active item is on the top level, let it stay active.
4918                        // Otherwise, blur the active item since it is no longer visible.
4919                        if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
4920                            clearTimeout( this.timer );
4921                        }
4922                    }
4923                }
4924            },
4925            "mouseenter .ui-menu-item": "_activateItem",
4926            "mousemove .ui-menu-item": "_activateItem",
4927            mouseleave: "collapseAll",
4928            "mouseleave .ui-menu": "collapseAll",
4929            focus: function( event, keepActiveItem ) {
4930
4931                // If there's already an active item, keep it active
4932                // If not, activate the first item
4933                var item = this.active || this._menuItems().first();
4934
4935                if ( !keepActiveItem ) {
4936                    this.focus( event, item );
4937                }
4938            },
4939            blur: function( event ) {
4940                this._delay( function() {
4941                    var notContained = !$.contains(
4942                        this.element[ 0 ],
4943                        this.document[ 0 ].activeElement
4944                    );
4945                    if ( notContained ) {
4946                        this.collapseAll( event );
4947                    }
4948                } );
4949            },
4950            keydown: "_keydown"
4951        } );
4952
4953        this.refresh();
4954
4955        // Clicks outside of a menu collapse any open menus
4956        this._on( this.document, {
4957            click: function( event ) {
4958                if ( this._closeOnDocumentClick( event ) ) {
4959                    this.collapseAll( event, true );
4960                }
4961
4962                // Reset the mouseHandled flag
4963                this.mouseHandled = false;
4964            }
4965        } );
4966    },
4967
4968    _activateItem: function( event ) {
4969
4970        // Ignore mouse events while typeahead is active, see #10458.
4971        // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
4972        // is over an item in the menu
4973        if ( this.previousFilter ) {
4974            return;
4975        }
4976
4977        // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
4978        if ( event.clientX === this.lastMousePosition.x &&
4979                event.clientY === this.lastMousePosition.y ) {
4980            return;
4981        }
4982
4983        this.lastMousePosition = {
4984            x: event.clientX,
4985            y: event.clientY
4986        };
4987
4988        var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
4989            target = $( event.currentTarget );
4990
4991        // Ignore bubbled events on parent items, see #11641
4992        if ( actualTarget[ 0 ] !== target[ 0 ] ) {
4993            return;
4994        }
4995
4996        // If the item is already active, there's nothing to do
4997        if ( target.is( ".ui-state-active" ) ) {
4998            return;
4999        }
5000
5001        // Remove ui-state-active class from siblings of the newly focused menu item
5002        // to avoid a jump caused by adjacent elements both having a class with a border
5003        this._removeClass( target.siblings().children( ".ui-state-active" ),
5004            null, "ui-state-active" );
5005        this.focus( event, target );
5006    },
5007
5008    _destroy: function() {
5009        var items = this.element.find( ".ui-menu-item" )
5010                .removeAttr( "role aria-disabled" ),
5011            submenus = items.children( ".ui-menu-item-wrapper" )
5012                .removeUniqueId()
5013                .removeAttr( "tabIndex role aria-haspopup" );
5014
5015        // Destroy (sub)menus
5016        this.element
5017            .removeAttr( "aria-activedescendant" )
5018            .find( ".ui-menu" ).addBack()
5019                .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
5020                    "tabIndex" )
5021                .removeUniqueId()
5022                .show();
5023
5024        submenus.children().each( function() {
5025            var elem = $( this );
5026            if ( elem.data( "ui-menu-submenu-caret" ) ) {
5027                elem.remove();
5028            }
5029        } );
5030    },
5031
5032    _keydown: function( event ) {
5033        var match, prev, character, skip,
5034            preventDefault = true;
5035
5036        switch ( event.keyCode ) {
5037        case $.ui.keyCode.PAGE_UP:
5038            this.previousPage( event );
5039            break;
5040        case $.ui.keyCode.PAGE_DOWN:
5041            this.nextPage( event );
5042            break;
5043        case $.ui.keyCode.HOME:
5044            this._move( "first", "first", event );
5045            break;
5046        case $.ui.keyCode.END:
5047            this._move( "last", "last", event );
5048            break;
5049        case $.ui.keyCode.UP:
5050            this.previous( event );
5051            break;
5052        case $.ui.keyCode.DOWN:
5053            this.next( event );
5054            break;
5055        case $.ui.keyCode.LEFT:
5056            this.collapse( event );
5057            break;
5058        case $.ui.keyCode.RIGHT:
5059            if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5060                this.expand( event );
5061            }
5062            break;
5063        case $.ui.keyCode.ENTER:
5064        case $.ui.keyCode.SPACE:
5065            this._activate( event );
5066            break;
5067        case $.ui.keyCode.ESCAPE:
5068            this.collapse( event );
5069            break;
5070        default:
5071            preventDefault = false;
5072            prev = this.previousFilter || "";
5073            skip = false;
5074
5075            // Support number pad values
5076            character = event.keyCode >= 96 && event.keyCode <= 105 ?
5077                ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
5078
5079            clearTimeout( this.filterTimer );
5080
5081            if ( character === prev ) {
5082                skip = true;
5083            } else {
5084                character = prev + character;
5085            }
5086
5087            match = this._filterMenuItems( character );
5088            match = skip && match.index( this.active.next() ) !== -1 ?
5089                this.active.nextAll( ".ui-menu-item" ) :
5090                match;
5091
5092            // If no matches on the current filter, reset to the last character pressed
5093            // to move down the menu to the first item that starts with that character
5094            if ( !match.length ) {
5095                character = String.fromCharCode( event.keyCode );
5096                match = this._filterMenuItems( character );
5097            }
5098
5099            if ( match.length ) {
5100                this.focus( event, match );
5101                this.previousFilter = character;
5102                this.filterTimer = this._delay( function() {
5103                    delete this.previousFilter;
5104                }, 1000 );
5105            } else {
5106                delete this.previousFilter;
5107            }
5108        }
5109
5110        if ( preventDefault ) {
5111            event.preventDefault();
5112        }
5113    },
5114
5115    _activate: function( event ) {
5116        if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5117            if ( this.active.children( "[aria-haspopup='true']" ).length ) {
5118                this.expand( event );
5119            } else {
5120                this.select( event );
5121            }
5122        }
5123    },
5124
5125    refresh: function() {
5126        var menus, items, newSubmenus, newItems, newWrappers,
5127            that = this,
5128            icon = this.options.icons.submenu,
5129            submenus = this.element.find( this.options.menus );
5130
5131        this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
5132
5133        // Initialize nested menus
5134        newSubmenus = submenus.filter( ":not(.ui-menu)" )
5135            .hide()
5136            .attr( {
5137                role: this.options.role,
5138                "aria-hidden": "true",
5139                "aria-expanded": "false"
5140            } )
5141            .each( function() {
5142                var menu = $( this ),
5143                    item = menu.prev(),
5144                    submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
5145
5146                that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
5147                item
5148                    .attr( "aria-haspopup", "true" )
5149                    .prepend( submenuCaret );
5150                menu.attr( "aria-labelledby", item.attr( "id" ) );
5151            } );
5152
5153        this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
5154
5155        menus = submenus.add( this.element );
5156        items = menus.find( this.options.items );
5157
5158        // Initialize menu-items containing spaces and/or dashes only as dividers
5159        items.not( ".ui-menu-item" ).each( function() {
5160            var item = $( this );
5161            if ( that._isDivider( item ) ) {
5162                that._addClass( item, "ui-menu-divider", "ui-widget-content" );
5163            }
5164        } );
5165
5166        // Don't refresh list items that are already adapted
5167        newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
5168        newWrappers = newItems.children()
5169            .not( ".ui-menu" )
5170                .uniqueId()
5171                .attr( {
5172                    tabIndex: -1,
5173                    role: this._itemRole()
5174                } );
5175        this._addClass( newItems, "ui-menu-item" )
5176            ._addClass( newWrappers, "ui-menu-item-wrapper" );
5177
5178        // Add aria-disabled attribute to any disabled menu item
5179        items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
5180
5181        // If the active item has been removed, blur the menu
5182        if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5183            this.blur();
5184        }
5185    },
5186
5187    _itemRole: function() {
5188        return {
5189            menu: "menuitem",
5190            listbox: "option"
5191        }[ this.options.role ];
5192    },
5193
5194    _setOption: function( key, value ) {
5195        if ( key === "icons" ) {
5196            var icons = this.element.find( ".ui-menu-icon" );
5197            this._removeClass( icons, null, this.options.icons.submenu )
5198                ._addClass( icons, null, value.submenu );
5199        }
5200        this._super( key, value );
5201    },
5202
5203    _setOptionDisabled: function( value ) {
5204        this._super( value );
5205
5206        this.element.attr( "aria-disabled", String( value ) );
5207        this._toggleClass( null, "ui-state-disabled", !!value );
5208    },
5209
5210    focus: function( event, item ) {
5211        var nested, focused, activeParent;
5212        this.blur( event, event && event.type === "focus" );
5213
5214        this._scrollIntoView( item );
5215
5216        this.active = item.first();
5217
5218        focused = this.active.children( ".ui-menu-item-wrapper" );
5219        this._addClass( focused, null, "ui-state-active" );
5220
5221        // Only update aria-activedescendant if there's a role
5222        // otherwise we assume focus is managed elsewhere
5223        if ( this.options.role ) {
5224            this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
5225        }
5226
5227        // Highlight active parent menu item, if any
5228        activeParent = this.active
5229            .parent()
5230                .closest( ".ui-menu-item" )
5231                    .children( ".ui-menu-item-wrapper" );
5232        this._addClass( activeParent, null, "ui-state-active" );
5233
5234        if ( event && event.type === "keydown" ) {
5235            this._close();
5236        } else {
5237            this.timer = this._delay( function() {
5238                this._close();
5239            }, this.delay );
5240        }
5241
5242        nested = item.children( ".ui-menu" );
5243        if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
5244            this._startOpening( nested );
5245        }
5246        this.activeMenu = item.parent();
5247
5248        this._trigger( "focus", event, { item: item } );
5249    },
5250
5251    _scrollIntoView: function( item ) {
5252        var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
5253        if ( this._hasScroll() ) {
5254            borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
5255            paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
5256            offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
5257            scroll = this.activeMenu.scrollTop();
5258            elementHeight = this.activeMenu.height();
5259            itemHeight = item.outerHeight();
5260
5261            if ( offset < 0 ) {
5262                this.activeMenu.scrollTop( scroll + offset );
5263            } else if ( offset + itemHeight > elementHeight ) {
5264                this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
5265            }
5266        }
5267    },
5268
5269    blur: function( event, fromFocus ) {
5270        if ( !fromFocus ) {
5271            clearTimeout( this.timer );
5272        }
5273
5274        if ( !this.active ) {
5275            return;
5276        }
5277
5278        this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
5279            null, "ui-state-active" );
5280
5281        this._trigger( "blur", event, { item: this.active } );
5282        this.active = null;
5283    },
5284
5285    _startOpening: function( submenu ) {
5286        clearTimeout( this.timer );
5287
5288        // Don't open if already open fixes a Firefox bug that caused a .5 pixel
5289        // shift in the submenu position when mousing over the caret icon
5290        if ( submenu.attr( "aria-hidden" ) !== "true" ) {
5291            return;
5292        }
5293
5294        this.timer = this._delay( function() {
5295            this._close();
5296            this._open( submenu );
5297        }, this.delay );
5298    },
5299
5300    _open: function( submenu ) {
5301        var position = $.extend( {
5302            of: this.active
5303        }, this.options.position );
5304
5305        clearTimeout( this.timer );
5306        this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
5307            .hide()
5308            .attr( "aria-hidden", "true" );
5309
5310        submenu
5311            .show()
5312            .removeAttr( "aria-hidden" )
5313            .attr( "aria-expanded", "true" )
5314            .position( position );
5315    },
5316
5317    collapseAll: function( event, all ) {
5318        clearTimeout( this.timer );
5319        this.timer = this._delay( function() {
5320
5321            // If we were passed an event, look for the submenu that contains the event
5322            var currentMenu = all ? this.element :
5323                $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
5324
5325            // If we found no valid submenu ancestor, use the main menu to close all
5326            // sub menus anyway
5327            if ( !currentMenu.length ) {
5328                currentMenu = this.element;
5329            }
5330
5331            this._close( currentMenu );
5332
5333            this.blur( event );
5334
5335            // Work around active item staying active after menu is blurred
5336            this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
5337
5338            this.activeMenu = currentMenu;
5339        }, all ? 0 : this.delay );
5340    },
5341
5342    // With no arguments, closes the currently active menu - if nothing is active
5343    // it closes all menus.  If passed an argument, it will search for menus BELOW
5344    _close: function( startMenu ) {
5345        if ( !startMenu ) {
5346            startMenu = this.active ? this.active.parent() : this.element;
5347        }
5348
5349        startMenu.find( ".ui-menu" )
5350            .hide()
5351            .attr( "aria-hidden", "true" )
5352            .attr( "aria-expanded", "false" );
5353    },
5354
5355    _closeOnDocumentClick: function( event ) {
5356        return !$( event.target ).closest( ".ui-menu" ).length;
5357    },
5358
5359    _isDivider: function( item ) {
5360
5361        // Match hyphen, em dash, en dash
5362        return !/[^\-\u2014\u2013\s]/.test( item.text() );
5363    },
5364
5365    collapse: function( event ) {
5366        var newItem = this.active &&
5367            this.active.parent().closest( ".ui-menu-item", this.element );
5368        if ( newItem && newItem.length ) {
5369            this._close();
5370            this.focus( event, newItem );
5371        }
5372    },
5373
5374    expand: function( event ) {
5375        var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
5376
5377        if ( newItem && newItem.length ) {
5378            this._open( newItem.parent() );
5379
5380            // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
5381            this._delay( function() {
5382                this.focus( event, newItem );
5383            } );
5384        }
5385    },
5386
5387    next: function( event ) {
5388        this._move( "next", "first", event );
5389    },
5390
5391    previous: function( event ) {
5392        this._move( "prev", "last", event );
5393    },
5394
5395    isFirstItem: function() {
5396        return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
5397    },
5398
5399    isLastItem: function() {
5400        return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
5401    },
5402
5403    _menuItems: function( menu ) {
5404        return ( menu || this.element )
5405            .find( this.options.items )
5406            .filter( ".ui-menu-item" );
5407    },
5408
5409    _move: function( direction, filter, event ) {
5410        var next;
5411        if ( this.active ) {
5412            if ( direction === "first" || direction === "last" ) {
5413                next = this.active
5414                    [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
5415                    .last();
5416            } else {
5417                next = this.active
5418                    [ direction + "All" ]( ".ui-menu-item" )
5419                    .first();
5420            }
5421        }
5422        if ( !next || !next.length || !this.active ) {
5423            next = this._menuItems( this.activeMenu )[ filter ]();
5424        }
5425
5426        this.focus( event, next );
5427    },
5428
5429    nextPage: function( event ) {
5430        var item, base, height;
5431
5432        if ( !this.active ) {
5433            this.next( event );
5434            return;
5435        }
5436        if ( this.isLastItem() ) {
5437            return;
5438        }
5439        if ( this._hasScroll() ) {
5440            base = this.active.offset().top;
5441            height = this.element.innerHeight();
5442
5443            // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5444            if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5445                height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5446            }
5447
5448            this.active.nextAll( ".ui-menu-item" ).each( function() {
5449                item = $( this );
5450                return item.offset().top - base - height < 0;
5451            } );
5452
5453            this.focus( event, item );
5454        } else {
5455            this.focus( event, this._menuItems( this.activeMenu )
5456                [ !this.active ? "first" : "last" ]() );
5457        }
5458    },
5459
5460    previousPage: function( event ) {
5461        var item, base, height;
5462        if ( !this.active ) {
5463            this.next( event );
5464            return;
5465        }
5466        if ( this.isFirstItem() ) {
5467            return;
5468        }
5469        if ( this._hasScroll() ) {
5470            base = this.active.offset().top;
5471            height = this.element.innerHeight();
5472
5473            // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5474            if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5475                height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5476            }
5477
5478            this.active.prevAll( ".ui-menu-item" ).each( function() {
5479                item = $( this );
5480                return item.offset().top - base + height > 0;
5481            } );
5482
5483            this.focus( event, item );
5484        } else {
5485            this.focus( event, this._menuItems( this.activeMenu ).first() );
5486        }
5487    },
5488
5489    _hasScroll: function() {
5490        return this.element.outerHeight() < this.element.prop( "scrollHeight" );
5491    },
5492
5493    select: function( event ) {
5494
5495        // TODO: It should never be possible to not have an active item at this
5496        // point, but the tests don't trigger mouseenter before click.
5497        this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
5498        var ui = { item: this.active };
5499        if ( !this.active.has( ".ui-menu" ).length ) {
5500            this.collapseAll( event, true );
5501        }
5502        this._trigger( "select", event, ui );
5503    },
5504
5505    _filterMenuItems: function( character ) {
5506        var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
5507            regex = new RegExp( "^" + escapedCharacter, "i" );
5508
5509        return this.activeMenu
5510            .find( this.options.items )
5511
5512                // Only match on items, not dividers or other content (#10571)
5513                .filter( ".ui-menu-item" )
5514                    .filter( function() {
5515                        return regex.test(
5516                            String.prototype.trim.call(
5517                                $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
5518                    } );
5519    }
5520} );
5521
5522
5523/*!
5524 * jQuery UI Autocomplete 1.14.1
5525 * https://jqueryui.com
5526 *
5527 * Copyright OpenJS Foundation and other contributors
5528 * Released under the MIT license.
5529 * https://jquery.org/license
5530 */
5531
5532//>>label: Autocomplete
5533//>>group: Widgets
5534//>>description: Lists suggested words as the user is typing.
5535//>>docs: https://api.jqueryui.com/autocomplete/
5536//>>demos: https://jqueryui.com/autocomplete/
5537//>>css.structure: ../../themes/base/core.css
5538//>>css.structure: ../../themes/base/autocomplete.css
5539//>>css.theme: ../../themes/base/theme.css
5540
5541
5542$.widget( "ui.autocomplete", {
5543    version: "1.14.1",
5544    defaultElement: "<input>",
5545    options: {
5546        appendTo: null,
5547        autoFocus: false,
5548        delay: 300,
5549        minLength: 1,
5550        position: {
5551            my: "left top",
5552            at: "left bottom",
5553            collision: "none"
5554        },
5555        source: null,
5556
5557        // Callbacks
5558        change: null,
5559        close: null,
5560        focus: null,
5561        open: null,
5562        response: null,
5563        search: null,
5564        select: null
5565    },
5566
5567    requestIndex: 0,
5568    pending: 0,
5569    liveRegionTimer: null,
5570
5571    _create: function() {
5572
5573        // Some browsers only repeat keydown events, not keypress events,
5574        // so we use the suppressKeyPress flag to determine if we've already
5575        // handled the keydown event. #7269
5576        // Unfortunately the code for & in keypress is the same as the up arrow,
5577        // so we use the suppressKeyPressRepeat flag to avoid handling keypress
5578        // events when we know the keydown event was used to modify the
5579        // search term. #7799
5580        var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5581            nodeName = this.element[ 0 ].nodeName.toLowerCase(),
5582            isTextarea = nodeName === "textarea",
5583            isInput = nodeName === "input";
5584
5585        // Textareas are always multi-line
5586        // Inputs are always single-line, even if inside a contentEditable element
5587        // All other element types are determined by whether they're contentEditable
5588        this.isMultiLine = isTextarea ||
5589            !isInput && this.element.prop( "contentEditable" ) === "true";
5590
5591        this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5592        this.isNewMenu = true;
5593
5594        this._addClass( "ui-autocomplete-input" );
5595        this.element.attr( "autocomplete", "off" );
5596
5597        this._on( this.element, {
5598            keydown: function( event ) {
5599                if ( this.element.prop( "readOnly" ) ) {
5600                    suppressKeyPress = true;
5601                    suppressInput = true;
5602                    suppressKeyPressRepeat = true;
5603                    return;
5604                }
5605
5606                suppressKeyPress = false;
5607                suppressInput = false;
5608                suppressKeyPressRepeat = false;
5609                var keyCode = $.ui.keyCode;
5610                switch ( event.keyCode ) {
5611                case keyCode.PAGE_UP:
5612                    suppressKeyPress = true;
5613                    this._move( "previousPage", event );
5614                    break;
5615                case keyCode.PAGE_DOWN:
5616                    suppressKeyPress = true;
5617                    this._move( "nextPage", event );
5618                    break;
5619                case keyCode.UP:
5620                    suppressKeyPress = true;
5621                    this._keyEvent( "previous", event );
5622                    break;
5623                case keyCode.DOWN:
5624                    suppressKeyPress = true;
5625                    this._keyEvent( "next", event );
5626                    break;
5627                case keyCode.ENTER:
5628
5629                    // when menu is open and has focus
5630                    if ( this.menu.active ) {
5631
5632                        // #6055 - Opera still allows the keypress to occur
5633                        // which causes forms to submit
5634                        suppressKeyPress = true;
5635                        event.preventDefault();
5636                        this.menu.select( event );
5637                    }
5638                    break;
5639                case keyCode.TAB:
5640                    if ( this.menu.active ) {
5641                        this.menu.select( event );
5642                    }
5643                    break;
5644                case keyCode.ESCAPE:
5645                    if ( this.menu.element.is( ":visible" ) ) {
5646                        if ( !this.isMultiLine ) {
5647                            this._value( this.term );
5648                        }
5649                        this.close( event );
5650
5651                        // Different browsers have different default behavior for escape
5652                        // Single press can mean undo or clear
5653                        event.preventDefault();
5654                    }
5655                    break;
5656                default:
5657                    suppressKeyPressRepeat = true;
5658
5659                    // search timeout should be triggered before the input value is changed
5660                    this._searchTimeout( event );
5661                    break;
5662                }
5663            },
5664            keypress: function( event ) {
5665                if ( suppressKeyPress ) {
5666                    suppressKeyPress = false;
5667                    if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5668                        event.preventDefault();
5669                    }
5670                    return;
5671                }
5672                if ( suppressKeyPressRepeat ) {
5673                    return;
5674                }
5675
5676                // Replicate some key handlers to allow them to repeat in Firefox and Opera
5677                var keyCode = $.ui.keyCode;
5678                switch ( event.keyCode ) {
5679                case keyCode.PAGE_UP:
5680                    this._move( "previousPage", event );
5681                    break;
5682                case keyCode.PAGE_DOWN:
5683                    this._move( "nextPage", event );
5684                    break;
5685                case keyCode.UP:
5686                    this._keyEvent( "previous", event );
5687                    break;
5688                case keyCode.DOWN:
5689                    this._keyEvent( "next", event );
5690                    break;
5691                }
5692            },
5693            input: function( event ) {
5694                if ( suppressInput ) {
5695                    suppressInput = false;
5696                    event.preventDefault();
5697                    return;
5698                }
5699                this._searchTimeout( event );
5700            },
5701            focus: function() {
5702                this.selectedItem = null;
5703                this.previous = this._value();
5704            },
5705            blur: function( event ) {
5706                clearTimeout( this.searching );
5707                this.close( event );
5708                this._change( event );
5709            }
5710        } );
5711
5712        this._initSource();
5713        this.menu = $( "<ul>" )
5714            .appendTo( this._appendTo() )
5715            .menu( {
5716
5717                // disable ARIA support, the live region takes care of that
5718                role: null
5719            } )
5720            .hide()
5721            .menu( "instance" );
5722
5723        this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
5724        this._on( this.menu.element, {
5725            mousedown: function( event ) {
5726
5727                // Prevent moving focus out of the text field
5728                event.preventDefault();
5729            },
5730            menufocus: function( event, ui ) {
5731                var label, item;
5732
5733                // Support: Firefox
5734                // Prevent accidental activation of menu items in Firefox (#7024 #9118)
5735                if ( this.isNewMenu ) {
5736                    this.isNewMenu = false;
5737                    if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
5738                        this.menu.blur();
5739
5740                        this.document.one( "mousemove", function() {
5741                            $( event.target ).trigger( event.originalEvent );
5742                        } );
5743
5744                        return;
5745                    }
5746                }
5747
5748                item = ui.item.data( "ui-autocomplete-item" );
5749                if ( false !== this._trigger( "focus", event, { item: item } ) ) {
5750
5751                    // use value to match what will end up in the input, if it was a key event
5752                    if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
5753                        this._value( item.value );
5754                    }
5755                }
5756
5757                // Announce the value in the liveRegion
5758                label = ui.item.attr( "aria-label" ) || item.value;
5759                if ( label && String.prototype.trim.call( label ).length ) {
5760                    clearTimeout( this.liveRegionTimer );
5761                    this.liveRegionTimer = this._delay( function() {
5762                        this.liveRegion.html( $( "<div>" ).text( label ) );
5763                    }, 100 );
5764                }
5765            },
5766            menuselect: function( event, ui ) {
5767                var item = ui.item.data( "ui-autocomplete-item" ),
5768                    previous = this.previous;
5769
5770                // Only trigger when focus was lost (click on menu)
5771                if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
5772                    this.element.trigger( "focus" );
5773                    this.previous = previous;
5774                }
5775
5776                if ( false !== this._trigger( "select", event, { item: item } ) ) {
5777                    this._value( item.value );
5778                }
5779
5780                // reset the term after the select event
5781                // this allows custom select handling to work properly
5782                this.term = this._value();
5783
5784                this.close( event );
5785                this.selectedItem = item;
5786            }
5787        } );
5788
5789        this.liveRegion = $( "<div>", {
5790            role: "status",
5791            "aria-live": "assertive",
5792            "aria-relevant": "additions"
5793        } )
5794            .appendTo( this.document[ 0 ].body );
5795
5796        this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
5797
5798        // Turning off autocomplete prevents the browser from remembering the
5799        // value when navigating through history, so we re-enable autocomplete
5800        // if the page is unloaded before the widget is destroyed. #7790
5801        this._on( this.window, {
5802            beforeunload: function() {
5803                this.element.removeAttr( "autocomplete" );
5804            }
5805        } );
5806    },
5807
5808    _destroy: function() {
5809        clearTimeout( this.searching );
5810        this.element.removeAttr( "autocomplete" );
5811        this.menu.element.remove();
5812        this.liveRegion.remove();
5813    },
5814
5815    _setOption: function( key, value ) {
5816        this._super( key, value );
5817        if ( key === "source" ) {
5818            this._initSource();
5819        }
5820        if ( key === "appendTo" ) {
5821            this.menu.element.appendTo( this._appendTo() );
5822        }
5823        if ( key === "disabled" && value && this.xhr ) {
5824            this.xhr.abort();
5825        }
5826    },
5827
5828    _isEventTargetInWidget: function( event ) {
5829        var menuElement = this.menu.element[ 0 ];
5830
5831        return event.target === this.element[ 0 ] ||
5832            event.target === menuElement ||
5833            $.contains( menuElement, event.target );
5834    },
5835
5836    _closeOnClickOutside: function( event ) {
5837        if ( !this._isEventTargetInWidget( event ) ) {
5838            this.close();
5839        }
5840    },
5841
5842    _appendTo: function() {
5843        var element = this.options.appendTo;
5844
5845        if ( element ) {
5846            element = element.jquery || element.nodeType ?
5847                $( element ) :
5848                this.document.find( element ).eq( 0 );
5849        }
5850
5851        if ( !element || !element[ 0 ] ) {
5852            element = this.element.closest( ".ui-front, dialog" );
5853        }
5854
5855        if ( !element.length ) {
5856            element = this.document[ 0 ].body;
5857        }
5858
5859        return element;
5860    },
5861
5862    _initSource: function() {
5863        var array, url,
5864            that = this;
5865        if ( Array.isArray( this.options.source ) ) {
5866            array = this.options.source;
5867            this.source = function( request, response ) {
5868                response( $.ui.autocomplete.filter( array, request.term ) );
5869            };
5870        } else if ( typeof this.options.source === "string" ) {
5871            url = this.options.source;
5872            this.source = function( request, response ) {
5873                if ( that.xhr ) {
5874                    that.xhr.abort();
5875                }
5876                that.xhr = $.ajax( {
5877                    url: url,
5878                    data: request,
5879                    dataType: "json",
5880                    success: function( data ) {
5881                        response( data );
5882                    },
5883                    error: function() {
5884                        response( [] );
5885                    }
5886                } );
5887            };
5888        } else {
5889            this.source = this.options.source;
5890        }
5891    },
5892
5893    _searchTimeout: function( event ) {
5894        clearTimeout( this.searching );
5895        this.searching = this._delay( function() {
5896
5897            // Search if the value has changed, or if the user retypes the same value (see #7434)
5898            var equalValues = this.term === this._value(),
5899                menuVisible = this.menu.element.is( ":visible" ),
5900                modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
5901
5902            if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
5903                this.selectedItem = null;
5904                this.search( null, event );
5905            }
5906        }, this.options.delay );
5907    },
5908
5909    search: function( value, event ) {
5910        value = value != null ? value : this._value();
5911
5912        // Always save the actual value, not the one passed as an argument
5913        this.term = this._value();
5914
5915        if ( value.length < this.options.minLength ) {
5916            return this.close( event );
5917        }
5918
5919        if ( this._trigger( "search", event ) === false ) {
5920            return;
5921        }
5922
5923        return this._search( value );
5924    },
5925
5926    _search: function( value ) {
5927        this.pending++;
5928        this._addClass( "ui-autocomplete-loading" );
5929        this.cancelSearch = false;
5930
5931        this.source( { term: value }, this._response() );
5932    },
5933
5934    _response: function() {
5935        var index = ++this.requestIndex;
5936
5937        return function( content ) {
5938            if ( index === this.requestIndex ) {
5939                this.__response( content );
5940            }
5941
5942            this.pending--;
5943            if ( !this.pending ) {
5944                this._removeClass( "ui-autocomplete-loading" );
5945            }
5946        }.bind( this );
5947    },
5948
5949    __response: function( content ) {
5950        if ( content ) {
5951            content = this._normalize( content );
5952        }
5953        this._trigger( "response", null, { content: content } );
5954        if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
5955            this._suggest( content );
5956            this._trigger( "open" );
5957        } else {
5958
5959            // use ._close() instead of .close() so we don't cancel future searches
5960            this._close();
5961        }
5962    },
5963
5964    close: function( event ) {
5965        this.cancelSearch = true;
5966        this._close( event );
5967    },
5968
5969    _close: function( event ) {
5970
5971        // Remove the handler that closes the menu on outside clicks
5972        this._off( this.document, "mousedown" );
5973
5974        if ( this.menu.element.is( ":visible" ) ) {
5975            this.menu.element.hide();
5976            this.menu.blur();
5977            this.isNewMenu = true;
5978            this._trigger( "close", event );
5979        }
5980    },
5981
5982    _change: function( event ) {
5983        if ( this.previous !== this._value() ) {
5984            this._trigger( "change", event, { item: this.selectedItem } );
5985        }
5986    },
5987
5988    _normalize: function( items ) {
5989
5990        // assume all items have the right format when the first item is complete
5991        if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
5992            return items;
5993        }
5994        return $.map( items, function( item ) {
5995            if ( typeof item === "string" ) {
5996                return {
5997                    label: item,
5998                    value: item
5999                };
6000            }
6001            return $.extend( {}, item, {
6002                label: item.label || item.value,
6003                value: item.value || item.label
6004            } );
6005        } );
6006    },
6007
6008    _suggest: function( items ) {
6009        var ul = this.menu.element.empty();
6010        this._renderMenu( ul, items );
6011        this.isNewMenu = true;
6012        this.menu.refresh();
6013
6014        // Size and position menu
6015        ul.show();
6016        this._resizeMenu();
6017        ul.position( $.extend( {
6018            of: this.element
6019        }, this.options.position ) );
6020
6021        if ( this.options.autoFocus ) {
6022            this.menu.next();
6023        }
6024
6025        // Listen for interactions outside of the widget (#6642)
6026        this._on( this.document, {
6027            mousedown: "_closeOnClickOutside"
6028        } );
6029    },
6030
6031    _resizeMenu: function() {
6032        var ul = this.menu.element;
6033        ul.outerWidth( Math.max(
6034
6035            // Firefox wraps long text (possibly a rounding bug)
6036            // so we add 1px to avoid the wrapping (#7513)
6037            ul.width( "" ).outerWidth() + 1,
6038            this.element.outerWidth()
6039        ) );
6040    },
6041
6042    _renderMenu: function( ul, items ) {
6043        var that = this;
6044        $.each( items, function( index, item ) {
6045            that._renderItemData( ul, item );
6046        } );
6047    },
6048
6049    _renderItemData: function( ul, item ) {
6050        return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6051    },
6052
6053    _renderItem: function( ul, item ) {
6054        return $( "<li>" )
6055            .append( $( "<div>" ).text( item.label ) )
6056            .appendTo( ul );
6057    },
6058
6059    _move: function( direction, event ) {
6060        if ( !this.menu.element.is( ":visible" ) ) {
6061            this.search( null, event );
6062            return;
6063        }
6064        if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6065                this.menu.isLastItem() && /^next/.test( direction ) ) {
6066
6067            if ( !this.isMultiLine ) {
6068                this._value( this.term );
6069            }
6070
6071            this.menu.blur();
6072            return;
6073        }
6074        this.menu[ direction ]( event );
6075    },
6076
6077    widget: function() {
6078        return this.menu.element;
6079    },
6080
6081    _value: function() {
6082        return this.valueMethod.apply( this.element, arguments );
6083    },
6084
6085    _keyEvent: function( keyEvent, event ) {
6086        if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6087            this._move( keyEvent, event );
6088
6089            // Prevents moving cursor to beginning/end of the text field in some browsers
6090            event.preventDefault();
6091        }
6092    }
6093} );
6094
6095$.extend( $.ui.autocomplete, {
6096    escapeRegex: function( value ) {
6097        return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
6098    },
6099    filter: function( array, term ) {
6100        var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
6101        return $.grep( array, function( value ) {
6102            return matcher.test( value.label || value.value || value );
6103        } );
6104    }
6105} );
6106
6107// Live region extension, adding a `messages` option
6108// NOTE: This is an experimental API. We are still investigating
6109// a full solution for string manipulation and internationalization.
6110$.widget( "ui.autocomplete", $.ui.autocomplete, {
6111    options: {
6112        messages: {
6113            noResults: "No search results.",
6114            results: function( amount ) {
6115                return amount + ( amount > 1 ? " results are" : " result is" ) +
6116                    " available, use up and down arrow keys to navigate.";
6117            }
6118        }
6119    },
6120
6121    __response: function( content ) {
6122        var message;
6123        this._superApply( arguments );
6124        if ( this.options.disabled || this.cancelSearch ) {
6125            return;
6126        }
6127        if ( content && content.length ) {
6128            message = this.options.messages.results( content.length );
6129        } else {
6130            message = this.options.messages.noResults;
6131        }
6132        clearTimeout( this.liveRegionTimer );
6133        this.liveRegionTimer = this._delay( function() {
6134            this.liveRegion.html( $( "<div>" ).text( message ) );
6135        }, 100 );
6136    }
6137} );
6138
6139var widgetsAutocomplete = $.ui.autocomplete;
6140
6141
6142/*!
6143 * jQuery UI Controlgroup 1.14.1
6144 * https://jqueryui.com
6145 *
6146 * Copyright OpenJS Foundation and other contributors
6147 * Released under the MIT license.
6148 * https://jquery.org/license
6149 */
6150
6151//>>label: Controlgroup
6152//>>group: Widgets
6153//>>description: Visually groups form control widgets
6154//>>docs: https://api.jqueryui.com/controlgroup/
6155//>>demos: https://jqueryui.com/controlgroup/
6156//>>css.structure: ../../themes/base/core.css
6157//>>css.structure: ../../themes/base/controlgroup.css
6158//>>css.theme: ../../themes/base/theme.css
6159
6160
6161var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
6162
6163var widgetsControlgroup = $.widget( "ui.controlgroup", {
6164    version: "1.14.1",
6165    defaultElement: "<div>",
6166    options: {
6167        direction: "horizontal",
6168        disabled: null,
6169        onlyVisible: true,
6170        items: {
6171            "button": "input[type=button], input[type=submit], input[type=reset], button, a",
6172            "controlgroupLabel": ".ui-controlgroup-label",
6173            "checkboxradio": "input[type='checkbox'], input[type='radio']",
6174            "selectmenu": "select",
6175            "spinner": ".ui-spinner-input"
6176        }
6177    },
6178
6179    _create: function() {
6180        this._enhance();
6181    },
6182
6183    // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
6184    _enhance: function() {
6185        this.element.attr( "role", "toolbar" );
6186        this.refresh();
6187    },
6188
6189    _destroy: function() {
6190        this._callChildMethod( "destroy" );
6191        this.childWidgets.removeData( "ui-controlgroup-data" );
6192        this.element.removeAttr( "role" );
6193        if ( this.options.items.controlgroupLabel ) {
6194            this.element
6195                .find( this.options.items.controlgroupLabel )
6196                .find( ".ui-controlgroup-label-contents" )
6197                .contents().unwrap();
6198        }
6199    },
6200
6201    _initWidgets: function() {
6202        var that = this,
6203            childWidgets = [];
6204
6205        // First we iterate over each of the items options
6206        $.each( this.options.items, function( widget, selector ) {
6207            var labels;
6208            var options = {};
6209
6210            // Make sure the widget has a selector set
6211            if ( !selector ) {
6212                return;
6213            }
6214
6215            if ( widget === "controlgroupLabel" ) {
6216                labels = that.element.find( selector );
6217                labels.each( function() {
6218                    var element = $( this );
6219
6220                    if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
6221                        return;
6222                    }
6223                    element.contents()
6224                        .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
6225                } );
6226                that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
6227                childWidgets = childWidgets.concat( labels.get() );
6228                return;
6229            }
6230
6231            // Make sure the widget actually exists
6232            if ( !$.fn[ widget ] ) {
6233                return;
6234            }
6235
6236            // We assume everything is in the middle to start because we can't determine
6237            // first / last elements until all enhancments are done.
6238            if ( that[ "_" + widget + "Options" ] ) {
6239                options = that[ "_" + widget + "Options" ]( "middle" );
6240            } else {
6241                options = { classes: {} };
6242            }
6243
6244            // Find instances of this widget inside controlgroup and init them
6245            that.element
6246                .find( selector )
6247                .each( function() {
6248                    var element = $( this );
6249                    var instance = element[ widget ]( "instance" );
6250
6251                    // We need to clone the default options for this type of widget to avoid
6252                    // polluting the variable options which has a wider scope than a single widget.
6253                    var instanceOptions = $.widget.extend( {}, options );
6254
6255                    // If the button is the child of a spinner ignore it
6256                    // TODO: Find a more generic solution
6257                    if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
6258                        return;
6259                    }
6260
6261                    // Create the widget if it doesn't exist
6262                    if ( !instance ) {
6263                        instance = element[ widget ]()[ widget ]( "instance" );
6264                    }
6265                    if ( instance ) {
6266                        instanceOptions.classes =
6267                            that._resolveClassesValues( instanceOptions.classes, instance );
6268                    }
6269                    element[ widget ]( instanceOptions );
6270
6271                    // Store an instance of the controlgroup to be able to reference
6272                    // from the outermost element for changing options and refresh
6273                    var widgetElement = element[ widget ]( "widget" );
6274                    $.data( widgetElement[ 0 ], "ui-controlgroup-data",
6275                        instance ? instance : element[ widget ]( "instance" ) );
6276
6277                    childWidgets.push( widgetElement[ 0 ] );
6278                } );
6279        } );
6280
6281        this.childWidgets = $( $.uniqueSort( childWidgets ) );
6282        this._addClass( this.childWidgets, "ui-controlgroup-item" );
6283    },
6284
6285    _callChildMethod: function( method ) {
6286        this.childWidgets.each( function() {
6287            var element = $( this ),
6288                data = element.data( "ui-controlgroup-data" );
6289            if ( data && data[ method ] ) {
6290                data[ method ]();
6291            }
6292        } );
6293    },
6294
6295    _updateCornerClass: function( element, position ) {
6296        var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
6297        var add = this._buildSimpleOptions( position, "label" ).classes.label;
6298
6299        this._removeClass( element, null, remove );
6300        this._addClass( element, null, add );
6301    },
6302
6303    _buildSimpleOptions: function( position, key ) {
6304        var direction = this.options.direction === "vertical";
6305        var result = {
6306            classes: {}
6307        };
6308        result.classes[ key ] = {
6309            "middle": "",
6310            "first": "ui-corner-" + ( direction ? "top" : "left" ),
6311            "last": "ui-corner-" + ( direction ? "bottom" : "right" ),
6312            "only": "ui-corner-all"
6313        }[ position ];
6314
6315        return result;
6316    },
6317
6318    _spinnerOptions: function( position ) {
6319        var options = this._buildSimpleOptions( position, "ui-spinner" );
6320
6321        options.classes[ "ui-spinner-up" ] = "";
6322        options.classes[ "ui-spinner-down" ] = "";
6323
6324        return options;
6325    },
6326
6327    _buttonOptions: function( position ) {
6328        return this._buildSimpleOptions( position, "ui-button" );
6329    },
6330
6331    _checkboxradioOptions: function( position ) {
6332        return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
6333    },
6334
6335    _selectmenuOptions: function( position ) {
6336        var direction = this.options.direction === "vertical";
6337        return {
6338            width: direction ? "auto" : false,
6339            classes: {
6340                middle: {
6341                    "ui-selectmenu-button-open": "",
6342                    "ui-selectmenu-button-closed": ""
6343                },
6344                first: {
6345                    "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
6346                    "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
6347                },
6348                last: {
6349                    "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
6350                    "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
6351                },
6352                only: {
6353                    "ui-selectmenu-button-open": "ui-corner-top",
6354                    "ui-selectmenu-button-closed": "ui-corner-all"
6355                }
6356
6357            }[ position ]
6358        };
6359    },
6360
6361    _resolveClassesValues: function( classes, instance ) {
6362        var result = {};
6363        $.each( classes, function( key ) {
6364            var current = instance.options.classes[ key ] || "";
6365            current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) );
6366            result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
6367        } );
6368        return result;
6369    },
6370
6371    _setOption: function( key, value ) {
6372        if ( key === "direction" ) {
6373            this._removeClass( "ui-controlgroup-" + this.options.direction );
6374        }
6375
6376        this._super( key, value );
6377        if ( key === "disabled" ) {
6378            this._callChildMethod( value ? "disable" : "enable" );
6379            return;
6380        }
6381
6382        this.refresh();
6383    },
6384
6385    refresh: function() {
6386        var children,
6387            that = this;
6388
6389        this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
6390
6391        if ( this.options.direction === "horizontal" ) {
6392            this._addClass( null, "ui-helper-clearfix" );
6393        }
6394        this._initWidgets();
6395
6396        children = this.childWidgets;
6397
6398        // We filter here because we need to track all childWidgets not just the visible ones
6399        if ( this.options.onlyVisible ) {
6400            children = children.filter( ":visible" );
6401        }
6402
6403        if ( children.length ) {
6404
6405            // We do this last because we need to make sure all enhancment is done
6406            // before determining first and last
6407            $.each( [ "first", "last" ], function( index, value ) {
6408                var instance = children[ value ]().data( "ui-controlgroup-data" );
6409
6410                if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
6411                    var options = that[ "_" + instance.widgetName + "Options" ](
6412                        children.length === 1 ? "only" : value
6413                    );
6414                    options.classes = that._resolveClassesValues( options.classes, instance );
6415                    instance.element[ instance.widgetName ]( options );
6416                } else {
6417                    that._updateCornerClass( children[ value ](), value );
6418                }
6419            } );
6420
6421            // Finally call the refresh method on each of the child widgets.
6422            this._callChildMethod( "refresh" );
6423        }
6424    }
6425} );
6426
6427/*!
6428 * jQuery UI Checkboxradio 1.14.1
6429 * https://jqueryui.com
6430 *
6431 * Copyright OpenJS Foundation and other contributors
6432 * Released under the MIT license.
6433 * https://jquery.org/license
6434 */
6435
6436//>>label: Checkboxradio
6437//>>group: Widgets
6438//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
6439//>>docs: https://api.jqueryui.com/checkboxradio/
6440//>>demos: https://jqueryui.com/checkboxradio/
6441//>>css.structure: ../../themes/base/core.css
6442//>>css.structure: ../../themes/base/button.css
6443//>>css.structure: ../../themes/base/checkboxradio.css
6444//>>css.theme: ../../themes/base/theme.css
6445
6446
6447$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
6448    version: "1.14.1",
6449    options: {
6450        disabled: null,
6451        label: null,
6452        icon: true,
6453        classes: {
6454            "ui-checkboxradio-label": "ui-corner-all",
6455            "ui-checkboxradio-icon": "ui-corner-all"
6456        }
6457    },
6458
6459    _getCreateOptions: function() {
6460        var disabled, labels, labelContents;
6461        var options = this._super() || {};
6462
6463        // We read the type here, because it makes more sense to throw a element type error first,
6464        // rather then the error for lack of a label. Often if its the wrong type, it
6465        // won't have a label (e.g. calling on a div, btn, etc)
6466        this._readType();
6467
6468        labels = this.element.labels();
6469
6470        // If there are multiple labels, use the last one
6471        this.label = $( labels[ labels.length - 1 ] );
6472        if ( !this.label.length ) {
6473            $.error( "No label found for checkboxradio widget" );
6474        }
6475
6476        this.originalLabel = "";
6477
6478        // We need to get the label text but this may also need to make sure it does not contain the
6479        // input itself.
6480        // The label contents could be text, html, or a mix. We wrap all elements
6481        // and read the wrapper's `innerHTML` to get a string representation of
6482        // the label, without the input as part of it.
6483        labelContents = this.label.contents().not( this.element[ 0 ] );
6484
6485        if ( labelContents.length ) {
6486            this.originalLabel += labelContents
6487                .clone()
6488                .wrapAll( "<div></div>" )
6489                .parent()
6490                .html();
6491        }
6492
6493        // Set the label option if we found label text
6494        if ( this.originalLabel ) {
6495            options.label = this.originalLabel;
6496        }
6497
6498        disabled = this.element[ 0 ].disabled;
6499        if ( disabled != null ) {
6500            options.disabled = disabled;
6501        }
6502        return options;
6503    },
6504
6505    _create: function() {
6506        var checked = this.element[ 0 ].checked;
6507
6508        this._bindFormResetHandler();
6509
6510        if ( this.options.disabled == null ) {
6511            this.options.disabled = this.element[ 0 ].disabled;
6512        }
6513
6514        this._setOption( "disabled", this.options.disabled );
6515        this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
6516        this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
6517
6518        if ( this.type === "radio" ) {
6519            this._addClass( this.label, "ui-checkboxradio-radio-label" );
6520        }
6521
6522        if ( this.options.label && this.options.label !== this.originalLabel ) {
6523            this._updateLabel();
6524        } else if ( this.originalLabel ) {
6525            this.options.label = this.originalLabel;
6526        }
6527
6528        this._enhance();
6529
6530        if ( checked ) {
6531            this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
6532        }
6533
6534        this._on( {
6535            change: "_toggleClasses",
6536            focus: function() {
6537                this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
6538            },
6539            blur: function() {
6540                this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
6541            }
6542        } );
6543    },
6544
6545    _readType: function() {
6546        var nodeName = this.element[ 0 ].nodeName.toLowerCase();
6547        this.type = this.element[ 0 ].type;
6548        if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
6549            $.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
6550                " and element.type=" + this.type );
6551        }
6552    },
6553
6554    // Support jQuery Mobile enhanced option
6555    _enhance: function() {
6556        this._updateIcon( this.element[ 0 ].checked );
6557    },
6558
6559    widget: function() {
6560        return this.label;
6561    },
6562
6563    _getRadioGroup: function() {
6564        var group;
6565        var name = this.element[ 0 ].name;
6566        var nameSelector = "input[name='" + CSS.escape( name ) + "']";
6567
6568        if ( !name ) {
6569            return $( [] );
6570        }
6571
6572        if ( this.form.length ) {
6573            group = $( this.form[ 0 ].elements ).filter( nameSelector );
6574        } else {
6575
6576            // Not inside a form, check all inputs that also are not inside a form
6577            group = $( nameSelector ).filter( function() {
6578                return $( $( this ).prop( "form" ) ).length === 0;
6579            } );
6580        }
6581
6582        return group.not( this.element );
6583    },
6584
6585    _toggleClasses: function() {
6586        var checked = this.element[ 0 ].checked;
6587        this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6588
6589        if ( this.options.icon && this.type === "checkbox" ) {
6590            this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
6591                ._toggleClass( this.icon, null, "ui-icon-blank", !checked );
6592        }
6593
6594        if ( this.type === "radio" ) {
6595            this._getRadioGroup()
6596                .each( function() {
6597                    var instance = $( this ).checkboxradio( "instance" );
6598
6599                    if ( instance ) {
6600                        instance._removeClass( instance.label,
6601                            "ui-checkboxradio-checked", "ui-state-active" );
6602                    }
6603                } );
6604        }
6605    },
6606
6607    _destroy: function() {
6608        this._unbindFormResetHandler();
6609
6610        if ( this.icon ) {
6611            this.icon.remove();
6612            this.iconSpace.remove();
6613        }
6614    },
6615
6616    _setOption: function( key, value ) {
6617
6618        // We don't allow the value to be set to nothing
6619        if ( key === "label" && !value ) {
6620            return;
6621        }
6622
6623        this._super( key, value );
6624
6625        if ( key === "disabled" ) {
6626            this._toggleClass( this.label, null, "ui-state-disabled", value );
6627            this.element[ 0 ].disabled = value;
6628
6629            // Don't refresh when setting disabled
6630            return;
6631        }
6632        this.refresh();
6633    },
6634
6635    _updateIcon: function( checked ) {
6636        var toAdd = "ui-icon ui-icon-background ";
6637
6638        if ( this.options.icon ) {
6639            if ( !this.icon ) {
6640                this.icon = $( "<span>" );
6641                this.iconSpace = $( "<span> </span>" );
6642                this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
6643            }
6644
6645            if ( this.type === "checkbox" ) {
6646                toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
6647                this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
6648            } else {
6649                toAdd += "ui-icon-blank";
6650            }
6651            this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
6652            if ( !checked ) {
6653                this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
6654            }
6655            this.icon.prependTo( this.label ).after( this.iconSpace );
6656        } else if ( this.icon !== undefined ) {
6657            this.icon.remove();
6658            this.iconSpace.remove();
6659            delete this.icon;
6660        }
6661    },
6662
6663    _updateLabel: function() {
6664
6665        // Remove the contents of the label ( minus the icon, icon space, and input )
6666        var contents = this.label.contents().not( this.element[ 0 ] );
6667        if ( this.icon ) {
6668            contents = contents.not( this.icon[ 0 ] );
6669        }
6670        if ( this.iconSpace ) {
6671            contents = contents.not( this.iconSpace[ 0 ] );
6672        }
6673        contents.remove();
6674
6675        this.label.append( this.options.label );
6676    },
6677
6678    refresh: function() {
6679        var checked = this.element[ 0 ].checked,
6680            isDisabled = this.element[ 0 ].disabled;
6681
6682        this._updateIcon( checked );
6683        this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6684        if ( this.options.label !== null ) {
6685            this._updateLabel();
6686        }
6687
6688        if ( isDisabled !== this.options.disabled ) {
6689            this._setOptions( { "disabled": isDisabled } );
6690        }
6691    }
6692
6693} ] );
6694
6695var widgetsCheckboxradio = $.ui.checkboxradio;
6696
6697
6698/*!
6699 * jQuery UI Button 1.14.1
6700 * https://jqueryui.com
6701 *
6702 * Copyright OpenJS Foundation and other contributors
6703 * Released under the MIT license.
6704 * https://jquery.org/license
6705 */
6706
6707//>>label: Button
6708//>>group: Widgets
6709//>>description: Enhances a form with themeable buttons.
6710//>>docs: https://api.jqueryui.com/button/
6711//>>demos: https://jqueryui.com/button/
6712//>>css.structure: ../../themes/base/core.css
6713//>>css.structure: ../../themes/base/button.css
6714//>>css.theme: ../../themes/base/theme.css
6715
6716
6717$.widget( "ui.button", {
6718    version: "1.14.1",
6719    defaultElement: "<button>",
6720    options: {
6721        classes: {
6722            "ui-button": "ui-corner-all"
6723        },
6724        disabled: null,
6725        icon: null,
6726        iconPosition: "beginning",
6727        label: null,
6728        showLabel: true
6729    },
6730
6731    _getCreateOptions: function() {
6732        var disabled,
6733
6734            // This is to support cases like in jQuery Mobile where the base widget does have
6735            // an implementation of _getCreateOptions
6736            options = this._super() || {};
6737
6738        this.isInput = this.element.is( "input" );
6739
6740        disabled = this.element[ 0 ].disabled;
6741        if ( disabled != null ) {
6742            options.disabled = disabled;
6743        }
6744
6745        this.originalLabel = this.isInput ? this.element.val() : this.element.html();
6746        if ( this.originalLabel ) {
6747            options.label = this.originalLabel;
6748        }
6749
6750        return options;
6751    },
6752
6753    _create: function() {
6754        if ( !this.option.showLabel & !this.options.icon ) {
6755            this.options.showLabel = true;
6756        }
6757
6758        // We have to check the option again here even though we did in _getCreateOptions,
6759        // because null may have been passed on init which would override what was set in
6760        // _getCreateOptions
6761        if ( this.options.disabled == null ) {
6762            this.options.disabled = this.element[ 0 ].disabled || false;
6763        }
6764
6765        this.hasTitle = !!this.element.attr( "title" );
6766
6767        // Check to see if the label needs to be set or if its already correct
6768        if ( this.options.label && this.options.label !== this.originalLabel ) {
6769            if ( this.isInput ) {
6770                this.element.val( this.options.label );
6771            } else {
6772                this.element.html( this.options.label );
6773            }
6774        }
6775        this._addClass( "ui-button", "ui-widget" );
6776        this._setOption( "disabled", this.options.disabled );
6777        this._enhance();
6778
6779        if ( this.element.is( "a" ) ) {
6780            this._on( {
6781                "keyup": function( event ) {
6782                    if ( event.keyCode === $.ui.keyCode.SPACE ) {
6783                        event.preventDefault();
6784
6785                        // If a native click is available use it, so we
6786                        // actually cause navigation. Otherwise, just trigger
6787                        // a click event.
6788                        if ( this.element[ 0 ].click ) {
6789                            this.element[ 0 ].click();
6790                        } else {
6791                            this.element.trigger( "click" );
6792                        }
6793                    }
6794                }
6795            } );
6796        }
6797    },
6798
6799    _enhance: function() {
6800        if ( !this.element.is( "button" ) ) {
6801            this.element.attr( "role", "button" );
6802        }
6803
6804        if ( this.options.icon ) {
6805            this._updateIcon( "icon", this.options.icon );
6806            this._updateTooltip();
6807        }
6808    },
6809
6810    _updateTooltip: function() {
6811        this.title = this.element.attr( "title" );
6812
6813        if ( !this.options.showLabel && !this.title ) {
6814            this.element.attr( "title", this.options.label );
6815        }
6816    },
6817
6818    _updateIcon: function( option, value ) {
6819        var icon = option !== "iconPosition",
6820            position = icon ? this.options.iconPosition : value,
6821            displayBlock = position === "top" || position === "bottom";
6822
6823        // Create icon
6824        if ( !this.icon ) {
6825            this.icon = $( "<span>" );
6826
6827            this._addClass( this.icon, "ui-button-icon", "ui-icon" );
6828
6829            if ( !this.options.showLabel ) {
6830                this._addClass( "ui-button-icon-only" );
6831            }
6832        } else if ( icon ) {
6833
6834            // If we are updating the icon remove the old icon class
6835            this._removeClass( this.icon, null, this.options.icon );
6836        }
6837
6838        // If we are updating the icon add the new icon class
6839        if ( icon ) {
6840            this._addClass( this.icon, null, value );
6841        }
6842
6843        this._attachIcon( position );
6844
6845        // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
6846        // the iconSpace if there is one.
6847        if ( displayBlock ) {
6848            this._addClass( this.icon, null, "ui-widget-icon-block" );
6849            if ( this.iconSpace ) {
6850                this.iconSpace.remove();
6851            }
6852        } else {
6853
6854            // Position is beginning or end so remove the ui-widget-icon-block class and add the
6855            // space if it does not exist
6856            if ( !this.iconSpace ) {
6857                this.iconSpace = $( "<span> </span>" );
6858                this._addClass( this.iconSpace, "ui-button-icon-space" );
6859            }
6860            this._removeClass( this.icon, null, "ui-wiget-icon-block" );
6861            this._attachIconSpace( position );
6862        }
6863    },
6864
6865    _destroy: function() {
6866        this.element.removeAttr( "role" );
6867
6868        if ( this.icon ) {
6869            this.icon.remove();
6870        }
6871        if ( this.iconSpace ) {
6872            this.iconSpace.remove();
6873        }
6874        if ( !this.hasTitle ) {
6875            this.element.removeAttr( "title" );
6876        }
6877    },
6878
6879    _attachIconSpace: function( iconPosition ) {
6880        this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
6881    },
6882
6883    _attachIcon: function( iconPosition ) {
6884        this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
6885    },
6886
6887    _setOptions: function( options ) {
6888        var newShowLabel = options.showLabel === undefined ?
6889                this.options.showLabel :
6890                options.showLabel,
6891            newIcon = options.icon === undefined ? this.options.icon : options.icon;
6892
6893        if ( !newShowLabel && !newIcon ) {
6894            options.showLabel = true;
6895        }
6896        this._super( options );
6897    },
6898
6899    _setOption: function( key, value ) {
6900        if ( key === "icon" ) {
6901            if ( value ) {
6902                this._updateIcon( key, value );
6903            } else if ( this.icon ) {
6904                this.icon.remove();
6905                if ( this.iconSpace ) {
6906                    this.iconSpace.remove();
6907                }
6908            }
6909        }
6910
6911        if ( key === "iconPosition" ) {
6912            this._updateIcon( key, value );
6913        }
6914
6915        // Make sure we can't end up with a button that has neither text nor icon
6916        if ( key === "showLabel" ) {
6917                this._toggleClass( "ui-button-icon-only", null, !value );
6918                this._updateTooltip();
6919        }
6920
6921        if ( key === "label" ) {
6922            if ( this.isInput ) {
6923                this.element.val( value );
6924            } else {
6925
6926                // If there is an icon, append it, else nothing then append the value
6927                // this avoids removal of the icon when setting label text
6928                this.element.html( value );
6929                if ( this.icon ) {
6930                    this._attachIcon( this.options.iconPosition );
6931                    this._attachIconSpace( this.options.iconPosition );
6932                }
6933            }
6934        }
6935
6936        this._super( key, value );
6937
6938        if ( key === "disabled" ) {
6939            this._toggleClass( null, "ui-state-disabled", value );
6940            this.element[ 0 ].disabled = value;
6941            if ( value ) {
6942                this.element.trigger( "blur" );
6943            }
6944        }
6945    },
6946
6947    refresh: function() {
6948
6949        // Make sure to only check disabled if its an element that supports this otherwise
6950        // check for the disabled class to determine state
6951        var isDisabled = this.element.is( "input, button" ) ?
6952            this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
6953
6954        if ( isDisabled !== this.options.disabled ) {
6955            this._setOptions( { disabled: isDisabled } );
6956        }
6957
6958        this._updateTooltip();
6959    }
6960} );
6961
6962// DEPRECATED
6963if ( $.uiBackCompat === true ) {
6964
6965    // Text and Icons options
6966    $.widget( "ui.button", $.ui.button, {
6967        options: {
6968            text: true,
6969            icons: {
6970                primary: null,
6971                secondary: null
6972            }
6973        },
6974
6975        _create: function() {
6976            if ( this.options.showLabel && !this.options.text ) {
6977                this.options.showLabel = this.options.text;
6978            }
6979            if ( !this.options.showLabel && this.options.text ) {
6980                this.options.text = this.options.showLabel;
6981            }
6982            if ( !this.options.icon && ( this.options.icons.primary ||
6983                    this.options.icons.secondary ) ) {
6984                if ( this.options.icons.primary ) {
6985                    this.options.icon = this.options.icons.primary;
6986                } else {
6987                    this.options.icon = this.options.icons.secondary;
6988                    this.options.iconPosition = "end";
6989                }
6990            } else if ( this.options.icon ) {
6991                this.options.icons.primary = this.options.icon;
6992            }
6993            this._super();
6994        },
6995
6996        _setOption: function( key, value ) {
6997            if ( key === "text" ) {
6998                this._super( "showLabel", value );
6999                return;
7000            }
7001            if ( key === "showLabel" ) {
7002                this.options.text = value;
7003            }
7004            if ( key === "icon" ) {
7005                this.options.icons.primary = value;
7006            }
7007            if ( key === "icons" ) {
7008                if ( value.primary ) {
7009                    this._super( "icon", value.primary );
7010                    this._super( "iconPosition", "beginning" );
7011                } else if ( value.secondary ) {
7012                    this._super( "icon", value.secondary );
7013                    this._super( "iconPosition", "end" );
7014                }
7015            }
7016            this._superApply( arguments );
7017        }
7018    } );
7019
7020    $.fn.button = ( function( orig ) {
7021        return function( options ) {
7022            var isMethodCall = typeof options === "string";
7023            var args = Array.prototype.slice.call( arguments, 1 );
7024            var returnValue = this;
7025
7026            if ( isMethodCall ) {
7027
7028                // If this is an empty collection, we need to have the instance method
7029                // return undefined instead of the jQuery instance
7030                if ( !this.length && options === "instance" ) {
7031                    returnValue = undefined;
7032                } else {
7033                    this.each( function() {
7034                        var methodValue;
7035                        var type = $( this ).attr( "type" );
7036                        var name = type !== "checkbox" && type !== "radio" ?
7037                            "button" :
7038                            "checkboxradio";
7039                        var instance = $.data( this, "ui-" + name );
7040
7041                        if ( options === "instance" ) {
7042                            returnValue = instance;
7043                            return false;
7044                        }
7045
7046                        if ( !instance ) {
7047                            return $.error( "cannot call methods on button" +
7048                                " prior to initialization; " +
7049                                "attempted to call method '" + options + "'" );
7050                        }
7051
7052                        if ( typeof instance[ options ] !== "function" ||
7053                            options.charAt( 0 ) === "_" ) {
7054                            return $.error( "no such method '" + options + "' for button" +
7055                                " widget instance" );
7056                        }
7057
7058                        methodValue = instance[ options ].apply( instance, args );
7059
7060                        if ( methodValue !== instance && methodValue !== undefined ) {
7061                            returnValue = methodValue && methodValue.jquery ?
7062                                returnValue.pushStack( methodValue.get() ) :
7063                                methodValue;
7064                            return false;
7065                        }
7066                    } );
7067                }
7068            } else {
7069
7070                // Allow multiple hashes to be passed on init
7071                if ( args.length ) {
7072                    options = $.widget.extend.apply( null, [ options ].concat( args ) );
7073                }
7074
7075                this.each( function() {
7076                    var type = $( this ).attr( "type" );
7077                    var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
7078                    var instance = $.data( this, "ui-" + name );
7079
7080                    if ( instance ) {
7081                        instance.option( options || {} );
7082                        if ( instance._init ) {
7083                            instance._init();
7084                        }
7085                    } else {
7086                        if ( name === "button" ) {
7087                            orig.call( $( this ), options );
7088                            return;
7089                        }
7090
7091                        $( this ).checkboxradio( $.extend( { icon: false }, options ) );
7092                    }
7093                } );
7094            }
7095
7096            return returnValue;
7097        };
7098    } )( $.fn.button );
7099
7100    $.fn.buttonset = function() {
7101        if ( !$.ui.controlgroup ) {
7102            $.error( "Controlgroup widget missing" );
7103        }
7104        if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
7105            return this.controlgroup.apply( this,
7106                [ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
7107        }
7108        if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
7109            return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
7110        }
7111        if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
7112            arguments[ 0 ].items = {
7113                button: arguments[ 0 ].items
7114            };
7115        }
7116        return this.controlgroup.apply( this, arguments );
7117    };
7118}
7119
7120var widgetsButton = $.ui.button;
7121
7122
7123/* eslint-disable max-len, camelcase */
7124/*!
7125 * jQuery UI Datepicker 1.14.1
7126 * https://jqueryui.com
7127 *
7128 * Copyright OpenJS Foundation and other contributors
7129 * Released under the MIT license.
7130 * https://jquery.org/license
7131 */
7132
7133//>>label: Datepicker
7134//>>group: Widgets
7135//>>description: Displays a calendar from an input or inline for selecting dates.
7136//>>docs: https://api.jqueryui.com/datepicker/
7137//>>demos: https://jqueryui.com/datepicker/
7138//>>css.structure: ../../themes/base/core.css
7139//>>css.structure: ../../themes/base/datepicker.css
7140//>>css.theme: ../../themes/base/theme.css
7141
7142
7143$.extend( $.ui, { datepicker: { version: "1.14.1" } } );
7144
7145var datepicker_instActive;
7146
7147function datepicker_getZindex( elem ) {
7148    var position, value;
7149    while ( elem.length && elem[ 0 ] !== document ) {
7150
7151        // Ignore z-index if position is set to a value where z-index is ignored by the browser
7152        // This makes behavior of this function consistent across browsers
7153        // WebKit always returns auto if the element is positioned
7154        position = elem.css( "position" );
7155        if ( position === "absolute" || position === "relative" || position === "fixed" ) {
7156
7157            // IE returns 0 when zIndex is not specified
7158            // other browsers return a string
7159            // we ignore the case of nested elements with an explicit value of 0
7160            // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
7161            value = parseInt( elem.css( "zIndex" ), 10 );
7162            if ( !isNaN( value ) && value !== 0 ) {
7163                return value;
7164            }
7165        }
7166        elem = elem.parent();
7167    }
7168
7169    return 0;
7170}
7171
7172/* Date picker manager.
7173   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7174   Settings for (groups of) date pickers are maintained in an instance object,
7175   allowing multiple different settings on the same page. */
7176
7177function Datepicker() {
7178    this._curInst = null; // The current instance in use
7179    this._keyEvent = false; // If the last event was a key event
7180    this._disabledInputs = []; // List of date picker inputs that have been disabled
7181    this._datepickerShowing = false; // True if the popup picker is showing , false if not
7182    this._inDialog = false; // True if showing within a "dialog", false if not
7183    this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7184    this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7185    this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7186    this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7187    this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7188    this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7189    this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7190    this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7191    this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7192    this.regional = []; // Available regional settings, indexed by language code
7193    this.regional[ "" ] = { // Default regional settings
7194        closeText: "Done", // Display text for close link
7195        prevText: "Prev", // Display text for previous month link
7196        nextText: "Next", // Display text for next month link
7197        currentText: "Today", // Display text for current month link
7198        monthNames: [ "January", "February", "March", "April", "May", "June",
7199            "July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting
7200        monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
7201        dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
7202        dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
7203        dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday
7204        weekHeader: "Wk", // Column header for week of the year
7205        dateFormat: "mm/dd/yy", // See format options on parseDate
7206        firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7207        isRTL: false, // True if right-to-left language, false if left-to-right
7208        showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7209        yearSuffix: "", // Additional text to append to the year in the month headers,
7210        selectMonthLabel: "Select month", // Invisible label for month selector
7211        selectYearLabel: "Select year" // Invisible label for year selector
7212    };
7213    this._defaults = { // Global defaults for all the date picker instances
7214        showOn: "focus", // "focus" for popup on focus,
7215            // "button" for trigger button, or "both" for either
7216        showAnim: "fadeIn", // Name of jQuery animation for popup
7217        showOptions: {}, // Options for enhanced animations
7218        defaultDate: null, // Used when field is blank: actual date,
7219            // +/-number for offset from today, null for today
7220        appendText: "", // Display text following the input box, e.g. showing the format
7221        buttonText: "...", // Text for trigger button
7222        buttonImage: "", // URL for trigger button image
7223        buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7224        hideIfNoPrevNext: false, // True to hide next/previous month links
7225            // if not applicable, false to just disable them
7226        navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7227        gotoCurrent: false, // True if today link goes back to current selection instead
7228        changeMonth: false, // True if month can be selected directly, false if only prev/next
7229        changeYear: false, // True if year can be selected directly, false if only prev/next
7230        yearRange: "c-10:c+10", // Range of years to display in drop-down,
7231            // either relative to today's year (-nn:+nn), relative to currently displayed year
7232            // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7233        showOtherMonths: false, // True to show dates in other months, false to leave blank
7234        selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7235        showWeek: false, // True to show week of the year, false to not show it
7236        calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7237            // takes a Date and returns the number of the week for it
7238        shortYearCutoff: "+10", // Short year values < this are in the current century,
7239            // > this are in the previous century,
7240            // string value starting with "+" for current year + value
7241        minDate: null, // The earliest selectable date, or null for no limit
7242        maxDate: null, // The latest selectable date, or null for no limit
7243        duration: "fast", // Duration of display/closure
7244        isHoliday: null, // true: add class for displaying holiday
7245        beforeShowDay: null, // Function that takes a date and returns an array with
7246            // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7247            // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7248        beforeShow: null, // Function that takes an input field and
7249            // returns a set of custom settings for the date picker
7250        onSelect: null, // Define a callback function when a date is selected
7251        onChangeMonthYear: null, // Define a callback function when the month or year is changed
7252        onClose: null, // Define a callback function when the datepicker is closed
7253        onUpdateDatepicker: null, // Define a callback function when the datepicker is updated
7254        numberOfMonths: 1, // Number of months to show at a time
7255        showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7256        stepMonths: 1, // Number of months to step back/forward
7257        stepBigMonths: 12, // Number of months to step back/forward for the big links
7258        altField: "", // Selector for an alternate field to store selected dates into
7259        altFormat: "", // The date format to use for the alternate field
7260        constrainInput: true, // The input is constrained by the current date format
7261        showButtonPanel: false, // True to show button panel, false to not show it
7262        autoSize: false, // True to size the input for the date format, false to leave as is
7263        disabled: false // The initial disabled state
7264    };
7265    $.extend( this._defaults, this.regional[ "" ] );
7266    this.regional.en = $.extend( true, {}, this.regional[ "" ] );
7267    this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
7268    this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
7269}
7270
7271$.extend( Datepicker.prototype, {
7272
7273    /* Class name added to elements to indicate already configured with a date picker. */
7274    markerClassName: "hasDatepicker",
7275
7276    //Keep track of the maximum number of rows displayed (see #7043)
7277    maxRows: 4,
7278
7279    // TODO rename to "widget" when switching to widget factory
7280    _widgetDatepicker: function() {
7281        return this.dpDiv;
7282    },
7283
7284    /* Override the default settings for all instances of the date picker.
7285     * @param  settings  object - the new settings to use as defaults (anonymous object)
7286     * @return the manager object
7287     */
7288    setDefaults: function( settings ) {
7289        datepicker_extendRemove( this._defaults, settings || {} );
7290        return this;
7291    },
7292
7293    /* Attach the date picker to a jQuery selection.
7294     * @param  target   element - the target input field or division or span
7295     * @param  settings  object - the new settings to use for this date picker instance (anonymous)
7296     */
7297    _attachDatepicker: function( target, settings ) {
7298        var nodeName, inline, inst;
7299        nodeName = target.nodeName.toLowerCase();
7300        inline = ( nodeName === "div" || nodeName === "span" );
7301        if ( !target.id ) {
7302            this.uuid += 1;
7303            target.id = "dp" + this.uuid;
7304        }
7305        inst = this._newInst( $( target ), inline );
7306        inst.settings = $.extend( {}, settings || {} );
7307        if ( nodeName === "input" ) {
7308            this._connectDatepicker( target, inst );
7309        } else if ( inline ) {
7310            this._inlineDatepicker( target, inst );
7311        }
7312    },
7313
7314    /* Create a new instance object. */
7315    _newInst: function( target, inline ) {
7316        var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
7317        return { id: id, input: target, // associated target
7318            selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7319            drawMonth: 0, drawYear: 0, // month being drawn
7320            inline: inline, // is datepicker inline or not
7321            dpDiv: ( !inline ? this.dpDiv : // presentation div
7322            datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
7323    },
7324
7325    /* Attach the date picker to an input field. */
7326    _connectDatepicker: function( target, inst ) {
7327        var input = $( target );
7328        inst.append = $( [] );
7329        inst.trigger = $( [] );
7330        if ( input.hasClass( this.markerClassName ) ) {
7331            return;
7332        }
7333        this._attachments( input, inst );
7334        input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
7335            on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
7336        this._autoSize( inst );
7337        $.data( target, "datepicker", inst );
7338
7339        //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7340        if ( inst.settings.disabled ) {
7341            this._disableDatepicker( target );
7342        }
7343    },
7344
7345    /* Make attachments based on settings. */
7346    _attachments: function( input, inst ) {
7347        var showOn, buttonText, buttonImage,
7348            appendText = this._get( inst, "appendText" ),
7349            isRTL = this._get( inst, "isRTL" );
7350
7351        if ( inst.append ) {
7352            inst.append.remove();
7353        }
7354        if ( appendText ) {
7355            inst.append = $( "<span>" )
7356                .addClass( this._appendClass )
7357                .text( appendText );
7358            input[ isRTL ? "before" : "after" ]( inst.append );
7359        }
7360
7361        input.off( "focus", this._showDatepicker );
7362
7363        if ( inst.trigger ) {
7364            inst.trigger.remove();
7365        }
7366
7367        showOn = this._get( inst, "showOn" );
7368        if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
7369            input.on( "focus", this._showDatepicker );
7370        }
7371        if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
7372            buttonText = this._get( inst, "buttonText" );
7373            buttonImage = this._get( inst, "buttonImage" );
7374
7375            if ( this._get( inst, "buttonImageOnly" ) ) {
7376                inst.trigger = $( "<img>" )
7377                    .addClass( this._triggerClass )
7378                    .attr( {
7379                        src: buttonImage,
7380                        alt: "대관 신청기간 선택 달력",
7381                        title: "대관 신청기간 선택 달력"
7382                    } );
7383            } else {
7384                inst.trigger = $( "<button type='button'>" )
7385                    .addClass( this._triggerClass );
7386                if ( buttonImage ) {
7387                    inst.trigger.html(
7388                        $( "<img>" )
7389                            .attr( {
7390                                src: buttonImage,
7391                                alt: "대관 신청기간 선택 달력",
7392                                title: "대관 신청기간 선택 달력"
7393                            } )
7394                    );
7395                } else {
7396                    inst.trigger.text( buttonText );
7397                }
7398            }
7399
7400            input[ isRTL ? "before" : "after" ]( inst.trigger );
7401            inst.trigger.on( "click", function() {
7402                if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
7403                    $.datepicker._hideDatepicker();
7404                } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
7405                    $.datepicker._hideDatepicker();
7406                    $.datepicker._showDatepicker( input[ 0 ] );
7407                } else {
7408                    $.datepicker._showDatepicker( input[ 0 ] );
7409                }
7410                return false;
7411            } );
7412        }
7413    },
7414
7415    /* Apply the maximum length for the date format. */
7416    _autoSize: function( inst ) {
7417        if ( this._get( inst, "autoSize" ) && !inst.inline ) {
7418            var findMax, max, maxI, i,
7419                date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
7420                dateFormat = this._get( inst, "dateFormat" );
7421
7422            if ( dateFormat.match( /[DM]/ ) ) {
7423                findMax = function( names ) {
7424                    max = 0;
7425                    maxI = 0;
7426                    for ( i = 0; i < names.length; i++ ) {
7427                        if ( names[ i ].length > max ) {
7428                            max = names[ i ].length;
7429                            maxI = i;
7430                        }
7431                    }
7432                    return maxI;
7433                };
7434                date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
7435                    "monthNames" : "monthNamesShort" ) ) ) );
7436                date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
7437                    "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
7438            }
7439            inst.input.attr( "size", this._formatDate( inst, date ).length );
7440        }
7441    },
7442
7443    /* Attach an inline date picker to a div. */
7444    _inlineDatepicker: function( target, inst ) {
7445        var divSpan = $( target );
7446        if ( divSpan.hasClass( this.markerClassName ) ) {
7447            return;
7448        }
7449        divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
7450        $.data( target, "datepicker", inst );
7451        this._setDate( inst, this._getDefaultDate( inst ), true );
7452        this._updateDatepicker( inst );
7453        this._updateAlternate( inst );
7454
7455        //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7456        if ( inst.settings.disabled ) {
7457            this._disableDatepicker( target );
7458        }
7459
7460        // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7461        // https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7462        inst.dpDiv.css( "display", "block" );
7463    },
7464
7465    /* Pop-up the date picker in a "dialog" box.
7466     * @param  input element - ignored
7467     * @param  date string or Date - the initial date to display
7468     * @param  onSelect  function - the function to call when a date is selected
7469     * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7470     * @param  pos int[2] - coordinates for the dialog's position within the screen or
7471     *                  event - with x/y coordinates or
7472     *                  leave empty for default (screen centre)
7473     * @return the manager object
7474     */
7475    _dialogDatepicker: function( input, date, onSelect, settings, pos ) {
7476        var id, browserWidth, browserHeight, scrollX, scrollY,
7477            inst = this._dialogInst; // internal instance
7478
7479        if ( !inst ) {
7480            this.uuid += 1;
7481            id = "dp" + this.uuid;
7482            this._dialogInput = $( "<input type='text' id='" + id +
7483                "' style='position: absolute; top: -100px; width: 0px;'/>" );
7484            this._dialogInput.on( "keydown", this._doKeyDown );
7485            $( "body" ).append( this._dialogInput );
7486            inst = this._dialogInst = this._newInst( this._dialogInput, false );
7487            inst.settings = {};
7488            $.data( this._dialogInput[ 0 ], "datepicker", inst );
7489        }
7490        datepicker_extendRemove( inst.settings, settings || {} );
7491        date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
7492        this._dialogInput.val( date );
7493
7494        this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
7495        if ( !this._pos ) {
7496            browserWidth = document.documentElement.clientWidth;
7497            browserHeight = document.documentElement.clientHeight;
7498            scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7499            scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7500            this._pos = // should use actual width/height below
7501                [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
7502        }
7503
7504        // Move input on screen for focus, but hidden behind dialog
7505        this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
7506        inst.settings.onSelect = onSelect;
7507        this._inDialog = true;
7508        this.dpDiv.addClass( this._dialogClass );
7509        this._showDatepicker( this._dialogInput[ 0 ] );
7510        if ( $.blockUI ) {
7511            $.blockUI( this.dpDiv );
7512        }
7513        $.data( this._dialogInput[ 0 ], "datepicker", inst );
7514        return this;
7515    },
7516
7517    /* Detach a datepicker from its control.
7518     * @param  target   element - the target input field or division or span
7519     */
7520    _destroyDatepicker: function( target ) {
7521        var nodeName,
7522            $target = $( target ),
7523            inst = $.data( target, "datepicker" );
7524
7525        if ( !$target.hasClass( this.markerClassName ) ) {
7526            return;
7527        }
7528
7529        nodeName = target.nodeName.toLowerCase();
7530        $.removeData( target, "datepicker" );
7531        if ( nodeName === "input" ) {
7532            inst.append.remove();
7533            inst.trigger.remove();
7534            $target.removeClass( this.markerClassName ).
7535                off( "focus", this._showDatepicker ).
7536                off( "keydown", this._doKeyDown ).
7537                off( "keypress", this._doKeyPress ).
7538                off( "keyup", this._doKeyUp );
7539        } else if ( nodeName === "div" || nodeName === "span" ) {
7540            $target.removeClass( this.markerClassName ).empty();
7541        }
7542
7543        $.datepicker._hideDatepicker();
7544        if ( datepicker_instActive === inst ) {
7545            datepicker_instActive = null;
7546            this._curInst = null;
7547        }
7548    },
7549
7550    /* Enable the date picker to a jQuery selection.
7551     * @param  target   element - the target input field or division or span
7552     */
7553    _enableDatepicker: function( target ) {
7554        var nodeName, inline,
7555            $target = $( target ),
7556            inst = $.data( target, "datepicker" );
7557
7558        if ( !$target.hasClass( this.markerClassName ) ) {
7559            return;
7560        }
7561
7562        nodeName = target.nodeName.toLowerCase();
7563        if ( nodeName === "input" ) {
7564            target.disabled = false;
7565            inst.trigger.filter( "button" ).
7566                each( function() {
7567                    this.disabled = false;
7568                } ).end().
7569                filter( "img" ).css( { opacity: "1.0", cursor: "" } );
7570        } else if ( nodeName === "div" || nodeName === "span" ) {
7571            inline = $target.children( "." + this._inlineClass );
7572            inline.children().removeClass( "ui-state-disabled" );
7573            inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7574                prop( "disabled", false );
7575        }
7576        this._disabledInputs = $.map( this._disabledInputs,
7577
7578            // Delete entry
7579            function( value ) {
7580                return ( value === target ? null : value );
7581            } );
7582    },
7583
7584    /* Disable the date picker to a jQuery selection.
7585     * @param  target   element - the target input field or division or span
7586     */
7587    _disableDatepicker: function( target ) {
7588        var nodeName, inline,
7589            $target = $( target ),
7590            inst = $.data( target, "datepicker" );
7591
7592        if ( !$target.hasClass( this.markerClassName ) ) {
7593            return;
7594        }
7595
7596        nodeName = target.nodeName.toLowerCase();
7597        if ( nodeName === "input" ) {
7598            target.disabled = true;
7599            inst.trigger.filter( "button" ).
7600                each( function() {
7601                    this.disabled = true;
7602                } ).end().
7603                filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
7604        } else if ( nodeName === "div" || nodeName === "span" ) {
7605            inline = $target.children( "." + this._inlineClass );
7606            inline.children().addClass( "ui-state-disabled" );
7607            inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7608                prop( "disabled", true );
7609        }
7610        this._disabledInputs = $.map( this._disabledInputs,
7611
7612            // Delete entry
7613            function( value ) {
7614                return ( value === target ? null : value );
7615            } );
7616        this._disabledInputs[ this._disabledInputs.length ] = target;
7617    },
7618
7619    /* Is the first field in a jQuery collection disabled as a datepicker?
7620     * @param  target   element - the target input field or division or span
7621     * @return boolean - true if disabled, false if enabled
7622     */
7623    _isDisabledDatepicker: function( target ) {
7624        if ( !target ) {
7625            return false;
7626        }
7627        for ( var i = 0; i < this._disabledInputs.length; i++ ) {
7628            if ( this._disabledInputs[ i ] === target ) {
7629                return true;
7630            }
7631        }
7632        return false;
7633    },
7634
7635    /* Retrieve the instance data for the target control.
7636     * @param  target  element - the target input field or division or span
7637     * @return  object - the associated instance data
7638     * @throws  error if a jQuery problem getting data
7639     */
7640    _getInst: function( target ) {
7641        try {
7642            return $.data( target, "datepicker" );
7643        } catch ( err ) {
7644            throw "Missing instance data for this datepicker";
7645        }
7646    },
7647
7648    /* Update or retrieve the settings for a date picker attached to an input field or division.
7649     * @param  target  element - the target input field or division or span
7650     * @param  name object - the new settings to update or
7651     *              string - the name of the setting to change or retrieve,
7652     *              when retrieving also "all" for all instance settings or
7653     *              "defaults" for all global defaults
7654     * @param  value   any - the new value for the setting
7655     *              (omit if above is an object or to retrieve a value)
7656     */
7657    _optionDatepicker: function( target, name, value ) {
7658        var settings, date, minDate, maxDate,
7659            inst = this._getInst( target );
7660
7661        if ( arguments.length === 2 && typeof name === "string" ) {
7662            return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
7663                ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
7664                this._get( inst, name ) ) : null ) );
7665        }
7666
7667        settings = name || {};
7668        if ( typeof name === "string" ) {
7669            settings = {};
7670            settings[ name ] = value;
7671        }
7672
7673        if ( inst ) {
7674            if ( this._curInst === inst ) {
7675                this._hideDatepicker();
7676            }
7677
7678            date = this._getDateDatepicker( target, true );
7679            minDate = this._getMinMaxDate( inst, "min" );
7680            maxDate = this._getMinMaxDate( inst, "max" );
7681            datepicker_extendRemove( inst.settings, settings );
7682
7683            // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7684            if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
7685                inst.settings.minDate = this._formatDate( inst, minDate );
7686            }
7687            if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
7688                inst.settings.maxDate = this._formatDate( inst, maxDate );
7689            }
7690            if ( "disabled" in settings ) {
7691                if ( settings.disabled ) {
7692                    this._disableDatepicker( target );
7693                } else {
7694                    this._enableDatepicker( target );
7695                }
7696            }
7697            this._attachments( $( target ), inst );
7698            this._autoSize( inst );
7699            this._setDate( inst, date );
7700            this._updateAlternate( inst );
7701            this._updateDatepicker( inst );
7702        }
7703    },
7704
7705    // Change method deprecated
7706    _changeDatepicker: function( target, name, value ) {
7707        this._optionDatepicker( target, name, value );
7708    },
7709
7710    /* Redraw the date picker attached to an input field or division.
7711     * @param  target  element - the target input field or division or span
7712     */
7713    _refreshDatepicker: function( target ) {
7714        var inst = this._getInst( target );
7715        if ( inst ) {
7716            this._updateDatepicker( inst );
7717        }
7718    },
7719
7720    /* Set the dates for a jQuery selection.
7721     * @param  target element - the target input field or division or span
7722     * @param  date Date - the new date
7723     */
7724    _setDateDatepicker: function( target, date ) {
7725        var inst = this._getInst( target );
7726        if ( inst ) {
7727            this._setDate( inst, date );
7728            this._updateDatepicker( inst );
7729            this._updateAlternate( inst );
7730        }
7731    },
7732
7733    /* Get the date(s) for the first entry in a jQuery selection.
7734     * @param  target element - the target input field or division or span
7735     * @param  noDefault boolean - true if no default date is to be used
7736     * @return Date - the current date
7737     */
7738    _getDateDatepicker: function( target, noDefault ) {
7739        var inst = this._getInst( target );
7740        if ( inst && !inst.inline ) {
7741            this._setDateFromField( inst, noDefault );
7742        }
7743        return ( inst ? this._getDate( inst ) : null );
7744    },
7745
7746    /* Handle keystrokes. */
7747    _doKeyDown: function( event ) {
7748        var onSelect, dateStr, sel,
7749            inst = $.datepicker._getInst( event.target ),
7750            handled = true,
7751            isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
7752
7753        inst._keyEvent = true;
7754        if ( $.datepicker._datepickerShowing ) {
7755            switch ( event.keyCode ) {
7756                case 9: $.datepicker._hideDatepicker();
7757                        handled = false;
7758                        break; // hide on tab out
7759                case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
7760                                    $.datepicker._currentClass + ")", inst.dpDiv );
7761                        if ( sel[ 0 ] ) {
7762                            $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
7763                        }
7764
7765                        onSelect = $.datepicker._get( inst, "onSelect" );
7766                        if ( onSelect ) {
7767                            dateStr = $.datepicker._formatDate( inst );
7768
7769                            // Trigger custom callback
7770                            onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
7771                        } else {
7772                            $.datepicker._hideDatepicker();
7773                        }
7774
7775                        return false; // don't submit the form
7776                case 27: $.datepicker._hideDatepicker();
7777                        break; // hide on escape
7778                case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7779                            -$.datepicker._get( inst, "stepBigMonths" ) :
7780                            -$.datepicker._get( inst, "stepMonths" ) ), "M" );
7781                        break; // previous month/year on page up/+ ctrl
7782                case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7783                            +$.datepicker._get( inst, "stepBigMonths" ) :
7784                            +$.datepicker._get( inst, "stepMonths" ) ), "M" );
7785                        break; // next month/year on page down/+ ctrl
7786                case 35: if ( event.ctrlKey || event.metaKey ) {
7787                            $.datepicker._clearDate( event.target );
7788                        }
7789                        handled = event.ctrlKey || event.metaKey;
7790                        break; // clear on ctrl or command +end
7791                case 36: if ( event.ctrlKey || event.metaKey ) {
7792                            $.datepicker._gotoToday( event.target );
7793                        }
7794                        handled = event.ctrlKey || event.metaKey;
7795                        break; // current on ctrl or command +home
7796                case 37: if ( event.ctrlKey || event.metaKey ) {
7797                            $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
7798                        }
7799                        handled = event.ctrlKey || event.metaKey;
7800
7801                        // -1 day on ctrl or command +left
7802                        if ( event.originalEvent.altKey ) {
7803                            $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7804                                -$.datepicker._get( inst, "stepBigMonths" ) :
7805                                -$.datepicker._get( inst, "stepMonths" ) ), "M" );
7806                        }
7807
7808                        // next month/year on alt +left on Mac
7809                        break;
7810                case 38: if ( event.ctrlKey || event.metaKey ) {
7811                            $.datepicker._adjustDate( event.target, -7, "D" );
7812                        }
7813                        handled = event.ctrlKey || event.metaKey;
7814                        break; // -1 week on ctrl or command +up
7815                case 39: if ( event.ctrlKey || event.metaKey ) {
7816                            $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
7817                        }
7818                        handled = event.ctrlKey || event.metaKey;
7819
7820                        // +1 day on ctrl or command +right
7821                        if ( event.originalEvent.altKey ) {
7822                            $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7823                                +$.datepicker._get( inst, "stepBigMonths" ) :
7824                                +$.datepicker._get( inst, "stepMonths" ) ), "M" );
7825                        }
7826
7827                        // next month/year on alt +right
7828                        break;
7829                case 40: if ( event.ctrlKey || event.metaKey ) {
7830                            $.datepicker._adjustDate( event.target, +7, "D" );
7831                        }
7832                        handled = event.ctrlKey || event.metaKey;
7833                        break; // +1 week on ctrl or command +down
7834                default: handled = false;
7835            }
7836        } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
7837            $.datepicker._showDatepicker( this );
7838        } else {
7839            handled = false;
7840        }
7841
7842        if ( handled ) {
7843            event.preventDefault();
7844            event.stopPropagation();
7845        }
7846    },
7847
7848    /* Filter entered characters - based on date format. */
7849    _doKeyPress: function( event ) {
7850        var chars, chr,
7851            inst = $.datepicker._getInst( event.target );
7852
7853        if ( $.datepicker._get( inst, "constrainInput" ) ) {
7854            chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
7855            chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
7856            return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
7857        }
7858    },
7859
7860    /* Synchronise manual entry and field/alternate field. */
7861    _doKeyUp: function( event ) {
7862        var date,
7863            inst = $.datepicker._getInst( event.target );
7864
7865        if ( inst.input.val() !== inst.lastVal ) {
7866            try {
7867                date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
7868                    ( inst.input ? inst.input.val() : null ),
7869                    $.datepicker._getFormatConfig( inst ) );
7870
7871                if ( date ) { // only if valid
7872                    $.datepicker._setDateFromField( inst );
7873                    $.datepicker._updateAlternate( inst );
7874                    $.datepicker._updateDatepicker( inst );
7875                }
7876            } catch ( err ) {
7877            }
7878        }
7879        return true;
7880    },
7881
7882    /* Pop-up the date picker for a given input field.
7883     * If false returned from beforeShow event handler do not show.
7884     * @param  input  element - the input field attached to the date picker or
7885     *                  event - if triggered by focus
7886     */
7887    _showDatepicker: function( input ) {
7888        input = input.target || input;
7889        if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
7890            input = $( "input", input.parentNode )[ 0 ];
7891        }
7892
7893        if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
7894            return;
7895        }
7896
7897        var inst, beforeShow, beforeShowSettings, isFixed,
7898            offset, showAnim, duration;
7899
7900        inst = $.datepicker._getInst( input );
7901        if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
7902            $.datepicker._curInst.dpDiv.stop( true, true );
7903            if ( inst && $.datepicker._datepickerShowing ) {
7904                $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
7905            }
7906        }
7907
7908        beforeShow = $.datepicker._get( inst, "beforeShow" );
7909        beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
7910        if ( beforeShowSettings === false ) {
7911            return;
7912        }
7913        datepicker_extendRemove( inst.settings, beforeShowSettings );
7914
7915        inst.lastVal = null;
7916        $.datepicker._lastInput = input;
7917        $.datepicker._setDateFromField( inst );
7918
7919        if ( $.datepicker._inDialog ) { // hide cursor
7920            input.value = "";
7921        }
7922        if ( !$.datepicker._pos ) { // position below input
7923            $.datepicker._pos = $.datepicker._findPos( input );
7924            $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
7925        }
7926
7927        isFixed = false;
7928        $( input ).parents().each( function() {
7929            isFixed |= $( this ).css( "position" ) === "fixed";
7930            return !isFixed;
7931        } );
7932
7933        offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
7934        $.datepicker._pos = null;
7935
7936        //to avoid flashes on Firefox
7937        inst.dpDiv.empty();
7938
7939        // determine sizing offscreen
7940        inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
7941        $.datepicker._updateDatepicker( inst );
7942
7943        // fix width for dynamic number of date pickers
7944        // and adjust position before showing
7945        offset = $.datepicker._checkOffset( inst, offset, isFixed );
7946        inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
7947            "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
7948            left: offset.left + "px", top: offset.top + "px" } );
7949
7950        if ( !inst.inline ) {
7951            showAnim = $.datepicker._get( inst, "showAnim" );
7952            duration = $.datepicker._get( inst, "duration" );
7953            inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
7954            $.datepicker._datepickerShowing = true;
7955
7956            if ( $.effects && $.effects.effect[ showAnim ] ) {
7957                inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
7958            } else {
7959                inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
7960            }
7961
7962            if ( $.datepicker._shouldFocusInput( inst ) ) {
7963                inst.input.trigger( "focus" );
7964            }
7965
7966            $.datepicker._curInst = inst;
7967        }
7968    },
7969
7970    /* Generate the date picker content. */
7971    _updateDatepicker: function( inst ) {
7972        this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
7973        datepicker_instActive = inst; // for delegate hover events
7974        inst.dpDiv.empty().append( this._generateHTML( inst ) );
7975        this._attachHandlers( inst );
7976
7977        var origyearshtml,
7978            numMonths = this._getNumberOfMonths( inst ),
7979            cols = numMonths[ 1 ],
7980            width = 17,
7981            activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
7982            onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
7983
7984        if ( activeCell.length > 0 ) {
7985            datepicker_handleMouseover.apply( activeCell.get( 0 ) );
7986        }
7987
7988        inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
7989        if ( cols > 1 ) {
7990            inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
7991        }
7992        inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
7993            "Class" ]( "ui-datepicker-multi" );
7994        inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
7995            "Class" ]( "ui-datepicker-rtl" );
7996
7997        if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
7998            inst.input.trigger( "focus" );
7999        }
8000
8001        // Deffered render of the years select (to avoid flashes on Firefox)
8002        if ( inst.yearshtml ) {
8003            origyearshtml = inst.yearshtml;
8004            setTimeout( function() {
8005
8006                //assure that inst.yearshtml didn't change.
8007                if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
8008                    inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
8009                }
8010                origyearshtml = inst.yearshtml = null;
8011            }, 0 );
8012        }
8013
8014        if ( onUpdateDatepicker ) {
8015            onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
8016        }
8017    },
8018
8019    _shouldFocusInput: function( inst ) {
8020        return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" );
8021    },
8022
8023    /* Check positioning to remain on screen. */
8024    _checkOffset: function( inst, offset, isFixed ) {
8025        var dpWidth = inst.dpDiv.outerWidth(),
8026            dpHeight = inst.dpDiv.outerHeight(),
8027            inputWidth = inst.input ? inst.input.outerWidth() : 0,
8028            inputHeight = inst.input ? inst.input.outerHeight() : 0,
8029            viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
8030            viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
8031
8032        offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
8033        offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
8034        offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
8035
8036        // Now check if datepicker is showing outside window viewport - move to a better place if so.
8037        offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
8038            Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
8039        offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
8040            Math.abs( dpHeight + inputHeight ) : 0 );
8041
8042        return offset;
8043    },
8044
8045    /* Find an object's position on the screen. */
8046    _findPos: function( obj ) {
8047        var position,
8048            inst = this._getInst( obj ),
8049            isRTL = this._get( inst, "isRTL" );
8050
8051        while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
8052            obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
8053        }
8054
8055        position = $( obj ).offset();
8056        return [ position.left, position.top ];
8057    },
8058
8059    /* Hide the date picker from view.
8060     * @param  input  element - the input field attached to the date picker
8061     */
8062    _hideDatepicker: function( input ) {
8063        var showAnim, duration, postProcess, onClose,
8064            inst = this._curInst;
8065
8066        if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
8067            return;
8068        }
8069
8070        if ( this._datepickerShowing ) {
8071            showAnim = this._get( inst, "showAnim" );
8072            duration = this._get( inst, "duration" );
8073            postProcess = function() {
8074                $.datepicker._tidyDialog( inst );
8075            };
8076
8077            if ( $.effects && ( $.effects.effect[ showAnim ] ) ) {
8078                inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
8079            } else {
8080                inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
8081                    ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
8082            }
8083
8084            if ( !showAnim ) {
8085                postProcess();
8086            }
8087            this._datepickerShowing = false;
8088
8089            onClose = this._get( inst, "onClose" );
8090            if ( onClose ) {
8091                onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
8092            }
8093
8094            this._lastInput = null;
8095            if ( this._inDialog ) {
8096                this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
8097                if ( $.blockUI ) {
8098                    $.unblockUI();
8099                    $( "body" ).append( this.dpDiv );
8100                }
8101            }
8102            this._inDialog = false;
8103        }
8104    },
8105
8106    /* Tidy up after a dialog display. */
8107    _tidyDialog: function( inst ) {
8108        inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
8109    },
8110
8111    /* Close date picker if clicked elsewhere. */
8112    _checkExternalClick: function( event ) {
8113        if ( !$.datepicker._curInst ) {
8114            return;
8115        }
8116
8117        var $target = $( event.target ),
8118            inst = $.datepicker._getInst( $target[ 0 ] );
8119
8120        if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
8121                $target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
8122                !$target.hasClass( $.datepicker.markerClassName ) &&
8123                !$target.closest( "." + $.datepicker._triggerClass ).length &&
8124                $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
8125            ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
8126                $.datepicker._hideDatepicker();
8127        }
8128    },
8129
8130    /* Adjust one of the date sub-fields. */
8131    _adjustDate: function( id, offset, period ) {
8132        var target = $( id ),
8133            inst = this._getInst( target[ 0 ] );
8134
8135        if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
8136            return;
8137        }
8138        this._adjustInstDate( inst, offset, period );
8139        this._updateDatepicker( inst );
8140    },
8141
8142    /* Action for current link. */
8143    _gotoToday: function( id ) {
8144        var date,
8145            target = $( id ),
8146            inst = this._getInst( target[ 0 ] );
8147
8148        if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
8149            inst.selectedDay = inst.currentDay;
8150            inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8151            inst.drawYear = inst.selectedYear = inst.currentYear;
8152        } else {
8153            date = new Date();
8154            inst.selectedDay = date.getDate();
8155            inst.drawMonth = inst.selectedMonth = date.getMonth();
8156            inst.drawYear = inst.selectedYear = date.getFullYear();
8157        }
8158        this._notifyChange( inst );
8159        this._adjustDate( target );
8160    },
8161
8162    /* Action for selecting a new month/year. */
8163    _selectMonthYear: function( id, select, period ) {
8164        var target = $( id ),
8165            inst = this._getInst( target[ 0 ] );
8166
8167        inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
8168        inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
8169            parseInt( select.options[ select.selectedIndex ].value, 10 );
8170
8171        this._notifyChange( inst );
8172        this._adjustDate( target );
8173    },
8174
8175    /* Action for selecting a day. */
8176    _selectDay: function( id, month, year, td ) {
8177        var inst,
8178            target = $( id );
8179
8180        if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
8181            return;
8182        }
8183
8184        inst = this._getInst( target[ 0 ] );
8185        inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
8186        inst.selectedMonth = inst.currentMonth = month;
8187        inst.selectedYear = inst.currentYear = year;
8188        this._selectDate( id, this._formatDate( inst,
8189            inst.currentDay, inst.currentMonth, inst.currentYear ) );
8190    },
8191
8192    /* Erase the input field and hide the date picker. */
8193    _clearDate: function( id ) {
8194        var target = $( id );
8195        this._selectDate( target, "" );
8196    },
8197
8198    /* Update the input field with the selected date. */
8199    _selectDate: function( id, dateStr ) {
8200        var onSelect,
8201            target = $( id ),
8202            inst = this._getInst( target[ 0 ] );
8203
8204        dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
8205        if ( inst.input ) {
8206            inst.input.val( dateStr );
8207        }
8208        this._updateAlternate( inst );
8209
8210        onSelect = this._get( inst, "onSelect" );
8211        if ( onSelect ) {
8212            onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
8213        } else if ( inst.input ) {
8214            inst.input.trigger( "change" ); // fire the change event
8215        }
8216
8217        if ( inst.inline ) {
8218            this._updateDatepicker( inst );
8219        } else {
8220            this._hideDatepicker();
8221            this._lastInput = inst.input[ 0 ];
8222            if ( typeof( inst.input[ 0 ] ) !== "object" ) {
8223                inst.input.trigger( "focus" ); // restore focus
8224            }
8225            this._lastInput = null;
8226        }
8227    },
8228
8229    /* Update any alternate field to synchronise with the main field. */
8230    _updateAlternate: function( inst ) {
8231        var altFormat, date, dateStr,
8232            altField = this._get( inst, "altField" );
8233
8234        if ( altField ) { // update alternate field too
8235            altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
8236            date = this._getDate( inst );
8237            dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
8238            $( document ).find( altField ).val( dateStr );
8239        }
8240    },
8241
8242    /* Set as beforeShowDay function to prevent selection of weekends.
8243     * @param  date  Date - the date to customise
8244     * @return [boolean, string] - is this date selectable?, what is its CSS class?
8245     */
8246    noWeekends: function( date ) {
8247        var day = date.getDay();
8248        return [ ( day > 0 && day < 6 ), "" ];
8249    },
8250
8251    /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8252     * @param  date  Date - the date to get the week for
8253     * @return  number - the number of the week within the year that contains this date
8254     */
8255    iso8601Week: function( date ) {
8256        var time,
8257            checkDate = new Date( date.getTime() );
8258
8259        // Find Thursday of this week starting on Monday
8260        checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
8261
8262        time = checkDate.getTime();
8263        checkDate.setMonth( 0 ); // Compare with Jan 1
8264        checkDate.setDate( 1 );
8265        return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
8266    },
8267
8268    /* Parse a string value into a date object.
8269     * See formatDate below for the possible formats.
8270     *
8271     * @param  format string - the expected format of the date
8272     * @param  value string - the date in the above format
8273     * @param  settings Object - attributes include:
8274     *                  shortYearCutoff  number - the cutoff year for determining the century (optional)
8275     *                  dayNamesShort   string[7] - abbreviated names of the days from Sunday (optional)
8276     *                  dayNames        string[7] - names of the days from Sunday (optional)
8277     *                  monthNamesShort string[12] - abbreviated names of the months (optional)
8278     *                  monthNames      string[12] - names of the months (optional)
8279     * @return  Date - the extracted date value or null if value is blank
8280     */
8281    parseDate: function( format, value, settings ) {
8282        if ( format == null || value == null ) {
8283            throw "Invalid arguments";
8284        }
8285
8286        value = ( typeof value === "object" ? value.toString() : value + "" );
8287        if ( value === "" ) {
8288            return null;
8289        }
8290
8291        var iFormat, dim, extra,
8292            iValue = 0,
8293            shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
8294            shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8295                new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
8296            dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8297            dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8298            monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8299            monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8300            year = -1,
8301            month = -1,
8302            day = -1,
8303            doy = -1,
8304            literal = false,
8305            date,
8306
8307            // Check whether a format character is doubled
8308            lookAhead = function( match ) {
8309                var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8310                if ( matches ) {
8311                    iFormat++;
8312                }
8313                return matches;
8314            },
8315
8316            // Extract a number from the string value
8317            getNumber = function( match ) {
8318                var isDoubled = lookAhead( match ),
8319                    size = ( match === "@" ? 14 : ( match === "!" ? 20 :
8320                    ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
8321                    minSize = ( match === "y" ? size : 1 ),
8322                    digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
8323                    num = value.substring( iValue ).match( digits );
8324                if ( !num ) {
8325                    throw "Missing number at position " + iValue;
8326                }
8327                iValue += num[ 0 ].length;
8328                return parseInt( num[ 0 ], 10 );
8329            },
8330
8331            // Extract a name from the string value and convert to an index
8332            getName = function( match, shortNames, longNames ) {
8333                var index = -1,
8334                    names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
8335                        return [ [ k, v ] ];
8336                    } ).sort( function( a, b ) {
8337                        return -( a[ 1 ].length - b[ 1 ].length );
8338                    } );
8339
8340                $.each( names, function( i, pair ) {
8341                    var name = pair[ 1 ];
8342                    if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
8343                        index = pair[ 0 ];
8344                        iValue += name.length;
8345                        return false;
8346                    }
8347                } );
8348                if ( index !== -1 ) {
8349                    return index + 1;
8350                } else {
8351                    throw "Unknown name at position " + iValue;
8352                }
8353            },
8354
8355            // Confirm that a literal character matches the string value
8356            checkLiteral = function() {
8357                if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
8358                    throw "Unexpected literal at position " + iValue;
8359                }
8360                iValue++;
8361            };
8362
8363        for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8364            if ( literal ) {
8365                if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8366                    literal = false;
8367                } else {
8368                    checkLiteral();
8369                }
8370            } else {
8371                switch ( format.charAt( iFormat ) ) {
8372                    case "d":
8373                        day = getNumber( "d" );
8374                        break;
8375                    case "D":
8376                        getName( "D", dayNamesShort, dayNames );
8377                        break;
8378                    case "o":
8379                        doy = getNumber( "o" );
8380                        break;
8381                    case "m":
8382                        month = getNumber( "m" );
8383                        break;
8384                    case "M":
8385                        month = getName( "M", monthNamesShort, monthNames );
8386                        break;
8387                    case "y":
8388                        year = getNumber( "y" );
8389                        break;
8390                    case "@":
8391                        date = new Date( getNumber( "@" ) );
8392                        year = date.getFullYear();
8393                        month = date.getMonth() + 1;
8394                        day = date.getDate();
8395                        break;
8396                    case "!":
8397                        date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
8398                        year = date.getFullYear();
8399                        month = date.getMonth() + 1;
8400                        day = date.getDate();
8401                        break;
8402                    case "'":
8403                        if ( lookAhead( "'" ) ) {
8404                            checkLiteral();
8405                        } else {
8406                            literal = true;
8407                        }
8408                        break;
8409                    default:
8410                        checkLiteral();
8411                }
8412            }
8413        }
8414
8415        if ( iValue < value.length ) {
8416            extra = value.substr( iValue );
8417            if ( !/^\s+/.test( extra ) ) {
8418                throw "Extra/unparsed characters found in date: " + extra;
8419            }
8420        }
8421
8422        if ( year === -1 ) {
8423            year = new Date().getFullYear();
8424        } else if ( year < 100 ) {
8425            year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8426                ( year <= shortYearCutoff ? 0 : -100 );
8427        }
8428
8429        if ( doy > -1 ) {
8430            month = 1;
8431            day = doy;
8432            do {
8433                dim = this._getDaysInMonth( year, month - 1 );
8434                if ( day <= dim ) {
8435                    break;
8436                }
8437                month++;
8438                day -= dim;
8439            } while ( true );
8440        }
8441
8442        date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
8443        if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
8444            throw "Invalid date"; // E.g. 31/02/00
8445        }
8446        return date;
8447    },
8448
8449    /* Standard date formats. */
8450    ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8451    COOKIE: "D, dd M yy",
8452    ISO_8601: "yy-mm-dd",
8453    RFC_822: "D, d M y",
8454    RFC_850: "DD, dd-M-y",
8455    RFC_1036: "D, d M y",
8456    RFC_1123: "D, d M yy",
8457    RFC_2822: "D, d M yy",
8458    RSS: "D, d M y", // RFC 822
8459    TICKS: "!",
8460    TIMESTAMP: "@",
8461    W3C: "yy-mm-dd", // ISO 8601
8462
8463    _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
8464        Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
8465
8466    /* Format a date object into a string value.
8467     * The format can be combinations of the following:
8468     * d  - day of month (no leading zero)
8469     * dd - day of month (two digit)
8470     * o  - day of year (no leading zeros)
8471     * oo - day of year (three digit)
8472     * D  - day name short
8473     * DD - day name long
8474     * m  - month of year (no leading zero)
8475     * mm - month of year (two digit)
8476     * M  - month name short
8477     * MM - month name long
8478     * y  - year (two digit)
8479     * yy - year (four digit)
8480     * @ - Unix timestamp (ms since 01/01/1970)
8481     * ! - Windows ticks (100ns since 01/01/0001)
8482     * "..." - literal text
8483     * '' - single quote
8484     *
8485     * @param  format string - the desired format of the date
8486     * @param  date Date - the date value to format
8487     * @param  settings Object - attributes include:
8488     *                  dayNamesShort   string[7] - abbreviated names of the days from Sunday (optional)
8489     *                  dayNames        string[7] - names of the days from Sunday (optional)
8490     *                  monthNamesShort string[12] - abbreviated names of the months (optional)
8491     *                  monthNames      string[12] - names of the months (optional)
8492     * @return  string - the date in the above format
8493     */
8494    formatDate: function( format, date, settings ) {
8495        if ( !date ) {
8496            return "";
8497        }
8498
8499        var iFormat,
8500            dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8501            dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8502            monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8503            monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8504
8505            // Check whether a format character is doubled
8506            lookAhead = function( match ) {
8507                var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8508                if ( matches ) {
8509                    iFormat++;
8510                }
8511                return matches;
8512            },
8513
8514            // Format a number, with leading zero if necessary
8515            formatNumber = function( match, value, len ) {
8516                var num = "" + value;
8517                if ( lookAhead( match ) ) {
8518                    while ( num.length < len ) {
8519                        num = "0" + num;
8520                    }
8521                }
8522                return num;
8523            },
8524
8525            // Format a name, short or long as requested
8526            formatName = function( match, value, shortNames, longNames ) {
8527                return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
8528            },
8529            output = "",
8530            literal = false;
8531
8532        if ( date ) {
8533            for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8534                if ( literal ) {
8535                    if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8536                        literal = false;
8537                    } else {
8538                        output += format.charAt( iFormat );
8539                    }
8540                } else {
8541                    switch ( format.charAt( iFormat ) ) {
8542                        case "d":
8543                            output += formatNumber( "d", date.getDate(), 2 );
8544                            break;
8545                        case "D":
8546                            output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
8547                            break;
8548                        case "o":
8549                            output += formatNumber( "o",
8550                                Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
8551                            break;
8552                        case "m":
8553                            output += formatNumber( "m", date.getMonth() + 1, 2 );
8554                            break;
8555                        case "M":
8556                            output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
8557                            break;
8558                        case "y":
8559                            output += ( lookAhead( "y" ) ? date.getFullYear() :
8560                                ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
8561                            break;
8562                        case "@":
8563                            output += date.getTime();
8564                            break;
8565                        case "!":
8566                            output += date.getTime() * 10000 + this._ticksTo1970;
8567                            break;
8568                        case "'":
8569                            if ( lookAhead( "'" ) ) {
8570                                output += "'";
8571                            } else {
8572                                literal = true;
8573                            }
8574                            break;
8575                        default:
8576                            output += format.charAt( iFormat );
8577                    }
8578                }
8579            }
8580        }
8581        return output;
8582    },
8583
8584    /* Extract all possible characters from the date format. */
8585    _possibleChars: function( format ) {
8586        var iFormat,
8587            chars = "",
8588            literal = false,
8589
8590            // Check whether a format character is doubled
8591            lookAhead = function( match ) {
8592                var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8593                if ( matches ) {
8594                    iFormat++;
8595                }
8596                return matches;
8597            };
8598
8599        for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8600            if ( literal ) {
8601                if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8602                    literal = false;
8603                } else {
8604                    chars += format.charAt( iFormat );
8605                }
8606            } else {
8607                switch ( format.charAt( iFormat ) ) {
8608                    case "d": case "m": case "y": case "@":
8609                        chars += "0123456789";
8610                        break;
8611                    case "D": case "M":
8612                        return null; // Accept anything
8613                    case "'":
8614                        if ( lookAhead( "'" ) ) {
8615                            chars += "'";
8616                        } else {
8617                            literal = true;
8618                        }
8619                        break;
8620                    default:
8621                        chars += format.charAt( iFormat );
8622                }
8623            }
8624        }
8625        return chars;
8626    },
8627
8628    /* Get a setting value, defaulting if necessary. */
8629    _get: function( inst, name ) {
8630        return inst.settings[ name ] !== undefined ?
8631            inst.settings[ name ] : this._defaults[ name ];
8632    },
8633
8634    /* Parse existing date and initialise date picker. */
8635    _setDateFromField: function( inst, noDefault ) {
8636        if ( inst.input.val() === inst.lastVal ) {
8637            return;
8638        }
8639
8640        var dateFormat = this._get( inst, "dateFormat" ),
8641            dates = inst.lastVal = inst.input ? inst.input.val() : null,
8642            defaultDate = this._getDefaultDate( inst ),
8643            date = defaultDate,
8644            settings = this._getFormatConfig( inst );
8645
8646        try {
8647            date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
8648        } catch ( event ) {
8649            dates = ( noDefault ? "" : dates );
8650        }
8651        inst.selectedDay = date.getDate();
8652        inst.drawMonth = inst.selectedMonth = date.getMonth();
8653        inst.drawYear = inst.selectedYear = date.getFullYear();
8654        inst.currentDay = ( dates ? date.getDate() : 0 );
8655        inst.currentMonth = ( dates ? date.getMonth() : 0 );
8656        inst.currentYear = ( dates ? date.getFullYear() : 0 );
8657        this._adjustInstDate( inst );
8658    },
8659
8660    /* Retrieve the default date shown on opening. */
8661    _getDefaultDate: function( inst ) {
8662        return this._restrictMinMax( inst,
8663            this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
8664    },
8665
8666    /* A date may be specified as an exact value or a relative one. */
8667    _determineDate: function( inst, date, defaultDate ) {
8668        var offsetNumeric = function( offset ) {
8669                var date = new Date();
8670                date.setDate( date.getDate() + offset );
8671                return date;
8672            },
8673            offsetString = function( offset ) {
8674                try {
8675                    return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8676                        offset, $.datepicker._getFormatConfig( inst ) );
8677                } catch ( e ) {
8678
8679                    // Ignore
8680                }
8681
8682                var date = ( offset.toLowerCase().match( /^c/ ) ?
8683                    $.datepicker._getDate( inst ) : null ) || new Date(),
8684                    year = date.getFullYear(),
8685                    month = date.getMonth(),
8686                    day = date.getDate(),
8687                    pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8688                    matches = pattern.exec( offset );
8689
8690                while ( matches ) {
8691                    switch ( matches[ 2 ] || "d" ) {
8692                        case "d" : case "D" :
8693                            day += parseInt( matches[ 1 ], 10 ); break;
8694                        case "w" : case "W" :
8695                            day += parseInt( matches[ 1 ], 10 ) * 7; break;
8696                        case "m" : case "M" :
8697                            month += parseInt( matches[ 1 ], 10 );
8698                            day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8699                            break;
8700                        case "y": case "Y" :
8701                            year += parseInt( matches[ 1 ], 10 );
8702                            day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8703                            break;
8704                    }
8705                    matches = pattern.exec( offset );
8706                }
8707                return new Date( year, month, day );
8708            },
8709            newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
8710                ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
8711
8712        newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
8713        if ( newDate ) {
8714            newDate.setHours( 0 );
8715            newDate.setMinutes( 0 );
8716            newDate.setSeconds( 0 );
8717            newDate.setMilliseconds( 0 );
8718        }
8719        return this._daylightSavingAdjust( newDate );
8720    },
8721
8722    /* Handle switch to/from daylight saving.
8723     * Hours may be non-zero on daylight saving cut-over:
8724     * > 12 when midnight changeover, but then cannot generate
8725     * midnight datetime, so jump to 1AM, otherwise reset.
8726     * @param  date  (Date) the date to check
8727     * @return  (Date) the corrected date
8728     */
8729    _daylightSavingAdjust: function( date ) {
8730        if ( !date ) {
8731            return null;
8732        }
8733        date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
8734        return date;
8735    },
8736
8737    /* Set the date(s) directly. */
8738    _setDate: function( inst, date, noChange ) {
8739        var clear = !date,
8740            origMonth = inst.selectedMonth,
8741            origYear = inst.selectedYear,
8742            newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
8743
8744        inst.selectedDay = inst.currentDay = newDate.getDate();
8745        inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8746        inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8747        if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
8748            this._notifyChange( inst );
8749        }
8750        this._adjustInstDate( inst );
8751        if ( inst.input ) {
8752            inst.input.val( clear ? "" : this._formatDate( inst ) );
8753        }
8754    },
8755
8756    /* Retrieve the date(s) directly. */
8757    _getDate: function( inst ) {
8758        var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
8759            this._daylightSavingAdjust( new Date(
8760            inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
8761            return startDate;
8762    },
8763
8764    /* Attach the onxxx handlers.  These are declared statically so
8765     * they work with static code transformers like Caja.
8766     */
8767    _attachHandlers: function( inst ) {
8768        var stepMonths = this._get( inst, "stepMonths" ),
8769            id = "#" + inst.id.replace( /\\\\/g, "\\" );
8770        inst.dpDiv.find( "[data-handler]" ).map( function() {
8771            var handler = {
8772                prev: function() {
8773                    $.datepicker._adjustDate( id, -stepMonths, "M" );
8774                },
8775                next: function() {
8776                    $.datepicker._adjustDate( id, +stepMonths, "M" );
8777                },
8778                hide: function() {
8779                    $.datepicker._hideDatepicker();
8780                },
8781                today: function() {
8782                    $.datepicker._gotoToday( id );
8783                },
8784                selectDay: function() {
8785                    $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
8786                    return false;
8787                },
8788                selectMonth: function() {
8789                    $.datepicker._selectMonthYear( id, this, "M" );
8790                    return false;
8791                },
8792                selectYear: function() {
8793                    $.datepicker._selectMonthYear( id, this, "Y" );
8794                    return false;
8795                }
8796            };
8797            $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
8798        } );
8799    },
8800
8801    /* Generate the HTML for the current state of the date picker. */
8802    _generateHTML: function( inst ) {
8803        var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8804            controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8805            monthNames, monthNamesShort, isHoliday, isHolidaySelectable, beforeShowDay, showOtherMonths,
8806            selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8807            cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8808            printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8809            tempDate = new Date(),
8810            today = this._daylightSavingAdjust(
8811                new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
8812            isRTL = this._get( inst, "isRTL" ),
8813            showButtonPanel = this._get( inst, "showButtonPanel" ),
8814            hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
8815            navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
8816            numMonths = this._getNumberOfMonths( inst ),
8817            showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
8818            stepMonths = this._get( inst, "stepMonths" ),
8819            isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
8820            currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
8821                new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
8822            minDate = this._getMinMaxDate( inst, "min" ),
8823            maxDate = this._getMinMaxDate( inst, "max" ),
8824            drawMonth = inst.drawMonth - showCurrentAtPos,
8825            drawYear = inst.drawYear;
8826
8827        if ( drawMonth < 0 ) {
8828            drawMonth += 12;
8829            drawYear--;
8830        }
8831        if ( maxDate ) {
8832            maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
8833                maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
8834            maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
8835            while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
8836                drawMonth--;
8837                if ( drawMonth < 0 ) {
8838                    drawMonth = 11;
8839                    drawYear--;
8840                }
8841            }
8842        }
8843        inst.drawMonth = drawMonth;
8844        inst.drawYear = drawYear;
8845
8846        prevText = this._get( inst, "prevText" );
8847        prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
8848            this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
8849            this._getFormatConfig( inst ) ) );
8850
8851        if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
8852            prev = $( "<a>" )
8853                .attr( {
8854                    "href": "#none",
8855                    "class": "ui-datepicker-prev ui-corner-all",
8856                    "data-handler": "prev",
8857                    "data-event": "click",
8858                    title: prevText
8859                } )
8860                .append(
8861                    $( "<span>" )
8862                        .addClass( "ui-icon ui-icon-circle-triangle-" +
8863                            ( isRTL ? "e" : "w" ) )
8864                        .text( prevText )
8865                )[ 0 ].outerHTML;
8866        } else if ( hideIfNoPrevNext ) {
8867            prev = "";
8868        } else {
8869            prev = $( "<a>" )
8870                .attr( {
8871                    "class": "ui-datepicker-prev ui-corner-all ui-state-disabled",
8872                    title: prevText
8873                } )
8874                .append(
8875                    $( "<span>" )
8876                        .addClass( "ui-icon ui-icon-circle-triangle-" +
8877                            ( isRTL ? "e" : "w" ) )
8878                        .text( prevText )
8879                )[ 0 ].outerHTML;
8880        }
8881
8882        nextText = this._get( inst, "nextText" );
8883        nextText = ( !navigationAsDateFormat ? nextText : this.formatDate( nextText,
8884            this._daylightSavingAdjust( new Date( drawYear, drawMonth + stepMonths, 1 ) ),
8885            this._getFormatConfig( inst ) ) );
8886
8887        if ( this._canAdjustMonth( inst, +1, drawYear, drawMonth ) ) {
8888            next = $( "<a>" )
8889                .attr( {
8890                    "href": "#none",
8891                    "class": "ui-datepicker-next ui-corner-all",
8892                    "data-handler": "next",
8893                    "data-event": "click",
8894                    title: nextText
8895                } )
8896                .append(
8897                    $( "<span>" )
8898                        .addClass( "ui-icon ui-icon-circle-triangle-" +
8899                            ( isRTL ? "w" : "e" ) )
8900                        .text( nextText )
8901                )[ 0 ].outerHTML;
8902        } else if ( hideIfNoPrevNext ) {
8903            next = "";
8904        } else {
8905            next = $( "<a>" )
8906                .attr( {
8907                    "class": "ui-datepicker-next ui-corner-all ui-state-disabled",
8908                    title: nextText
8909                } )
8910                .append(
8911                    $( "<span>" )
8912                        .attr( "class", "ui-icon ui-icon-circle-triangle-" +
8913                            ( isRTL ? "w" : "e" ) )
8914                        .text( nextText )
8915                )[ 0 ].outerHTML;
8916        }
8917
8918        currentText = this._get( inst, "currentText" );
8919        gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
8920        currentText = ( !navigationAsDateFormat ? currentText :
8921            this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
8922
8923        controls = "";
8924        if ( !inst.inline ) {
8925            controls = $( "<button>" )
8926                .attr( {
8927                    type: "button",
8928                    "class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
8929                    "data-handler": "hide",
8930                    "data-event": "click"
8931                } )
8932                .text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
8933        }
8934
8935        buttonPanel = "";
8936        if ( showButtonPanel ) {
8937            buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
8938                .append( isRTL ? controls : "" )
8939                .append( this._isInRange( inst, gotoDate ) ?
8940                    $( "<button>" )
8941                        .attr( {
8942                            type: "button",
8943                            "class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
8944                            "data-handler": "today",
8945                            "data-event": "click"
8946                        } )
8947                        .text( currentText ) :
8948                    "" )
8949                .append( isRTL ? "" : controls )[ 0 ].outerHTML;
8950        }
8951
8952        firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
8953        firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
8954
8955        showWeek = this._get( inst, "showWeek" );
8956        dayNames = this._get( inst, "dayNames" );
8957        dayNamesMin = this._get( inst, "dayNamesMin" );
8958        monthNames = this._get( inst, "monthNames" );
8959        monthNamesShort = this._get( inst, "monthNamesShort" );
8960        isHoliday = this._get(inst, "isHoliday");
8961        beforeShowDay = this._get( inst, "beforeShowDay" );
8962        showOtherMonths = this._get( inst, "showOtherMonths" );
8963        selectOtherMonths = this._get( inst, "selectOtherMonths" );
8964        defaultDate = this._getDefaultDate( inst );
8965        html = "";
8966
8967        for ( row = 0; row < numMonths[ 0 ]; row++ ) {
8968            group = "";
8969            this.maxRows = 4;
8970            for ( col = 0; col < numMonths[ 1 ]; col++ ) {
8971                selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
8972                cornerClass = " ui-corner-all";
8973                calender = "";
8974                if ( isMultiMonth ) {
8975                    calender += "<div class='ui-datepicker-group";
8976                    if ( numMonths[ 1 ] > 1 ) {
8977                        switch ( col ) {
8978                            case 0: calender += " ui-datepicker-group-first";
8979                                cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
8980                            case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
8981                                cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
8982                            default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
8983                        }
8984                    }
8985                    calender += "'>";
8986                }
8987                calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
8988                    ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
8989                    ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
8990                    this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
8991                    row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
8992                    "</div><table class='ui-datepicker-calendar' summay='관람일을 선택 할 수 있는 달력입니다.'><caption class='hide'>관람일선택</caption><thead>" +
8993                    "<tr>";
8994                thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
8995                for ( dow = 0; dow < 7; dow++ ) { // days of the week
8996                    day = ( dow + firstDay ) % 7;
8997                    thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
8998                        "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
8999                }
9000                calender += thead + "</tr></thead><tbody>";
9001                daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
9002                if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
9003                    inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
9004                }
9005                leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
9006                curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
9007                numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
9008                this.maxRows = numRows;
9009                printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
9010                for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
9011                    calender += "<tr>";
9012                    tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9013                        this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
9014                    for ( dow = 0; dow < 7; dow++ ) { // create date picker days
9015                        daySettings = ( beforeShowDay ?
9016                            beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
9017                        isHolidayValid = (isHoliday ?
9018                                isHoliday.apply((inst.input ? inst.input[0] : null), [printDate]) : [true, ""]);
9019                        isHolidaySelectable = !isHolidayValid[0] ;
9020
9021                        otherMonth = ( printDate.getMonth() !== drawMonth );
9022                        unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
9023                            ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
9024                        tbody += "<td class='" +
9025                            ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
9026                            ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
9027                            ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
9028                            ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
9029
9030                            // or defaultDate is current printedDate and defaultDate is selectedDate
9031                            " " + this._dayOverClass : "" ) + // highlight selected day
9032                            ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
9033                            ( isHolidaySelectable ? " holiday ": " " ) +  // add class for displaying holidays
9034                            ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
9035                            ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
9036                            ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
9037                            ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
9038                            ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
9039                            ( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
9040                            ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9041                            ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
9042                            ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
9043                            ( printDate.getTime() === currentDate.getTime() ? "' title='선택일" : "" ) + // introduce selected day
9044                            ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
9045                            "' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
9046                            "' data-date='" + printDate.getDate() + // store date as data
9047                            "'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
9048                        printDate.setDate( printDate.getDate() + 1 );
9049                        printDate = this._daylightSavingAdjust( printDate );
9050                    }
9051                    calender += tbody + "</tr>";
9052                }
9053                drawMonth++;
9054                if ( drawMonth > 11 ) {
9055                    drawMonth = 0;
9056                    drawYear++;
9057                }
9058                calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
9059                            ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
9060                group += calender;
9061            }
9062            html += group;
9063        }
9064        html += buttonPanel;
9065        inst._keyEvent = false;
9066        return html;
9067    },
9068
9069    /* Generate the month and year header. */
9070    _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
9071            secondary, monthNames, monthNamesShort ) {
9072
9073        var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9074            changeMonth = this._get( inst, "changeMonth" ),
9075            changeYear = this._get( inst, "changeYear" ),
9076            showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
9077            selectMonthLabel = this._get( inst, "selectMonthLabel" ),
9078            selectYearLabel = this._get( inst, "selectYearLabel" ),
9079            html = "<div class='ui-datepicker-title'>",
9080            monthHtml = "";
9081
9082        // Month selection
9083        if ( secondary || !changeMonth ) {
9084            monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
9085        } else {
9086            inMinYear = ( minDate && minDate.getFullYear() === drawYear );
9087            inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
9088            monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
9089            for ( month = 0; month < 12; month++ ) {
9090                if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
9091                    monthHtml += "<option value='" + month + "'" +
9092                        ( month === drawMonth ? " selected='selected'" : "" ) +
9093                        ">" + monthNamesShort[ month ] + "</option>";
9094                }
9095            }
9096            monthHtml += "</select>";
9097        }
9098
9099        if ( !showMonthAfterYear ) {
9100            html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
9101        }
9102
9103        // Year selection
9104        if ( !inst.yearshtml ) {
9105            inst.yearshtml = "";
9106            if ( secondary || !changeYear ) {
9107                html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9108            } else {
9109
9110                // determine range of years to display
9111                years = this._get( inst, "yearRange" ).split( ":" );
9112                thisYear = new Date().getFullYear();
9113                determineYear = function( value ) {
9114                    var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
9115                        ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
9116                        parseInt( value, 10 ) ) );
9117                    return ( isNaN( year ) ? thisYear : year );
9118                };
9119                year = determineYear( years[ 0 ] );
9120                endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
9121                year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
9122                endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
9123                inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
9124                for ( ; year <= endYear; year++ ) {
9125                    inst.yearshtml += "<option value='" + year + "'" +
9126                        ( year === drawYear ? " selected='selected'" : "" ) +
9127                        ">" + year + "</option>";
9128                }
9129                inst.yearshtml += "</select>";
9130
9131                html += inst.yearshtml;
9132                inst.yearshtml = null;
9133            }
9134        }
9135
9136        html += this._get( inst, "yearSuffix" );
9137        if ( showMonthAfterYear ) {
9138            html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
9139        }
9140        html += "</div>"; // Close datepicker_header
9141        return html;
9142    },
9143
9144    /* Adjust one of the date sub-fields. */
9145    _adjustInstDate: function( inst, offset, period ) {
9146        var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
9147            month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
9148            day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
9149            date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
9150
9151        inst.selectedDay = date.getDate();
9152        inst.drawMonth = inst.selectedMonth = date.getMonth();
9153        inst.drawYear = inst.selectedYear = date.getFullYear();
9154        if ( period === "M" || period === "Y" ) {
9155            this._notifyChange( inst );
9156        }
9157    },
9158
9159    /* Ensure a date is within any min/max bounds. */
9160    _restrictMinMax: function( inst, date ) {
9161        var minDate = this._getMinMaxDate( inst, "min" ),
9162            maxDate = this._getMinMaxDate( inst, "max" ),
9163            newDate = ( minDate && date < minDate ? minDate : date );
9164        return ( maxDate && newDate > maxDate ? maxDate : newDate );
9165    },
9166
9167    /* Notify change of month/year. */
9168    _notifyChange: function( inst ) {
9169        var onChange = this._get( inst, "onChangeMonthYear" );
9170        if ( onChange ) {
9171            onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
9172                [ inst.selectedYear, inst.selectedMonth + 1, inst ] );
9173        }
9174    },
9175
9176    /* Determine the number of months to show. */
9177    _getNumberOfMonths: function( inst ) {
9178        var numMonths = this._get( inst, "numberOfMonths" );
9179        return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
9180    },
9181
9182    /* Determine the current maximum date - ensure no time components are set. */
9183    _getMinMaxDate: function( inst, minMax ) {
9184        return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
9185    },
9186
9187    /* Find the number of days in a given month. */
9188    _getDaysInMonth: function( year, month ) {
9189        return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
9190    },
9191
9192    /* Find the day of the week of the first of a month. */
9193    _getFirstDayOfMonth: function( year, month ) {
9194        return new Date( year, month, 1 ).getDay();
9195    },
9196
9197    /* Determines if we should allow a "next/prev" month display change. */
9198    _canAdjustMonth: function( inst, offset, curYear, curMonth ) {
9199        var numMonths = this._getNumberOfMonths( inst ),
9200            date = this._daylightSavingAdjust( new Date( curYear,
9201            curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
9202
9203        if ( offset < 0 ) {
9204            date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
9205        }
9206        return this._isInRange( inst, date );
9207    },
9208
9209    /* Is the given date in the accepted range? */
9210    _isInRange: function( inst, date ) {
9211        var yearSplit, currentYear,
9212            minDate = this._getMinMaxDate( inst, "min" ),
9213            maxDate = this._getMinMaxDate( inst, "max" ),
9214            minYear = null,
9215            maxYear = null,
9216            years = this._get( inst, "yearRange" );
9217            if ( years ) {
9218                yearSplit = years.split( ":" );
9219                currentYear = new Date().getFullYear();
9220                minYear = parseInt( yearSplit[ 0 ], 10 );
9221                maxYear = parseInt( yearSplit[ 1 ], 10 );
9222                if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
9223                    minYear += currentYear;
9224                }
9225                if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
9226                    maxYear += currentYear;
9227                }
9228            }
9229
9230        return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
9231            ( !maxDate || date.getTime() <= maxDate.getTime() ) &&
9232            ( !minYear || date.getFullYear() >= minYear ) &&
9233            ( !maxYear || date.getFullYear() <= maxYear ) );
9234    },
9235
9236    /* Provide the configuration settings for formatting/parsing. */
9237    _getFormatConfig: function( inst ) {
9238        var shortYearCutoff = this._get( inst, "shortYearCutoff" );
9239        shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
9240            new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
9241        return { shortYearCutoff: shortYearCutoff,
9242            dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
9243            monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
9244    },
9245
9246    /* Format the given date for display. */
9247    _formatDate: function( inst, day, month, year ) {
9248        if ( !day ) {
9249            inst.currentDay = inst.selectedDay;
9250            inst.currentMonth = inst.selectedMonth;
9251            inst.currentYear = inst.selectedYear;
9252        }
9253        var date = ( day ? ( typeof day === "object" ? day :
9254            this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
9255            this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
9256        return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
9257    }
9258} );
9259
9260/*
9261 * Bind hover events for datepicker elements.
9262 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9263 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9264 */
9265function datepicker_bindHover( dpDiv ) {
9266    var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9267    return dpDiv.on( "mouseout", selector, function() {
9268            $( this ).removeClass( "ui-state-hover" );
9269            if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9270                $( this ).removeClass( "ui-datepicker-prev-hover" );
9271            }
9272            if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9273                $( this ).removeClass( "ui-datepicker-next-hover" );
9274            }
9275        } )
9276        .on( "mouseover", selector, datepicker_handleMouseover );
9277}
9278
9279function datepicker_handleMouseover() {
9280    if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
9281        $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
9282        $( this ).addClass( "ui-state-hover" );
9283        if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9284            $( this ).addClass( "ui-datepicker-prev-hover" );
9285        }
9286        if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9287            $( this ).addClass( "ui-datepicker-next-hover" );
9288        }
9289    }
9290}
9291
9292/* jQuery extend now ignores nulls! */
9293function datepicker_extendRemove( target, props ) {
9294    $.extend( target, props );
9295    for ( var name in props ) {
9296        if ( props[ name ] == null ) {
9297            target[ name ] = props[ name ];
9298        }
9299    }
9300    return target;
9301}
9302
9303/* Invoke the datepicker functionality.
9304   @param  options  string - a command, optionally followed by additional parameters or
9305                    Object - settings for attaching new datepicker functionality
9306   @return  jQuery object */
9307$.fn.datepicker = function( options ) {
9308
9309    /* Verify an empty collection wasn't passed - Fixes #6976 */
9310    if ( !this.length ) {
9311        return this;
9312    }
9313
9314    /* Initialise the date picker. */
9315    if ( !$.datepicker.initialized ) {
9316        $( document ).on( "mousedown", $.datepicker._checkExternalClick );
9317        $.datepicker.initialized = true;
9318    }
9319
9320    /* Append datepicker main container to body if not exist. */
9321    if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
9322        $( "body" ).append( $.datepicker.dpDiv );
9323    }
9324
9325    var otherArgs = Array.prototype.slice.call( arguments, 1 );
9326    if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
9327        return $.datepicker[ "_" + options + "Datepicker" ].
9328            apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9329    }
9330    if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
9331        return $.datepicker[ "_" + options + "Datepicker" ].
9332            apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9333    }
9334    return this.each( function() {
9335        if ( typeof options === "string" ) {
9336            $.datepicker[ "_" + options + "Datepicker" ]
9337                .apply( $.datepicker, [ this ].concat( otherArgs ) );
9338        } else {
9339            $.datepicker._attachDatepicker( this, options );
9340        }
9341    } );
9342};
9343
9344$.datepicker = new Datepicker(); // singleton instance
9345$.datepicker.initialized = false;
9346$.datepicker.uuid = new Date().getTime();
9347$.datepicker.version = "1.14.1";
9348
9349var widgetsDatepicker = $.datepicker;
9350
9351
9352/*!
9353 * jQuery UI Mouse 1.14.1
9354 * https://jqueryui.com
9355 *
9356 * Copyright OpenJS Foundation and other contributors
9357 * Released under the MIT license.
9358 * https://jquery.org/license
9359 */
9360
9361//>>label: Mouse
9362//>>group: Widgets
9363//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
9364//>>docs: https://api.jqueryui.com/mouse/
9365
9366
9367var mouseHandled = false;
9368$( document ).on( "mouseup", function() {
9369    mouseHandled = false;
9370} );
9371
9372var widgetsMouse = $.widget( "ui.mouse", {
9373    version: "1.14.1",
9374    options: {
9375        cancel: "input, textarea, button, select, option",
9376        distance: 1,
9377        delay: 0
9378    },
9379    _mouseInit: function() {
9380        var that = this;
9381
9382        this.element
9383            .on( "mousedown." + this.widgetName, function( event ) {
9384                return that._mouseDown( event );
9385            } )
9386            .on( "click." + this.widgetName, function( event ) {
9387                if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
9388                    $.removeData( event.target, that.widgetName + ".preventClickEvent" );
9389                    event.stopImmediatePropagation();
9390                    return false;
9391                }
9392            } );
9393
9394        this.started = false;
9395    },
9396
9397    // TODO: make sure destroying one instance of mouse doesn't mess with
9398    // other instances of mouse
9399    _mouseDestroy: function() {
9400        this.element.off( "." + this.widgetName );
9401        if ( this._mouseMoveDelegate ) {
9402            this.document
9403                .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9404                .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9405        }
9406    },
9407
9408    _mouseDown: function( event ) {
9409
9410        // don't let more than one widget handle mouseStart
9411        if ( mouseHandled ) {
9412            return;
9413        }
9414
9415        this._mouseMoved = false;
9416
9417        // We may have missed mouseup (out of window)
9418        if ( this._mouseStarted ) {
9419            this._mouseUp( event );
9420        }
9421
9422        this._mouseDownEvent = event;
9423
9424        var that = this,
9425            btnIsLeft = event.which === 1,
9426            elIsCancel = typeof this.options.cancel === "string" ?
9427                $( event.target ).closest( this.options.cancel ).length :
9428                false;
9429        if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
9430            return true;
9431        }
9432
9433        this.mouseDelayMet = !this.options.delay;
9434        if ( !this.mouseDelayMet ) {
9435            this._mouseDelayTimer = setTimeout( function() {
9436                that.mouseDelayMet = true;
9437            }, this.options.delay );
9438        }
9439
9440        if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9441            this._mouseStarted = ( this._mouseStart( event ) !== false );
9442            if ( !this._mouseStarted ) {
9443                event.preventDefault();
9444                return true;
9445            }
9446        }
9447
9448        // Click event may never have fired (Gecko & Opera)
9449        if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
9450            $.removeData( event.target, this.widgetName + ".preventClickEvent" );
9451        }
9452
9453        // These delegates are required to keep context
9454        this._mouseMoveDelegate = function( event ) {
9455            return that._mouseMove( event );
9456        };
9457        this._mouseUpDelegate = function( event ) {
9458            return that._mouseUp( event );
9459        };
9460
9461        this.document
9462            .on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9463            .on( "mouseup." + this.widgetName, this._mouseUpDelegate );
9464
9465        event.preventDefault();
9466
9467        mouseHandled = true;
9468        return true;
9469    },
9470
9471    _mouseMove: function( event ) {
9472
9473        // Only check for mouseups outside the document if you've moved inside the document
9474        // at least once.
9475        if ( this._mouseMoved && !event.which ) {
9476
9477            // Support: Safari <=8 - 9
9478            // Safari sets which to 0 if you press any of the following keys
9479            // during a drag (#14461)
9480            if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
9481                    event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
9482                this.ignoreMissingWhich = true;
9483            } else if ( !this.ignoreMissingWhich ) {
9484                return this._mouseUp( event );
9485            }
9486        }
9487
9488        if ( event.which || event.button ) {
9489            this._mouseMoved = true;
9490        }
9491
9492        if ( this._mouseStarted ) {
9493            this._mouseDrag( event );
9494            return event.preventDefault();
9495        }
9496
9497        if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9498            this._mouseStarted =
9499                ( this._mouseStart( this._mouseDownEvent, event ) !== false );
9500            if ( this._mouseStarted ) {
9501                this._mouseDrag( event );
9502            } else {
9503                this._mouseUp( event );
9504            }
9505        }
9506
9507        return !this._mouseStarted;
9508    },
9509
9510    _mouseUp: function( event ) {
9511        this.document
9512            .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9513            .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9514
9515        if ( this._mouseStarted ) {
9516            this._mouseStarted = false;
9517
9518            if ( event.target === this._mouseDownEvent.target ) {
9519                $.data( event.target, this.widgetName + ".preventClickEvent", true );
9520            }
9521
9522            this._mouseStop( event );
9523        }
9524
9525        if ( this._mouseDelayTimer ) {
9526            clearTimeout( this._mouseDelayTimer );
9527            delete this._mouseDelayTimer;
9528        }
9529
9530        this.ignoreMissingWhich = false;
9531        mouseHandled = false;
9532        event.preventDefault();
9533    },
9534
9535    _mouseDistanceMet: function( event ) {
9536        return ( Math.max(
9537                Math.abs( this._mouseDownEvent.pageX - event.pageX ),
9538                Math.abs( this._mouseDownEvent.pageY - event.pageY )
9539            ) >= this.options.distance
9540        );
9541    },
9542
9543    _mouseDelayMet: function( /* event */ ) {
9544        return this.mouseDelayMet;
9545    },
9546
9547    // These are placeholder methods, to be overriden by extending plugin
9548    _mouseStart: function( /* event */ ) {},
9549    _mouseDrag: function( /* event */ ) {},
9550    _mouseStop: function( /* event */ ) {},
9551    _mouseCapture: function( /* event */ ) {
9552        return true;
9553    }
9554} );
9555
9556
9557
9558// $.ui.plugin is deprecated. Use $.widget() extensions instead.
9559var plugin = $.ui.plugin = {
9560    add: function( module, option, set ) {
9561        var i,
9562            proto = $.ui[ module ].prototype;
9563        for ( i in set ) {
9564            proto.plugins[ i ] = proto.plugins[ i ] || [];
9565            proto.plugins[ i ].push( [ option, set[ i ] ] );
9566        }
9567    },
9568    call: function( instance, name, args, allowDisconnected ) {
9569        var i,
9570            set = instance.plugins[ name ];
9571
9572        if ( !set ) {
9573            return;
9574        }
9575
9576        if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
9577                instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
9578            return;
9579        }
9580
9581        for ( i = 0; i < set.length; i++ ) {
9582            if ( instance.options[ set[ i ][ 0 ] ] ) {
9583                set[ i ][ 1 ].apply( instance.element, args );
9584            }
9585        }
9586    }
9587};
9588
9589
9590/*!
9591 * jQuery UI Draggable 1.14.1
9592 * https://jqueryui.com
9593 *
9594 * Copyright OpenJS Foundation and other contributors
9595 * Released under the MIT license.
9596 * https://jquery.org/license
9597 */
9598
9599//>>label: Draggable
9600//>>group: Interactions
9601//>>description: Enables dragging functionality for any element.
9602//>>docs: https://api.jqueryui.com/draggable/
9603//>>demos: https://jqueryui.com/draggable/
9604//>>css.structure: ../../themes/base/draggable.css
9605
9606
9607$.widget( "ui.draggable", $.ui.mouse, {
9608    version: "1.14.1",
9609    widgetEventPrefix: "drag",
9610    options: {
9611        addClasses: true,
9612        appendTo: "parent",
9613        axis: false,
9614        connectToSortable: false,
9615        containment: false,
9616        cursor: "auto",
9617        cursorAt: false,
9618        grid: false,
9619        handle: false,
9620        helper: "original",
9621        iframeFix: false,
9622        opacity: false,
9623        refreshPositions: false,
9624        revert: false,
9625        revertDuration: 500,
9626        scope: "default",
9627        scroll: true,
9628        scrollSensitivity: 20,
9629        scrollSpeed: 20,
9630        snap: false,
9631        snapMode: "both",
9632        snapTolerance: 20,
9633        stack: false,
9634        zIndex: false,
9635
9636        // Callbacks
9637        drag: null,
9638        start: null,
9639        stop: null
9640    },
9641    _create: function() {
9642
9643        if ( this.options.helper === "original" ) {
9644            this._setPositionRelative();
9645        }
9646        if ( this.options.addClasses ) {
9647            this._addClass( "ui-draggable" );
9648        }
9649        this._setHandleClassName();
9650
9651        this._mouseInit();
9652    },
9653
9654    _setOption: function( key, value ) {
9655        this._super( key, value );
9656        if ( key === "handle" ) {
9657            this._removeHandleClassName();
9658            this._setHandleClassName();
9659        }
9660    },
9661
9662    _destroy: function() {
9663        if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
9664            this.destroyOnClear = true;
9665            return;
9666        }
9667        this._removeHandleClassName();
9668        this._mouseDestroy();
9669    },
9670
9671    _mouseCapture: function( event ) {
9672        var o = this.options;
9673
9674        // Among others, prevent a drag on a resizable-handle
9675        if ( this.helper || o.disabled ||
9676                $( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
9677            return false;
9678        }
9679
9680        //Quit if we're not on a valid handle
9681        this.handle = this._getHandle( event );
9682        if ( !this.handle ) {
9683            return false;
9684        }
9685
9686        this._blurActiveElement( event );
9687
9688        this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
9689
9690        return true;
9691
9692    },
9693
9694    _blockFrames: function( selector ) {
9695        this.iframeBlocks = this.document.find( selector ).map( function() {
9696            var iframe = $( this );
9697
9698            return $( "<div>" )
9699                .css( "position", "absolute" )
9700                .appendTo( iframe.parent() )
9701                .outerWidth( iframe.outerWidth() )
9702                .outerHeight( iframe.outerHeight() )
9703                .offset( iframe.offset() )[ 0 ];
9704        } );
9705    },
9706
9707    _unblockFrames: function() {
9708        if ( this.iframeBlocks ) {
9709            this.iframeBlocks.remove();
9710            delete this.iframeBlocks;
9711        }
9712    },
9713
9714    _blurActiveElement: function( event ) {
9715        var activeElement = this.document[ 0 ].activeElement,
9716            target = $( event.target );
9717
9718        // Don't blur if the event occurred on an element that is within
9719        // the currently focused element
9720        // See #10527, #12472
9721        if ( target.closest( activeElement ).length ) {
9722            return;
9723        }
9724
9725        // Blur any element that currently has focus, see #4261
9726        $( activeElement ).trigger( "blur" );
9727    },
9728
9729    _mouseStart: function( event ) {
9730
9731        var o = this.options;
9732
9733        //Create and append the visible helper
9734        this.helper = this._createHelper( event );
9735
9736        this._addClass( this.helper, "ui-draggable-dragging" );
9737
9738        //Cache the helper size
9739        this._cacheHelperProportions();
9740
9741        //If ddmanager is used for droppables, set the global draggable
9742        if ( $.ui.ddmanager ) {
9743            $.ui.ddmanager.current = this;
9744        }
9745
9746        /*
9747         * - Position generation -
9748         * This block generates everything position related - it's the core of draggables.
9749         */
9750
9751        //Cache the margins of the original element
9752        this._cacheMargins();
9753
9754        //Store the helper's css position
9755        this.cssPosition = this.helper.css( "position" );
9756        this.scrollParent = this.helper.scrollParent( true );
9757        this.offsetParent = this.helper.offsetParent();
9758        this.hasFixedAncestor = this.helper.parents().filter( function() {
9759                return $( this ).css( "position" ) === "fixed";
9760            } ).length > 0;
9761
9762        //The element's absolute position on the page minus margins
9763        this.positionAbs = this.element.offset();
9764        this._refreshOffsets( event );
9765
9766        //Generate the original position
9767        this.originalPosition = this.position = this._generatePosition( event, false );
9768        this.originalPageX = event.pageX;
9769        this.originalPageY = event.pageY;
9770
9771        //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
9772        if ( o.cursorAt ) {
9773            this._adjustOffsetFromHelper( o.cursorAt );
9774        }
9775
9776        //Set a containment if given in the options
9777        this._setContainment();
9778
9779        //Trigger event + callbacks
9780        if ( this._trigger( "start", event ) === false ) {
9781            this._clear();
9782            return false;
9783        }
9784
9785        //Recache the helper size
9786        this._cacheHelperProportions();
9787
9788        //Prepare the droppable offsets
9789        if ( $.ui.ddmanager && !o.dropBehaviour ) {
9790            $.ui.ddmanager.prepareOffsets( this, event );
9791        }
9792
9793        // Execute the drag once - this causes the helper not to be visible before getting its
9794        // correct position
9795        this._mouseDrag( event, true );
9796
9797        // If the ddmanager is used for droppables, inform the manager that dragging has started
9798        // (see #5003)
9799        if ( $.ui.ddmanager ) {
9800            $.ui.ddmanager.dragStart( this, event );
9801        }
9802
9803        return true;
9804    },
9805
9806    _refreshOffsets: function( event ) {
9807        this.offset = {
9808            top: this.positionAbs.top - this.margins.top,
9809            left: this.positionAbs.left - this.margins.left,
9810            scroll: false,
9811            parent: this._getParentOffset(),
9812            relative: this._getRelativeOffset()
9813        };
9814
9815        this.offset.click = {
9816            left: event.pageX - this.offset.left,
9817            top: event.pageY - this.offset.top
9818        };
9819    },
9820
9821    _mouseDrag: function( event, noPropagation ) {
9822
9823        // reset any necessary cached properties (see #5009)
9824        if ( this.hasFixedAncestor ) {
9825            this.offset.parent = this._getParentOffset();
9826        }
9827
9828        //Compute the helpers position
9829        this.position = this._generatePosition( event, true );
9830        this.positionAbs = this._convertPositionTo( "absolute" );
9831
9832        //Call plugins and callbacks and use the resulting position if something is returned
9833        if ( !noPropagation ) {
9834            var ui = this._uiHash();
9835            if ( this._trigger( "drag", event, ui ) === false ) {
9836                this._mouseUp( new $.Event( "mouseup", event ) );
9837                return false;
9838            }
9839            this.position = ui.position;
9840        }
9841
9842        this.helper[ 0 ].style.left = this.position.left + "px";
9843        this.helper[ 0 ].style.top = this.position.top + "px";
9844
9845        if ( $.ui.ddmanager ) {
9846            $.ui.ddmanager.drag( this, event );
9847        }
9848
9849        return false;
9850    },
9851
9852    _mouseStop: function( event ) {
9853
9854        //If we are using droppables, inform the manager about the drop
9855        var that = this,
9856            dropped = false;
9857        if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
9858            dropped = $.ui.ddmanager.drop( this, event );
9859        }
9860
9861        //if a drop comes from outside (a sortable)
9862        if ( this.dropped ) {
9863            dropped = this.dropped;
9864            this.dropped = false;
9865        }
9866
9867        if ( ( this.options.revert === "invalid" && !dropped ) ||
9868                ( this.options.revert === "valid" && dropped ) ||
9869                this.options.revert === true || ( typeof this.options.revert === "function" &&
9870                this.options.revert.call( this.element, dropped ) )
9871        ) {
9872            $( this.helper ).animate(
9873                this.originalPosition,
9874                parseInt( this.options.revertDuration, 10 ),
9875                function() {
9876                    if ( that._trigger( "stop", event ) !== false ) {
9877                        that._clear();
9878                    }
9879                }
9880            );
9881        } else {
9882            if ( this._trigger( "stop", event ) !== false ) {
9883                this._clear();
9884            }
9885        }
9886
9887        return false;
9888    },
9889
9890    _mouseUp: function( event ) {
9891        this._unblockFrames();
9892
9893        // If the ddmanager is used for droppables, inform the manager that dragging has stopped
9894        // (see #5003)
9895        if ( $.ui.ddmanager ) {
9896            $.ui.ddmanager.dragStop( this, event );
9897        }
9898
9899        // Only need to focus if the event occurred on the draggable itself, see #10527
9900        if ( this.handleElement.is( event.target ) ) {
9901
9902            // The interaction is over; whether or not the click resulted in a drag,
9903            // focus the element
9904            this.element.trigger( "focus" );
9905        }
9906
9907        return $.ui.mouse.prototype._mouseUp.call( this, event );
9908    },
9909
9910    cancel: function() {
9911
9912        if ( this.helper.is( ".ui-draggable-dragging" ) ) {
9913            this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
9914        } else {
9915            this._clear();
9916        }
9917
9918        return this;
9919
9920    },
9921
9922    _getHandle: function( event ) {
9923        return this.options.handle ?
9924            !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
9925            true;
9926    },
9927
9928    _setHandleClassName: function() {
9929        this.handleElement = this.options.handle ?
9930            this.element.find( this.options.handle ) : this.element;
9931        this._addClass( this.handleElement, "ui-draggable-handle" );
9932    },
9933
9934    _removeHandleClassName: function() {
9935        this._removeClass( this.handleElement, "ui-draggable-handle" );
9936    },
9937
9938    _createHelper: function( event ) {
9939
9940        var o = this.options,
9941            helperIsFunction = typeof o.helper === "function",
9942            helper = helperIsFunction ?
9943                $( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
9944                ( o.helper === "clone" ?
9945                    this.element.clone().removeAttr( "id" ) :
9946                    this.element );
9947
9948        if ( !helper.parents( "body" ).length ) {
9949            helper.appendTo( ( o.appendTo === "parent" ?
9950                this.element[ 0 ].parentNode :
9951                o.appendTo ) );
9952        }
9953
9954        // https://bugs.jqueryui.com/ticket/9446
9955        // a helper function can return the original element
9956        // which wouldn't have been set to relative in _create
9957        if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
9958            this._setPositionRelative();
9959        }
9960
9961        if ( helper[ 0 ] !== this.element[ 0 ] &&
9962                !( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
9963            helper.css( "position", "absolute" );
9964        }
9965
9966        return helper;
9967
9968    },
9969
9970    _setPositionRelative: function() {
9971        if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
9972            this.element[ 0 ].style.position = "relative";
9973        }
9974    },
9975
9976    _adjustOffsetFromHelper: function( obj ) {
9977        if ( typeof obj === "string" ) {
9978            obj = obj.split( " " );
9979        }
9980        if ( Array.isArray( obj ) ) {
9981            obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
9982        }
9983        if ( "left" in obj ) {
9984            this.offset.click.left = obj.left + this.margins.left;
9985        }
9986        if ( "right" in obj ) {
9987            this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
9988        }
9989        if ( "top" in obj ) {
9990            this.offset.click.top = obj.top + this.margins.top;
9991        }
9992        if ( "bottom" in obj ) {
9993            this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
9994        }
9995    },
9996
9997    _isRootNode: function( element ) {
9998        return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
9999    },
10000
10001    _getParentOffset: function() {
10002
10003        //Get the offsetParent and cache its position
10004        var po = this.offsetParent.offset(),
10005            document = this.document[ 0 ];
10006
10007        // This is a special case where we need to modify a offset calculated on start, since the
10008        // following happened:
10009        // 1. The position of the helper is absolute, so it's position is calculated based on the
10010        // next positioned parent
10011        // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
10012        // the document, which means that the scroll is included in the initial calculation of the
10013        // offset of the parent, and never recalculated upon drag
10014        if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
10015                $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
10016            po.left += this.scrollParent.scrollLeft();
10017            po.top += this.scrollParent.scrollTop();
10018        }
10019
10020        if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
10021            po = { top: 0, left: 0 };
10022        }
10023
10024        return {
10025            top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
10026            left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
10027        };
10028
10029    },
10030
10031    _getRelativeOffset: function() {
10032        if ( this.cssPosition !== "relative" ) {
10033            return { top: 0, left: 0 };
10034        }
10035
10036        var p = this.element.position(),
10037            scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10038
10039        return {
10040            top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
10041                ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
10042            left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
10043                ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
10044        };
10045
10046    },
10047
10048    _cacheMargins: function() {
10049        this.margins = {
10050            left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
10051            top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
10052            right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
10053            bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
10054        };
10055    },
10056
10057    _cacheHelperProportions: function() {
10058        this.helperProportions = {
10059            width: this.helper.outerWidth(),
10060            height: this.helper.outerHeight()
10061        };
10062    },
10063
10064    _setContainment: function() {
10065
10066        var isUserScrollable, c, ce,
10067            o = this.options,
10068            document = this.document[ 0 ];
10069
10070        this.relativeContainer = null;
10071
10072        if ( !o.containment ) {
10073            this.containment = null;
10074            return;
10075        }
10076
10077        if ( o.containment === "window" ) {
10078            this.containment = [
10079                $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
10080                $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
10081                $( window ).scrollLeft() + $( window ).width() -
10082                    this.helperProportions.width - this.margins.left,
10083                $( window ).scrollTop() +
10084                    ( $( window ).height() || document.body.parentNode.scrollHeight ) -
10085                    this.helperProportions.height - this.margins.top
10086            ];
10087            return;
10088        }
10089
10090        if ( o.containment === "document" ) {
10091            this.containment = [
10092                0,
10093                0,
10094                $( document ).width() - this.helperProportions.width - this.margins.left,
10095                ( $( document ).height() || document.body.parentNode.scrollHeight ) -
10096                    this.helperProportions.height - this.margins.top
10097            ];
10098            return;
10099        }
10100
10101        if ( o.containment.constructor === Array ) {
10102            this.containment = o.containment;
10103            return;
10104        }
10105
10106        if ( o.containment === "parent" ) {
10107            o.containment = this.helper[ 0 ].parentNode;
10108        }
10109
10110        c = $( o.containment );
10111        ce = c[ 0 ];
10112
10113        if ( !ce ) {
10114            return;
10115        }
10116
10117        isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
10118
10119        this.containment = [
10120            ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
10121                ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
10122            ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
10123                ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
10124            ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
10125                ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
10126                ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
10127                this.helperProportions.width -
10128                this.margins.left -
10129                this.margins.right,
10130            ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
10131                ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
10132                ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
10133                this.helperProportions.height -
10134                this.margins.top -
10135                this.margins.bottom
10136        ];
10137        this.relativeContainer = c;
10138    },
10139
10140    _convertPositionTo: function( d, pos ) {
10141
10142        if ( !pos ) {
10143            pos = this.position;
10144        }
10145
10146        var mod = d === "absolute" ? 1 : -1,
10147            scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10148
10149        return {
10150            top: (
10151
10152                // The absolute mouse position
10153                pos.top +
10154
10155                // Only for relative positioned nodes: Relative offset from element to offset parent
10156                this.offset.relative.top * mod +
10157
10158                // The offsetParent's offset without borders (offset + border)
10159                this.offset.parent.top * mod -
10160                ( ( this.cssPosition === "fixed" ?
10161                    -this.offset.scroll.top :
10162                    ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
10163            ),
10164            left: (
10165
10166                // The absolute mouse position
10167                pos.left +
10168
10169                // Only for relative positioned nodes: Relative offset from element to offset parent
10170                this.offset.relative.left * mod +
10171
10172                // The offsetParent's offset without borders (offset + border)
10173                this.offset.parent.left * mod   -
10174                ( ( this.cssPosition === "fixed" ?
10175                    -this.offset.scroll.left :
10176                    ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
10177            )
10178        };
10179
10180    },
10181
10182    _generatePosition: function( event, constrainPosition ) {
10183
10184        var containment, co, top, left,
10185            o = this.options,
10186            scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
10187            pageX = event.pageX,
10188            pageY = event.pageY;
10189
10190        // Cache the scroll
10191        if ( !scrollIsRootNode || !this.offset.scroll ) {
10192            this.offset.scroll = {
10193                top: this.scrollParent.scrollTop(),
10194                left: this.scrollParent.scrollLeft()
10195            };
10196        }
10197
10198        /*
10199         * - Position constraining -
10200         * Constrain the position to a mix of grid, containment.
10201         */
10202
10203        // If we are not dragging yet, we won't check for options
10204        if ( constrainPosition ) {
10205            if ( this.containment ) {
10206                if ( this.relativeContainer ) {
10207                    co = this.relativeContainer.offset();
10208                    containment = [
10209                        this.containment[ 0 ] + co.left,
10210                        this.containment[ 1 ] + co.top,
10211                        this.containment[ 2 ] + co.left,
10212                        this.containment[ 3 ] + co.top
10213                    ];
10214                } else {
10215                    containment = this.containment;
10216                }
10217
10218                if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
10219                    pageX = containment[ 0 ] + this.offset.click.left;
10220                }
10221                if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
10222                    pageY = containment[ 1 ] + this.offset.click.top;
10223                }
10224                if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
10225                    pageX = containment[ 2 ] + this.offset.click.left;
10226                }
10227                if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
10228                    pageY = containment[ 3 ] + this.offset.click.top;
10229                }
10230            }
10231
10232            if ( o.grid ) {
10233
10234                //Check for grid elements set to 0 to prevent divide by 0 error causing invalid
10235                // argument errors in IE (see ticket #6950)
10236                top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
10237                    this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
10238                pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
10239                    top - this.offset.click.top > containment[ 3 ] ) ?
10240                        top :
10241                        ( ( top - this.offset.click.top >= containment[ 1 ] ) ?
10242                            top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
10243
10244                left = o.grid[ 0 ] ? this.originalPageX +
10245                    Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
10246                    this.originalPageX;
10247                pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
10248                    left - this.offset.click.left > containment[ 2 ] ) ?
10249                        left :
10250                        ( ( left - this.offset.click.left >= containment[ 0 ] ) ?
10251                            left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
10252            }
10253
10254            if ( o.axis === "y" ) {
10255                pageX = this.originalPageX;
10256            }
10257
10258            if ( o.axis === "x" ) {
10259                pageY = this.originalPageY;
10260            }
10261        }
10262
10263        return {
10264            top: (
10265
10266                // The absolute mouse position
10267                pageY -
10268
10269                // Click offset (relative to the element)
10270                this.offset.click.top -
10271
10272                // Only for relative positioned nodes: Relative offset from element to offset parent
10273                this.offset.relative.top -
10274
10275                // The offsetParent's offset without borders (offset + border)
10276                this.offset.parent.top +
10277                ( this.cssPosition === "fixed" ?
10278                    -this.offset.scroll.top :
10279                    ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
10280            ),
10281            left: (
10282
10283                // The absolute mouse position
10284                pageX -
10285
10286                // Click offset (relative to the element)
10287                this.offset.click.left -
10288
10289                // Only for relative positioned nodes: Relative offset from element to offset parent
10290                this.offset.relative.left -
10291
10292                // The offsetParent's offset without borders (offset + border)
10293                this.offset.parent.left +
10294                ( this.cssPosition === "fixed" ?
10295                    -this.offset.scroll.left :
10296                    ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
10297            )
10298        };
10299
10300    },
10301
10302    _clear: function() {
10303        this._removeClass( this.helper, "ui-draggable-dragging" );
10304        if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
10305            this.helper.remove();
10306        }
10307        this.helper = null;
10308        this.cancelHelperRemoval = false;
10309        if ( this.destroyOnClear ) {
10310            this.destroy();
10311        }
10312    },
10313
10314    // From now on bulk stuff - mainly helpers
10315
10316    _trigger: function( type, event, ui ) {
10317        ui = ui || this._uiHash();
10318        $.ui.plugin.call( this, type, [ event, ui, this ], true );
10319
10320        // Absolute position and offset (see #6884 ) have to be recalculated after plugins
10321        if ( /^(drag|start|stop)/.test( type ) ) {
10322            this.positionAbs = this._convertPositionTo( "absolute" );
10323            ui.offset = this.positionAbs;
10324        }
10325        return $.Widget.prototype._trigger.call( this, type, event, ui );
10326    },
10327
10328    plugins: {},
10329
10330    _uiHash: function() {
10331        return {
10332            helper: this.helper,
10333            position: this.position,
10334            originalPosition: this.originalPosition,
10335            offset: this.positionAbs
10336        };
10337    }
10338
10339} );
10340
10341$.ui.plugin.add( "draggable", "connectToSortable", {
10342    start: function( event, ui, draggable ) {
10343        var uiSortable = $.extend( {}, ui, {
10344            item: draggable.element
10345        } );
10346
10347        draggable.sortables = [];
10348        $( draggable.options.connectToSortable ).each( function() {
10349            var sortable = $( this ).sortable( "instance" );
10350
10351            if ( sortable && !sortable.options.disabled ) {
10352                draggable.sortables.push( sortable );
10353
10354                // RefreshPositions is called at drag start to refresh the containerCache
10355                // which is used in drag. This ensures it's initialized and synchronized
10356                // with any changes that might have happened on the page since initialization.
10357                sortable.refreshPositions();
10358                sortable._trigger( "activate", event, uiSortable );
10359            }
10360        } );
10361    },
10362    stop: function( event, ui, draggable ) {
10363        var uiSortable = $.extend( {}, ui, {
10364            item: draggable.element
10365        } );
10366
10367        draggable.cancelHelperRemoval = false;
10368
10369        $.each( draggable.sortables, function() {
10370            var sortable = this;
10371
10372            if ( sortable.isOver ) {
10373                sortable.isOver = 0;
10374
10375                // Allow this sortable to handle removing the helper
10376                draggable.cancelHelperRemoval = true;
10377                sortable.cancelHelperRemoval = false;
10378
10379                // Use _storedCSS To restore properties in the sortable,
10380                // as this also handles revert (#9675) since the draggable
10381                // may have modified them in unexpected ways (#8809)
10382                sortable._storedCSS = {
10383                    position: sortable.placeholder.css( "position" ),
10384                    top: sortable.placeholder.css( "top" ),
10385                    left: sortable.placeholder.css( "left" )
10386                };
10387
10388                sortable._mouseStop( event );
10389
10390                // Once drag has ended, the sortable should return to using
10391                // its original helper, not the shared helper from draggable
10392                sortable.options.helper = sortable.options._helper;
10393            } else {
10394
10395                // Prevent this Sortable from removing the helper.
10396                // However, don't set the draggable to remove the helper
10397                // either as another connected Sortable may yet handle the removal.
10398                sortable.cancelHelperRemoval = true;
10399
10400                sortable._trigger( "deactivate", event, uiSortable );
10401            }
10402        } );
10403    },
10404    drag: function( event, ui, draggable ) {
10405        $.each( draggable.sortables, function() {
10406            var innermostIntersecting = false,
10407                sortable = this;
10408
10409            // Copy over variables that sortable's _intersectsWith uses
10410            sortable.positionAbs = draggable.positionAbs;
10411            sortable.helperProportions = draggable.helperProportions;
10412            sortable.offset.click = draggable.offset.click;
10413
10414            if ( sortable._intersectsWith( sortable.containerCache ) ) {
10415                innermostIntersecting = true;
10416
10417                $.each( draggable.sortables, function() {
10418
10419                    // Copy over variables that sortable's _intersectsWith uses
10420                    this.positionAbs = draggable.positionAbs;
10421                    this.helperProportions = draggable.helperProportions;
10422                    this.offset.click = draggable.offset.click;
10423
10424                    if ( this !== sortable &&
10425                            this._intersectsWith( this.containerCache ) &&
10426                            $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
10427                        innermostIntersecting = false;
10428                    }
10429
10430                    return innermostIntersecting;
10431                } );
10432            }
10433
10434            if ( innermostIntersecting ) {
10435
10436                // If it intersects, we use a little isOver variable and set it once,
10437                // so that the move-in stuff gets fired only once.
10438                if ( !sortable.isOver ) {
10439                    sortable.isOver = 1;
10440
10441                    // Store draggable's parent in case we need to reappend to it later.
10442                    draggable._parent = ui.helper.parent();
10443
10444                    sortable.currentItem = ui.helper
10445                        .appendTo( sortable.element )
10446                        .data( "ui-sortable-item", true );
10447
10448                    // Store helper option to later restore it
10449                    sortable.options._helper = sortable.options.helper;
10450
10451                    sortable.options.helper = function() {
10452                        return ui.helper[ 0 ];
10453                    };
10454
10455                    // Fire the start events of the sortable with our passed browser event,
10456                    // and our own helper (so it doesn't create a new one)
10457                    event.target = sortable.currentItem[ 0 ];
10458                    sortable._mouseCapture( event, true );
10459                    sortable._mouseStart( event, true, true );
10460
10461                    // Because the browser event is way off the new appended portlet,
10462                    // modify necessary variables to reflect the changes
10463                    sortable.offset.click.top = draggable.offset.click.top;
10464                    sortable.offset.click.left = draggable.offset.click.left;
10465                    sortable.offset.parent.left -= draggable.offset.parent.left -
10466                        sortable.offset.parent.left;
10467                    sortable.offset.parent.top -= draggable.offset.parent.top -
10468                        sortable.offset.parent.top;
10469
10470                    draggable._trigger( "toSortable", event );
10471
10472                    // Inform draggable that the helper is in a valid drop zone,
10473                    // used solely in the revert option to handle "valid/invalid".
10474                    draggable.dropped = sortable.element;
10475
10476                    // Need to refreshPositions of all sortables in the case that
10477                    // adding to one sortable changes the location of the other sortables (#9675)
10478                    $.each( draggable.sortables, function() {
10479                        this.refreshPositions();
10480                    } );
10481
10482                    // Hack so receive/update callbacks work (mostly)
10483                    draggable.currentItem = draggable.element;
10484                    sortable.fromOutside = draggable;
10485                }
10486
10487                if ( sortable.currentItem ) {
10488                    sortable._mouseDrag( event );
10489
10490                    // Copy the sortable's position because the draggable's can potentially reflect
10491                    // a relative position, while sortable is always absolute, which the dragged
10492                    // element has now become. (#8809)
10493                    ui.position = sortable.position;
10494                }
10495            } else {
10496
10497                // If it doesn't intersect with the sortable, and it intersected before,
10498                // we fake the drag stop of the sortable, but make sure it doesn't remove
10499                // the helper by using cancelHelperRemoval.
10500                if ( sortable.isOver ) {
10501
10502                    sortable.isOver = 0;
10503                    sortable.cancelHelperRemoval = true;
10504
10505                    // Calling sortable's mouseStop would trigger a revert,
10506                    // so revert must be temporarily false until after mouseStop is called.
10507                    sortable.options._revert = sortable.options.revert;
10508                    sortable.options.revert = false;
10509
10510                    sortable._trigger( "out", event, sortable._uiHash( sortable ) );
10511                    sortable._mouseStop( event, true );
10512
10513                    // Restore sortable behaviors that were modfied
10514                    // when the draggable entered the sortable area (#9481)
10515                    sortable.options.revert = sortable.options._revert;
10516                    sortable.options.helper = sortable.options._helper;
10517
10518                    if ( sortable.placeholder ) {
10519                        sortable.placeholder.remove();
10520                    }
10521
10522                    // Restore and recalculate the draggable's offset considering the sortable
10523                    // may have modified them in unexpected ways. (#8809, #10669)
10524                    ui.helper.appendTo( draggable._parent );
10525                    draggable._refreshOffsets( event );
10526                    ui.position = draggable._generatePosition( event, true );
10527
10528                    draggable._trigger( "fromSortable", event );
10529
10530                    // Inform draggable that the helper is no longer in a valid drop zone
10531                    draggable.dropped = false;
10532
10533                    // Need to refreshPositions of all sortables just in case removing
10534                    // from one sortable changes the location of other sortables (#9675)
10535                    $.each( draggable.sortables, function() {
10536                        this.refreshPositions();
10537                    } );
10538                }
10539            }
10540        } );
10541    }
10542} );
10543
10544$.ui.plugin.add( "draggable", "cursor", {
10545    start: function( event, ui, instance ) {
10546        var t = $( "body" ),
10547            o = instance.options;
10548
10549        if ( t.css( "cursor" ) ) {
10550            o._cursor = t.css( "cursor" );
10551        }
10552        t.css( "cursor", o.cursor );
10553    },
10554    stop: function( event, ui, instance ) {
10555        var o = instance.options;
10556        if ( o._cursor ) {
10557            $( "body" ).css( "cursor", o._cursor );
10558        }
10559    }
10560} );
10561
10562$.ui.plugin.add( "draggable", "opacity", {
10563    start: function( event, ui, instance ) {
10564        var t = $( ui.helper ),
10565            o = instance.options;
10566        if ( t.css( "opacity" ) ) {
10567            o._opacity = t.css( "opacity" );
10568        }
10569        t.css( "opacity", o.opacity );
10570    },
10571    stop: function( event, ui, instance ) {
10572        var o = instance.options;
10573        if ( o._opacity ) {
10574            $( ui.helper ).css( "opacity", o._opacity );
10575        }
10576    }
10577} );
10578
10579$.ui.plugin.add( "draggable", "scroll", {
10580    start: function( event, ui, i ) {
10581        if ( !i.scrollParentNotHidden ) {
10582            i.scrollParentNotHidden = i.helper.scrollParent( false );
10583        }
10584
10585        if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
10586                i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
10587            i.overflowOffset = i.scrollParentNotHidden.offset();
10588        }
10589    },
10590    drag: function( event, ui, i  ) {
10591
10592        var o = i.options,
10593            scrolled = false,
10594            scrollParent = i.scrollParentNotHidden[ 0 ],
10595            document = i.document[ 0 ];
10596
10597        if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
10598            if ( !o.axis || o.axis !== "x" ) {
10599                if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
10600                        o.scrollSensitivity ) {
10601                    scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
10602                } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
10603                    scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
10604                }
10605            }
10606
10607            if ( !o.axis || o.axis !== "y" ) {
10608                if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
10609                        o.scrollSensitivity ) {
10610                    scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
10611                } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
10612                    scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
10613                }
10614            }
10615
10616        } else {
10617
10618            if ( !o.axis || o.axis !== "x" ) {
10619                if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
10620                    scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
10621                } else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
10622                        o.scrollSensitivity ) {
10623                    scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
10624                }
10625            }
10626
10627            if ( !o.axis || o.axis !== "y" ) {
10628                if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
10629                    scrolled = $( document ).scrollLeft(
10630                        $( document ).scrollLeft() - o.scrollSpeed
10631                    );
10632                } else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
10633                        o.scrollSensitivity ) {
10634                    scrolled = $( document ).scrollLeft(
10635                        $( document ).scrollLeft() + o.scrollSpeed
10636                    );
10637                }
10638            }
10639
10640        }
10641
10642        if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
10643            $.ui.ddmanager.prepareOffsets( i, event );
10644        }
10645
10646    }
10647} );
10648
10649$.ui.plugin.add( "draggable", "snap", {
10650    start: function( event, ui, i ) {
10651
10652        var o = i.options;
10653
10654        i.snapElements = [];
10655
10656        $( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
10657            .each( function() {
10658                var $t = $( this ),
10659                    $o = $t.offset();
10660                if ( this !== i.element[ 0 ] ) {
10661                    i.snapElements.push( {
10662                        item: this,
10663                        width: $t.outerWidth(), height: $t.outerHeight(),
10664                        top: $o.top, left: $o.left
10665                    } );
10666                }
10667            } );
10668
10669    },
10670    drag: function( event, ui, inst ) {
10671
10672        var ts, bs, ls, rs, l, r, t, b, i, first,
10673            o = inst.options,
10674            d = o.snapTolerance,
10675            x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
10676            y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
10677
10678        for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
10679
10680            l = inst.snapElements[ i ].left - inst.margins.left;
10681            r = l + inst.snapElements[ i ].width;
10682            t = inst.snapElements[ i ].top - inst.margins.top;
10683            b = t + inst.snapElements[ i ].height;
10684
10685            if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
10686                    !$.contains( inst.snapElements[ i ].item.ownerDocument,
10687                    inst.snapElements[ i ].item ) ) {
10688                if ( inst.snapElements[ i ].snapping ) {
10689                    if ( inst.options.snap.release ) {
10690                        inst.options.snap.release.call(
10691                            inst.element,
10692                            event,
10693                            $.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
10694                        );
10695                    }
10696                }
10697                inst.snapElements[ i ].snapping = false;
10698                continue;
10699            }
10700
10701            if ( o.snapMode !== "inner" ) {
10702                ts = Math.abs( t - y2 ) <= d;
10703                bs = Math.abs( b - y1 ) <= d;
10704                ls = Math.abs( l - x2 ) <= d;
10705                rs = Math.abs( r - x1 ) <= d;
10706                if ( ts ) {
10707                    ui.position.top = inst._convertPositionTo( "relative", {
10708                        top: t - inst.helperProportions.height,
10709                        left: 0
10710                    } ).top;
10711                }
10712                if ( bs ) {
10713                    ui.position.top = inst._convertPositionTo( "relative", {
10714                        top: b,
10715                        left: 0
10716                    } ).top;
10717                }
10718                if ( ls ) {
10719                    ui.position.left = inst._convertPositionTo( "relative", {
10720                        top: 0,
10721                        left: l - inst.helperProportions.width
10722                    } ).left;
10723                }
10724                if ( rs ) {
10725                    ui.position.left = inst._convertPositionTo( "relative", {
10726                        top: 0,
10727                        left: r
10728                    } ).left;
10729                }
10730            }
10731
10732            first = ( ts || bs || ls || rs );
10733
10734            if ( o.snapMode !== "outer" ) {
10735                ts = Math.abs( t - y1 ) <= d;
10736                bs = Math.abs( b - y2 ) <= d;
10737                ls = Math.abs( l - x1 ) <= d;
10738                rs = Math.abs( r - x2 ) <= d;
10739                if ( ts ) {
10740                    ui.position.top = inst._convertPositionTo( "relative", {
10741                        top: t,
10742                        left: 0
10743                    } ).top;
10744                }
10745                if ( bs ) {
10746                    ui.position.top = inst._convertPositionTo( "relative", {
10747                        top: b - inst.helperProportions.height,
10748                        left: 0
10749                    } ).top;
10750                }
10751                if ( ls ) {
10752                    ui.position.left = inst._convertPositionTo( "relative", {
10753                        top: 0,
10754                        left: l
10755                    } ).left;
10756                }
10757                if ( rs ) {
10758                    ui.position.left = inst._convertPositionTo( "relative", {
10759                        top: 0,
10760                        left: r - inst.helperProportions.width
10761                    } ).left;
10762                }
10763            }
10764
10765            if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
10766                if ( inst.options.snap.snap ) {
10767                    inst.options.snap.snap.call(
10768                        inst.element,
10769                        event,
10770                        $.extend( inst._uiHash(), {
10771                            snapItem: inst.snapElements[ i ].item
10772                        } ) );
10773                }
10774            }
10775            inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
10776
10777        }
10778
10779    }
10780} );
10781
10782$.ui.plugin.add( "draggable", "stack", {
10783    start: function( event, ui, instance ) {
10784        var min,
10785            o = instance.options,
10786            group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
10787                return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
10788                    ( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
10789            } );
10790
10791        if ( !group.length ) {
10792            return;
10793        }
10794
10795        min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
10796        $( group ).each( function( i ) {
10797            $( this ).css( "zIndex", min + i );
10798        } );
10799        this.css( "zIndex", ( min + group.length ) );
10800    }
10801} );
10802
10803$.ui.plugin.add( "draggable", "zIndex", {
10804    start: function( event, ui, instance ) {
10805        var t = $( ui.helper ),
10806            o = instance.options;
10807
10808        if ( t.css( "zIndex" ) ) {
10809            o._zIndex = t.css( "zIndex" );
10810        }
10811        t.css( "zIndex", o.zIndex );
10812    },
10813    stop: function( event, ui, instance ) {
10814        var o = instance.options;
10815
10816        if ( o._zIndex ) {
10817            $( ui.helper ).css( "zIndex", o._zIndex );
10818        }
10819    }
10820} );
10821
10822var widgetsDraggable = $.ui.draggable;
10823
10824
10825/*!
10826 * jQuery UI Resizable 1.14.1
10827 * https://jqueryui.com
10828 *
10829 * Copyright OpenJS Foundation and other contributors
10830 * Released under the MIT license.
10831 * https://jquery.org/license
10832 */
10833
10834//>>label: Resizable
10835//>>group: Interactions
10836//>>description: Enables resize functionality for any element.
10837//>>docs: https://api.jqueryui.com/resizable/
10838//>>demos: https://jqueryui.com/resizable/
10839//>>css.structure: ../../themes/base/core.css
10840//>>css.structure: ../../themes/base/resizable.css
10841//>>css.theme: ../../themes/base/theme.css
10842
10843
10844$.widget( "ui.resizable", $.ui.mouse, {
10845    version: "1.14.1",
10846    widgetEventPrefix: "resize",
10847    options: {
10848        alsoResize: false,
10849        animate: false,
10850        animateDuration: "slow",
10851        animateEasing: "swing",
10852        aspectRatio: false,
10853        autoHide: false,
10854        classes: {
10855            "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
10856        },
10857        containment: false,
10858        ghost: false,
10859        grid: false,
10860        handles: "e,s,se",
10861        helper: false,
10862        maxHeight: null,
10863        maxWidth: null,
10864        minHeight: 10,
10865        minWidth: 10,
10866
10867        // See #7960
10868        zIndex: 90,
10869
10870        // Callbacks
10871        resize: null,
10872        start: null,
10873        stop: null
10874    },
10875
10876    _num: function( value ) {
10877        return parseFloat( value ) || 0;
10878    },
10879
10880    _isNumber: function( value ) {
10881        return !isNaN( parseFloat( value ) );
10882    },
10883
10884    _hasScroll: function( el, a ) {
10885
10886        var scroll,
10887            has = false,
10888            overflow = $( el ).css( "overflow" );
10889
10890        if ( overflow === "hidden" ) {
10891            return false;
10892        }
10893        if ( overflow === "scroll" ) {
10894            return true;
10895        }
10896
10897        scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop";
10898
10899        if ( el[ scroll ] > 0 ) {
10900            return true;
10901        }
10902
10903        // TODO: determine which cases actually cause this to happen
10904        // if the element doesn't have the scroll set, see if it's possible to
10905        // set the scroll
10906        try {
10907            el[ scroll ] = 1;
10908            has = ( el[ scroll ] > 0 );
10909            el[ scroll ] = 0;
10910        } catch ( e ) {
10911
10912            // `el` might be a string, then setting `scroll` will throw
10913            // an error in strict mode; ignore it.
10914        }
10915        return has;
10916    },
10917
10918    _create: function() {
10919
10920        var margins,
10921            o = this.options,
10922            that = this;
10923        this._addClass( "ui-resizable" );
10924
10925        $.extend( this, {
10926            _aspectRatio: !!( o.aspectRatio ),
10927            aspectRatio: o.aspectRatio,
10928            originalElement: this.element,
10929            _proportionallyResizeElements: [],
10930            _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
10931        } );
10932
10933        // Wrap the element if it cannot hold child nodes
10934        if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
10935
10936            this.element.wrap(
10937                $( "<div class='ui-wrapper'></div>" ).css( {
10938                    overflow: "hidden",
10939                    position: this.element.css( "position" ),
10940                    width: this.element.outerWidth(),
10941                    height: this.element.outerHeight(),
10942                    top: this.element.css( "top" ),
10943                    left: this.element.css( "left" )
10944                } )
10945            );
10946
10947            this.element = this.element.parent().data(
10948                "ui-resizable", this.element.resizable( "instance" )
10949            );
10950
10951            this.elementIsWrapper = true;
10952
10953            margins = {
10954                marginTop: this.originalElement.css( "marginTop" ),
10955                marginRight: this.originalElement.css( "marginRight" ),
10956                marginBottom: this.originalElement.css( "marginBottom" ),
10957                marginLeft: this.originalElement.css( "marginLeft" )
10958            };
10959
10960            this.element.css( margins );
10961
10962            // Support: Safari
10963            // Prevent Safari textarea resize
10964            this.originalResizeStyle = this.originalElement.css( "resize" );
10965            this.originalElement.css( "resize", "none" );
10966
10967            this._proportionallyResizeElements.push( this.originalElement.css( {
10968                position: "static",
10969                zoom: 1,
10970                display: "block"
10971            } ) );
10972
10973            this._proportionallyResize();
10974        }
10975
10976        this._setupHandles();
10977
10978        if ( o.autoHide ) {
10979            $( this.element )
10980                .on( "mouseenter", function() {
10981                    if ( o.disabled ) {
10982                        return;
10983                    }
10984                    that._removeClass( "ui-resizable-autohide" );
10985                    that._handles.show();
10986                } )
10987                .on( "mouseleave", function() {
10988                    if ( o.disabled ) {
10989                        return;
10990                    }
10991                    if ( !that.resizing ) {
10992                        that._addClass( "ui-resizable-autohide" );
10993                        that._handles.hide();
10994                    }
10995                } );
10996        }
10997
10998        this._mouseInit();
10999    },
11000
11001    _destroy: function() {
11002
11003        this._mouseDestroy();
11004        this._addedHandles.remove();
11005
11006        var wrapper,
11007            _destroy = function( exp ) {
11008                $( exp )
11009                    .removeData( "resizable" )
11010                    .removeData( "ui-resizable" )
11011                    .off( ".resizable" );
11012            };
11013
11014        // TODO: Unwrap at same DOM position
11015        if ( this.elementIsWrapper ) {
11016            _destroy( this.element );
11017            wrapper = this.element;
11018            this.originalElement.css( {
11019                position: wrapper.css( "position" ),
11020                width: wrapper.outerWidth(),
11021                height: wrapper.outerHeight(),
11022                top: wrapper.css( "top" ),
11023                left: wrapper.css( "left" )
11024            } ).insertAfter( wrapper );
11025            wrapper.remove();
11026        }
11027
11028        this.originalElement.css( "resize", this.originalResizeStyle );
11029        _destroy( this.originalElement );
11030
11031        return this;
11032    },
11033
11034    _setOption: function( key, value ) {
11035        this._super( key, value );
11036
11037        switch ( key ) {
11038        case "handles":
11039            this._removeHandles();
11040            this._setupHandles();
11041            break;
11042        case "aspectRatio":
11043            this._aspectRatio = !!value;
11044            break;
11045        default:
11046            break;
11047        }
11048    },
11049
11050    _setupHandles: function() {
11051        var o = this.options, handle, i, n, hname, axis, that = this;
11052        this.handles = o.handles ||
11053            ( !$( ".ui-resizable-handle", this.element ).length ?
11054                "e,s,se" : {
11055                    n: ".ui-resizable-n",
11056                    e: ".ui-resizable-e",
11057                    s: ".ui-resizable-s",
11058                    w: ".ui-resizable-w",
11059                    se: ".ui-resizable-se",
11060                    sw: ".ui-resizable-sw",
11061                    ne: ".ui-resizable-ne",
11062                    nw: ".ui-resizable-nw"
11063                } );
11064
11065        this._handles = $();
11066        this._addedHandles = $();
11067        if ( this.handles.constructor === String ) {
11068
11069            if ( this.handles === "all" ) {
11070                this.handles = "n,e,s,w,se,sw,ne,nw";
11071            }
11072
11073            n = this.handles.split( "," );
11074            this.handles = {};
11075
11076            for ( i = 0; i < n.length; i++ ) {
11077
11078                handle = String.prototype.trim.call( n[ i ] );
11079                hname = "ui-resizable-" + handle;
11080                axis = $( "<div>" );
11081                this._addClass( axis, "ui-resizable-handle " + hname );
11082
11083                axis.css( { zIndex: o.zIndex } );
11084
11085                this.handles[ handle ] = ".ui-resizable-" + handle;
11086                if ( !this.element.children( this.handles[ handle ] ).length ) {
11087                    this.element.append( axis );
11088                    this._addedHandles = this._addedHandles.add( axis );
11089                }
11090            }
11091
11092        }
11093
11094        this._renderAxis = function( target ) {
11095
11096            var i, axis, padPos, padWrapper;
11097
11098            target = target || this.element;
11099
11100            for ( i in this.handles ) {
11101
11102                if ( this.handles[ i ].constructor === String ) {
11103                    this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
11104                } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
11105                    this.handles[ i ] = $( this.handles[ i ] );
11106                    this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
11107                }
11108
11109                if ( this.elementIsWrapper &&
11110                        this.originalElement[ 0 ]
11111                            .nodeName
11112                            .match( /^(textarea|input|select|button)$/i ) ) {
11113                    axis = $( this.handles[ i ], this.element );
11114
11115                    padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
11116                        axis.outerHeight() :
11117                        axis.outerWidth();
11118
11119                    padPos = [ "padding",
11120                        /ne|nw|n/.test( i ) ? "Top" :
11121                        /se|sw|s/.test( i ) ? "Bottom" :
11122                        /^e$/.test( i ) ? "Right" : "Left" ].join( "" );
11123
11124                    target.css( padPos, padWrapper );
11125
11126                    this._proportionallyResize();
11127                }
11128
11129                this._handles = this._handles.add( this.handles[ i ] );
11130            }
11131        };
11132
11133        // TODO: make renderAxis a prototype function
11134        this._renderAxis( this.element );
11135
11136        this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
11137        this._handles.disableSelection();
11138
11139        this._handles.on( "mouseover", function() {
11140            if ( !that.resizing ) {
11141                if ( this.className ) {
11142                    axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
11143                }
11144                that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
11145            }
11146        } );
11147
11148        if ( o.autoHide ) {
11149            this._handles.hide();
11150            this._addClass( "ui-resizable-autohide" );
11151        }
11152    },
11153
11154    _removeHandles: function() {
11155        this._addedHandles.remove();
11156    },
11157
11158    _mouseCapture: function( event ) {
11159        var i, handle,
11160            capture = false;
11161
11162        for ( i in this.handles ) {
11163            handle = $( this.handles[ i ] )[ 0 ];
11164            if ( handle === event.target || $.contains( handle, event.target ) ) {
11165                capture = true;
11166            }
11167        }
11168
11169        return !this.options.disabled && capture;
11170    },
11171
11172    _mouseStart: function( event ) {
11173
11174        var curleft, curtop, cursor, calculatedSize,
11175            o = this.options,
11176            el = this.element;
11177
11178        this.resizing = true;
11179
11180        this._renderProxy();
11181
11182        curleft = this._num( this.helper.css( "left" ) );
11183        curtop = this._num( this.helper.css( "top" ) );
11184
11185        if ( o.containment ) {
11186            curleft += $( o.containment ).scrollLeft() || 0;
11187            curtop += $( o.containment ).scrollTop() || 0;
11188        }
11189
11190        this.offset = this.helper.offset();
11191        this.position = { left: curleft, top: curtop };
11192
11193        if ( !this._helper ) {
11194            calculatedSize = this._calculateAdjustedElementDimensions( el );
11195        }
11196
11197        this.size = this._helper ? {
11198                width: this.helper.width(),
11199                height: this.helper.height()
11200            } : {
11201                width: calculatedSize.width,
11202                height: calculatedSize.height
11203            };
11204
11205        this.originalSize = this._helper ? {
11206                width: el.outerWidth(),
11207                height: el.outerHeight()
11208            } : {
11209                width: calculatedSize.width,
11210                height: calculatedSize.height
11211            };
11212
11213        this.sizeDiff = {
11214            width: el.outerWidth() - el.width(),
11215            height: el.outerHeight() - el.height()
11216        };
11217
11218        this.originalPosition = { left: curleft, top: curtop };
11219        this.originalMousePosition = { left: event.pageX, top: event.pageY };
11220
11221        this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
11222            o.aspectRatio :
11223            ( ( this.originalSize.width / this.originalSize.height ) || 1 );
11224
11225        cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
11226        $( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
11227
11228        this._addClass( "ui-resizable-resizing" );
11229        this._propagate( "start", event );
11230        return true;
11231    },
11232
11233    _mouseDrag: function( event ) {
11234
11235        var data, props,
11236            smp = this.originalMousePosition,
11237            a = this.axis,
11238            dx = ( event.pageX - smp.left ) || 0,
11239            dy = ( event.pageY - smp.top ) || 0,
11240            trigger = this._change[ a ];
11241
11242        this._updatePrevProperties();
11243
11244        if ( !trigger ) {
11245            return false;
11246        }
11247
11248        data = trigger.apply( this, [ event, dx, dy ] );
11249
11250        this._updateVirtualBoundaries( event.shiftKey );
11251        if ( this._aspectRatio || event.shiftKey ) {
11252            data = this._updateRatio( data, event );
11253        }
11254
11255        data = this._respectSize( data, event );
11256
11257        this._updateCache( data );
11258
11259        this._propagate( "resize", event );
11260
11261        props = this._applyChanges();
11262
11263        if ( !this._helper && this._proportionallyResizeElements.length ) {
11264            this._proportionallyResize();
11265        }
11266
11267        if ( !$.isEmptyObject( props ) ) {
11268            this._updatePrevProperties();
11269            this._trigger( "resize", event, this.ui() );
11270            this._applyChanges();
11271        }
11272
11273        return false;
11274    },
11275
11276    _mouseStop: function( event ) {
11277
11278        this.resizing = false;
11279        var pr, ista, soffseth, soffsetw, s, left, top,
11280            o = this.options, that = this;
11281
11282        if ( this._helper ) {
11283
11284            pr = this._proportionallyResizeElements;
11285            ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
11286            soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
11287            soffsetw = ista ? 0 : that.sizeDiff.width;
11288
11289            s = {
11290                width: ( that.helper.width()  - soffsetw ),
11291                height: ( that.helper.height() - soffseth )
11292            };
11293            left = ( parseFloat( that.element.css( "left" ) ) +
11294                ( that.position.left - that.originalPosition.left ) ) || null;
11295            top = ( parseFloat( that.element.css( "top" ) ) +
11296                ( that.position.top - that.originalPosition.top ) ) || null;
11297
11298            if ( !o.animate ) {
11299                this.element.css( $.extend( s, { top: top, left: left } ) );
11300            }
11301
11302            that.helper.height( that.size.height );
11303            that.helper.width( that.size.width );
11304
11305            if ( this._helper && !o.animate ) {
11306                this._proportionallyResize();
11307            }
11308        }
11309
11310        $( "body" ).css( "cursor", "auto" );
11311
11312        this._removeClass( "ui-resizable-resizing" );
11313
11314        this._propagate( "stop", event );
11315
11316        if ( this._helper ) {
11317            this.helper.remove();
11318        }
11319
11320        return false;
11321
11322    },
11323
11324    _updatePrevProperties: function() {
11325        this.prevPosition = {
11326            top: this.position.top,
11327            left: this.position.left
11328        };
11329        this.prevSize = {
11330            width: this.size.width,
11331            height: this.size.height
11332        };
11333    },
11334
11335    _applyChanges: function() {
11336        var props = {};
11337
11338        if ( this.position.top !== this.prevPosition.top ) {
11339            props.top = this.position.top + "px";
11340        }
11341        if ( this.position.left !== this.prevPosition.left ) {
11342            props.left = this.position.left + "px";
11343        }
11344
11345        this.helper.css( props );
11346
11347        if ( this.size.width !== this.prevSize.width ) {
11348            props.width = this.size.width + "px";
11349            this.helper.width( props.width );
11350        }
11351        if ( this.size.height !== this.prevSize.height ) {
11352            props.height = this.size.height + "px";
11353            this.helper.height( props.height );
11354        }
11355
11356        return props;
11357    },
11358
11359    _updateVirtualBoundaries: function( forceAspectRatio ) {
11360        var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
11361            o = this.options;
11362
11363        b = {
11364            minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
11365            maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
11366            minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
11367            maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
11368        };
11369
11370        if ( this._aspectRatio || forceAspectRatio ) {
11371            pMinWidth = b.minHeight * this.aspectRatio;
11372            pMinHeight = b.minWidth / this.aspectRatio;
11373            pMaxWidth = b.maxHeight * this.aspectRatio;
11374            pMaxHeight = b.maxWidth / this.aspectRatio;
11375
11376            if ( pMinWidth > b.minWidth ) {
11377                b.minWidth = pMinWidth;
11378            }
11379            if ( pMinHeight > b.minHeight ) {
11380                b.minHeight = pMinHeight;
11381            }
11382            if ( pMaxWidth < b.maxWidth ) {
11383                b.maxWidth = pMaxWidth;
11384            }
11385            if ( pMaxHeight < b.maxHeight ) {
11386                b.maxHeight = pMaxHeight;
11387            }
11388        }
11389        this._vBoundaries = b;
11390    },
11391
11392    _updateCache: function( data ) {
11393        this.offset = this.helper.offset();
11394        if ( this._isNumber( data.left ) ) {
11395            this.position.left = data.left;
11396        }
11397        if ( this._isNumber( data.top ) ) {
11398            this.position.top = data.top;
11399        }
11400        if ( this._isNumber( data.height ) ) {
11401            this.size.height = data.height;
11402        }
11403        if ( this._isNumber( data.width ) ) {
11404            this.size.width = data.width;
11405        }
11406    },
11407
11408    _updateRatio: function( data ) {
11409
11410        var cpos = this.position,
11411            csize = this.size,
11412            a = this.axis;
11413
11414        if ( this._isNumber( data.height ) ) {
11415            data.width = ( data.height * this.aspectRatio );
11416        } else if ( this._isNumber( data.width ) ) {
11417            data.height = ( data.width / this.aspectRatio );
11418        }
11419
11420        if ( a === "sw" ) {
11421            data.left = cpos.left + ( csize.width - data.width );
11422            data.top = null;
11423        }
11424        if ( a === "nw" ) {
11425            data.top = cpos.top + ( csize.height - data.height );
11426            data.left = cpos.left + ( csize.width - data.width );
11427        }
11428
11429        return data;
11430    },
11431
11432    _respectSize: function( data ) {
11433
11434        var o = this._vBoundaries,
11435            a = this.axis,
11436            ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
11437            ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
11438            isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
11439            isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
11440            dw = this.originalPosition.left + this.originalSize.width,
11441            dh = this.originalPosition.top + this.originalSize.height,
11442            cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
11443        if ( isminw ) {
11444            data.width = o.minWidth;
11445        }
11446        if ( isminh ) {
11447            data.height = o.minHeight;
11448        }
11449        if ( ismaxw ) {
11450            data.width = o.maxWidth;
11451        }
11452        if ( ismaxh ) {
11453            data.height = o.maxHeight;
11454        }
11455
11456        if ( isminw && cw ) {
11457            data.left = dw - o.minWidth;
11458        }
11459        if ( ismaxw && cw ) {
11460            data.left = dw - o.maxWidth;
11461        }
11462        if ( isminh && ch ) {
11463            data.top = dh - o.minHeight;
11464        }
11465        if ( ismaxh && ch ) {
11466            data.top = dh - o.maxHeight;
11467        }
11468
11469        // Fixing jump error on top/left - bug #2330
11470        if ( !data.width && !data.height && !data.left && data.top ) {
11471            data.top = null;
11472        } else if ( !data.width && !data.height && !data.top && data.left ) {
11473            data.left = null;
11474        }
11475
11476        return data;
11477    },
11478
11479    _getPaddingPlusBorderDimensions: function( element ) {
11480        var i = 0,
11481            widths = [],
11482            borders = [
11483                element.css( "borderTopWidth" ),
11484                element.css( "borderRightWidth" ),
11485                element.css( "borderBottomWidth" ),
11486                element.css( "borderLeftWidth" )
11487            ],
11488            paddings = [
11489                element.css( "paddingTop" ),
11490                element.css( "paddingRight" ),
11491                element.css( "paddingBottom" ),
11492                element.css( "paddingLeft" )
11493            ];
11494
11495        for ( ; i < 4; i++ ) {
11496            widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
11497            widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
11498        }
11499
11500        return {
11501            height: widths[ 0 ] + widths[ 2 ],
11502            width: widths[ 1 ] + widths[ 3 ]
11503        };
11504    },
11505
11506    _calculateAdjustedElementDimensions: function( element ) {
11507        var elWidth, elHeight, paddingBorder,
11508            ce = element.get( 0 );
11509
11510        if ( element.css( "box-sizing" ) !== "content-box" ||
11511            ( !this._hasScroll( ce ) && !this._hasScroll( ce, "left" ) ) ) {
11512                return {
11513                    height: parseFloat( element.css( "height" ) ),
11514                    width: parseFloat( element.css( "width" ) )
11515                };
11516        }
11517
11518        // Check if CSS inline styles are set and use those (usually from previous resizes)
11519        elWidth = parseFloat( ce.style.width );
11520        elHeight = parseFloat( ce.style.height );
11521
11522        paddingBorder = this._getPaddingPlusBorderDimensions( element );
11523        elWidth = isNaN( elWidth ) ?
11524            this._getElementTheoreticalSize( element, paddingBorder, "width" ) :
11525            elWidth;
11526        elHeight = isNaN( elHeight ) ?
11527            this._getElementTheoreticalSize( element, paddingBorder, "height" ) :
11528            elHeight;
11529
11530        return {
11531            height: elHeight,
11532            width: elWidth
11533        };
11534    },
11535
11536    _getElementTheoreticalSize: function( element, extraSize, dimension ) {
11537
11538        // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
11539        var size = Math.max( 0, Math.ceil(
11540            element.get( 0 )[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
11541            extraSize[ dimension ] -
11542            0.5
11543
11544        // If offsetWidth/offsetHeight is unknown, then we can't determine theoretical size.
11545        // Use an explicit zero to avoid NaN.
11546        // See https://github.com/jquery/jquery/issues/3964
11547        ) ) || 0;
11548
11549        return size;
11550    },
11551
11552    _proportionallyResize: function() {
11553
11554        if ( !this._proportionallyResizeElements.length ) {
11555            return;
11556        }
11557
11558        var prel,
11559            i = 0,
11560            element = this.helper || this.element;
11561
11562        for ( ; i < this._proportionallyResizeElements.length; i++ ) {
11563
11564            prel = this._proportionallyResizeElements[ i ];
11565
11566            // TODO: Seems like a bug to cache this.outerDimensions
11567            // considering that we are in a loop.
11568            if ( !this.outerDimensions ) {
11569                this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
11570            }
11571
11572            prel.css( {
11573                height: ( element.height() - this.outerDimensions.height ) || 0,
11574                width: ( element.width() - this.outerDimensions.width ) || 0
11575            } );
11576
11577        }
11578
11579    },
11580
11581    _renderProxy: function() {
11582
11583        var el = this.element, o = this.options;
11584        this.elementOffset = el.offset();
11585
11586        if ( this._helper ) {
11587
11588            this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } );
11589
11590            this._addClass( this.helper, this._helper );
11591            this.helper.css( {
11592                width: this.element.outerWidth(),
11593                height: this.element.outerHeight(),
11594                position: "absolute",
11595                left: this.elementOffset.left + "px",
11596                top: this.elementOffset.top + "px",
11597                zIndex: ++o.zIndex //TODO: Don't modify option
11598            } );
11599
11600            this.helper
11601                .appendTo( "body" )
11602                .disableSelection();
11603
11604        } else {
11605            this.helper = this.element;
11606        }
11607
11608    },
11609
11610    _change: {
11611        e: function( event, dx ) {
11612            return { width: this.originalSize.width + dx };
11613        },
11614        w: function( event, dx ) {
11615            var cs = this.originalSize, sp = this.originalPosition;
11616            return { left: sp.left + dx, width: cs.width - dx };
11617        },
11618        n: function( event, dx, dy ) {
11619            var cs = this.originalSize, sp = this.originalPosition;
11620            return { top: sp.top + dy, height: cs.height - dy };
11621        },
11622        s: function( event, dx, dy ) {
11623            return { height: this.originalSize.height + dy };
11624        },
11625        se: function( event, dx, dy ) {
11626            return $.extend( this._change.s.apply( this, arguments ),
11627                this._change.e.apply( this, [ event, dx, dy ] ) );
11628        },
11629        sw: function( event, dx, dy ) {
11630            return $.extend( this._change.s.apply( this, arguments ),
11631                this._change.w.apply( this, [ event, dx, dy ] ) );
11632        },
11633        ne: function( event, dx, dy ) {
11634            return $.extend( this._change.n.apply( this, arguments ),
11635                this._change.e.apply( this, [ event, dx, dy ] ) );
11636        },
11637        nw: function( event, dx, dy ) {
11638            return $.extend( this._change.n.apply( this, arguments ),
11639                this._change.w.apply( this, [ event, dx, dy ] ) );
11640        }
11641    },
11642
11643    _propagate: function( n, event ) {
11644        $.ui.plugin.call( this, n, [ event, this.ui() ] );
11645        if ( n !== "resize" ) {
11646            this._trigger( n, event, this.ui() );
11647        }
11648    },
11649
11650    plugins: {},
11651
11652    ui: function() {
11653        return {
11654            originalElement: this.originalElement,
11655            element: this.element,
11656            helper: this.helper,
11657            position: this.position,
11658            size: this.size,
11659            originalSize: this.originalSize,
11660            originalPosition: this.originalPosition
11661        };
11662    }
11663
11664} );
11665
11666/*
11667 * Resizable Extensions
11668 */
11669
11670$.ui.plugin.add( "resizable", "animate", {
11671
11672    stop: function( event ) {
11673        var that = $( this ).resizable( "instance" ),
11674            o = that.options,
11675            pr = that._proportionallyResizeElements,
11676            ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
11677            soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
11678            soffsetw = ista ? 0 : that.sizeDiff.width,
11679            style = {
11680                width: ( that.size.width - soffsetw ),
11681                height: ( that.size.height - soffseth )
11682            },
11683            left = ( parseFloat( that.element.css( "left" ) ) +
11684                ( that.position.left - that.originalPosition.left ) ) || null,
11685            top = ( parseFloat( that.element.css( "top" ) ) +
11686                ( that.position.top - that.originalPosition.top ) ) || null;
11687
11688        that.element.animate(
11689            $.extend( style, top && left ? { top: top, left: left } : {} ), {
11690                duration: o.animateDuration,
11691                easing: o.animateEasing,
11692                step: function() {
11693
11694                    var data = {
11695                        width: parseFloat( that.element.css( "width" ) ),
11696                        height: parseFloat( that.element.css( "height" ) ),
11697                        top: parseFloat( that.element.css( "top" ) ),
11698                        left: parseFloat( that.element.css( "left" ) )
11699                    };
11700
11701                    if ( pr && pr.length ) {
11702                        $( pr[ 0 ] ).css( { width: data.width, height: data.height } );
11703                    }
11704
11705                    // Propagating resize, and updating values for each animation step
11706                    that._updateCache( data );
11707                    that._propagate( "resize", event );
11708
11709                }
11710            }
11711        );
11712    }
11713
11714} );
11715
11716$.ui.plugin.add( "resizable", "containment", {
11717
11718    start: function() {
11719        var element, p, co, ch, cw, width, height,
11720            that = $( this ).resizable( "instance" ),
11721            o = that.options,
11722            el = that.element,
11723            oc = o.containment,
11724            ce = ( oc instanceof $ ) ?
11725                oc.get( 0 ) :
11726                ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
11727
11728        if ( !ce ) {
11729            return;
11730        }
11731
11732        that.containerElement = $( ce );
11733
11734        if ( /document/.test( oc ) || oc === document ) {
11735            that.containerOffset = {
11736                left: 0,
11737                top: 0
11738            };
11739            that.containerPosition = {
11740                left: 0,
11741                top: 0
11742            };
11743
11744            that.parentData = {
11745                element: $( document ),
11746                left: 0,
11747                top: 0,
11748                width: $( document ).width(),
11749                height: $( document ).height() || document.body.parentNode.scrollHeight
11750            };
11751        } else {
11752            element = $( ce );
11753            p = [];
11754            $( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
11755                p[ i ] = that._num( element.css( "padding" + name ) );
11756            } );
11757
11758            that.containerOffset = element.offset();
11759            that.containerPosition = element.position();
11760            that.containerSize = {
11761                height: ( element.innerHeight() - p[ 3 ] ),
11762                width: ( element.innerWidth() - p[ 1 ] )
11763            };
11764
11765            co = that.containerOffset;
11766            ch = that.containerSize.height;
11767            cw = that.containerSize.width;
11768            width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw );
11769            height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch );
11770
11771            that.parentData = {
11772                element: ce,
11773                left: co.left,
11774                top: co.top,
11775                width: width,
11776                height: height
11777            };
11778        }
11779    },
11780
11781    resize: function( event ) {
11782        var woset, hoset, isParent, isOffsetRelative,
11783            that = $( this ).resizable( "instance" ),
11784            o = that.options,
11785            co = that.containerOffset,
11786            cp = that.position,
11787            pRatio = that._aspectRatio || event.shiftKey,
11788            cop = {
11789                top: 0,
11790                left: 0
11791            },
11792            ce = that.containerElement,
11793            continueResize = true;
11794
11795        if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
11796            cop = co;
11797        }
11798
11799        if ( cp.left < ( that._helper ? co.left : 0 ) ) {
11800            that.size.width = that.size.width +
11801                ( that._helper ?
11802                    ( that.position.left - co.left ) :
11803                    ( that.position.left - cop.left ) );
11804
11805            if ( pRatio ) {
11806                that.size.height = that.size.width / that.aspectRatio;
11807                continueResize = false;
11808            }
11809            that.position.left = o.helper ? co.left : 0;
11810        }
11811
11812        if ( cp.top < ( that._helper ? co.top : 0 ) ) {
11813            that.size.height = that.size.height +
11814                ( that._helper ?
11815                    ( that.position.top - co.top ) :
11816                    that.position.top );
11817
11818            if ( pRatio ) {
11819                that.size.width = that.size.height * that.aspectRatio;
11820                continueResize = false;
11821            }
11822            that.position.top = that._helper ? co.top : 0;
11823        }
11824
11825        isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
11826        isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
11827
11828        if ( isParent && isOffsetRelative ) {
11829            that.offset.left = that.parentData.left + that.position.left;
11830            that.offset.top = that.parentData.top + that.position.top;
11831        } else {
11832            that.offset.left = that.element.offset().left;
11833            that.offset.top = that.element.offset().top;
11834        }
11835
11836        woset = Math.abs( that.sizeDiff.width +
11837            ( that._helper ?
11838                that.offset.left - cop.left :
11839                ( that.offset.left - co.left ) ) );
11840
11841        hoset = Math.abs( that.sizeDiff.height +
11842            ( that._helper ?
11843                that.offset.top - cop.top :
11844                ( that.offset.top - co.top ) ) );
11845
11846        if ( woset + that.size.width >= that.parentData.width ) {
11847            that.size.width = that.parentData.width - woset;
11848            if ( pRatio ) {
11849                that.size.height = that.size.width / that.aspectRatio;
11850                continueResize = false;
11851            }
11852        }
11853
11854        if ( hoset + that.size.height >= that.parentData.height ) {
11855            that.size.height = that.parentData.height - hoset;
11856            if ( pRatio ) {
11857                that.size.width = that.size.height * that.aspectRatio;
11858                continueResize = false;
11859            }
11860        }
11861
11862        if ( !continueResize ) {
11863            that.position.left = that.prevPosition.left;
11864            that.position.top = that.prevPosition.top;
11865            that.size.width = that.prevSize.width;
11866            that.size.height = that.prevSize.height;
11867        }
11868    },
11869
11870    stop: function() {
11871        var that = $( this ).resizable( "instance" ),
11872            o = that.options,
11873            co = that.containerOffset,
11874            cop = that.containerPosition,
11875            ce = that.containerElement,
11876            helper = $( that.helper ),
11877            ho = helper.offset(),
11878            w = helper.outerWidth() - that.sizeDiff.width,
11879            h = helper.outerHeight() - that.sizeDiff.height;
11880
11881        if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
11882            $( this ).css( {
11883                left: ho.left - cop.left - co.left,
11884                width: w,
11885                height: h
11886            } );
11887        }
11888
11889        if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
11890            $( this ).css( {
11891                left: ho.left - cop.left - co.left,
11892                width: w,
11893                height: h
11894            } );
11895        }
11896    }
11897} );
11898
11899$.ui.plugin.add( "resizable", "alsoResize", {
11900
11901    start: function() {
11902        var that = $( this ).resizable( "instance" ),
11903            o = that.options;
11904
11905        $( o.alsoResize ).each( function() {
11906            var el = $( this ),
11907                elSize = that._calculateAdjustedElementDimensions( el );
11908
11909            el.data( "ui-resizable-alsoresize", {
11910                width: elSize.width, height: elSize.height,
11911                left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
11912            } );
11913        } );
11914    },
11915
11916    resize: function( event, ui ) {
11917        var that = $( this ).resizable( "instance" ),
11918            o = that.options,
11919            os = that.originalSize,
11920            op = that.originalPosition,
11921            delta = {
11922                height: ( that.size.height - os.height ) || 0,
11923                width: ( that.size.width - os.width ) || 0,
11924                top: ( that.position.top - op.top ) || 0,
11925                left: ( that.position.left - op.left ) || 0
11926            };
11927
11928            $( o.alsoResize ).each( function() {
11929                var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
11930                    css = el.parents( ui.originalElement[ 0 ] ).length ?
11931                            [ "width", "height" ] :
11932                            [ "width", "height", "top", "left" ];
11933
11934                $.each( css, function( i, prop ) {
11935                    var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
11936                    if ( sum && sum >= 0 ) {
11937                        style[ prop ] = sum || null;
11938                    }
11939                } );
11940
11941                el.css( style );
11942            } );
11943    },
11944
11945    stop: function() {
11946        $( this ).removeData( "ui-resizable-alsoresize" );
11947    }
11948} );
11949
11950$.ui.plugin.add( "resizable", "ghost", {
11951
11952    start: function() {
11953
11954        var that = $( this ).resizable( "instance" ), cs = that.size;
11955
11956        that.ghost = that.originalElement.clone();
11957        that.ghost.css( {
11958            opacity: 0.25,
11959            display: "block",
11960            position: "relative",
11961            height: cs.height,
11962            width: cs.width,
11963            margin: 0,
11964            left: 0,
11965            top: 0
11966        } );
11967
11968        that._addClass( that.ghost, "ui-resizable-ghost" );
11969
11970        // DEPRECATED
11971        // TODO: remove after 1.12
11972        if ( $.uiBackCompat === true && typeof that.options.ghost === "string" ) {
11973
11974            // Ghost option
11975            that.ghost.addClass( this.options.ghost );
11976        }
11977
11978        that.ghost.appendTo( that.helper );
11979
11980    },
11981
11982    resize: function() {
11983        var that = $( this ).resizable( "instance" );
11984        if ( that.ghost ) {
11985            that.ghost.css( {
11986                position: "relative",
11987                height: that.size.height,
11988                width: that.size.width
11989            } );
11990        }
11991    },
11992
11993    stop: function() {
11994        var that = $( this ).resizable( "instance" );
11995        if ( that.ghost && that.helper ) {
11996            that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
11997        }
11998    }
11999
12000} );
12001
12002$.ui.plugin.add( "resizable", "grid", {
12003
12004    resize: function() {
12005        var outerDimensions,
12006            that = $( this ).resizable( "instance" ),
12007            o = that.options,
12008            cs = that.size,
12009            os = that.originalSize,
12010            op = that.originalPosition,
12011            a = that.axis,
12012            grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
12013            gridX = ( grid[ 0 ] || 1 ),
12014            gridY = ( grid[ 1 ] || 1 ),
12015            ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
12016            oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
12017            newWidth = os.width + ox,
12018            newHeight = os.height + oy,
12019            isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
12020            isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
12021            isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
12022            isMinHeight = o.minHeight && ( o.minHeight > newHeight );
12023
12024        o.grid = grid;
12025
12026        if ( isMinWidth ) {
12027            newWidth += gridX;
12028        }
12029        if ( isMinHeight ) {
12030            newHeight += gridY;
12031        }
12032        if ( isMaxWidth ) {
12033            newWidth -= gridX;
12034        }
12035        if ( isMaxHeight ) {
12036            newHeight -= gridY;
12037        }
12038
12039        if ( /^(se|s|e)$/.test( a ) ) {
12040            that.size.width = newWidth;
12041            that.size.height = newHeight;
12042        } else if ( /^(ne)$/.test( a ) ) {
12043            that.size.width = newWidth;
12044            that.size.height = newHeight;
12045            that.position.top = op.top - oy;
12046        } else if ( /^(sw)$/.test( a ) ) {
12047            that.size.width = newWidth;
12048            that.size.height = newHeight;
12049            that.position.left = op.left - ox;
12050        } else {
12051            if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
12052                outerDimensions = that._getPaddingPlusBorderDimensions( this );
12053            }
12054
12055            if ( newHeight - gridY > 0 ) {
12056                that.size.height = newHeight;
12057                that.position.top = op.top - oy;
12058            } else {
12059                newHeight = gridY - outerDimensions.height;
12060                that.size.height = newHeight;
12061                that.position.top = op.top + os.height - newHeight;
12062            }
12063            if ( newWidth - gridX > 0 ) {
12064                that.size.width = newWidth;
12065                that.position.left = op.left - ox;
12066            } else {
12067                newWidth = gridX - outerDimensions.width;
12068                that.size.width = newWidth;
12069                that.position.left = op.left + os.width - newWidth;
12070            }
12071        }
12072    }
12073
12074} );
12075
12076var widgetsResizable = $.ui.resizable;
12077
12078
12079/*!
12080 * jQuery UI Dialog 1.14.1
12081 * https://jqueryui.com
12082 *
12083 * Copyright OpenJS Foundation and other contributors
12084 * Released under the MIT license.
12085 * https://jquery.org/license
12086 */
12087
12088//>>label: Dialog
12089//>>group: Widgets
12090//>>description: Displays customizable dialog windows.
12091//>>docs: https://api.jqueryui.com/dialog/
12092//>>demos: https://jqueryui.com/dialog/
12093//>>css.structure: ../../themes/base/core.css
12094//>>css.structure: ../../themes/base/dialog.css
12095//>>css.theme: ../../themes/base/theme.css
12096
12097
12098$.widget( "ui.dialog", {
12099    version: "1.14.1",
12100    options: {
12101        appendTo: "body",
12102        autoOpen: true,
12103        buttons: [],
12104        classes: {
12105            "ui-dialog": "ui-corner-all",
12106            "ui-dialog-titlebar": "ui-corner-all"
12107        },
12108        closeOnEscape: true,
12109        closeText: "Close",
12110        draggable: true,
12111        hide: null,
12112        height: "auto",
12113        maxHeight: null,
12114        maxWidth: null,
12115        minHeight: 150,
12116        minWidth: 150,
12117        modal: false,
12118        position: {
12119            my: "center",
12120            at: "center",
12121            of: window,
12122            collision: "fit",
12123
12124            // Ensure the titlebar is always visible
12125            using: function( pos ) {
12126                var topOffset = $( this ).css( pos ).offset().top;
12127                if ( topOffset < 0 ) {
12128                    $( this ).css( "top", pos.top - topOffset );
12129                }
12130            }
12131        },
12132        resizable: true,
12133        show: null,
12134        title: null,
12135        uiDialogTitleHeadingLevel: 0,
12136        width: 300,
12137
12138        // Callbacks
12139        beforeClose: null,
12140        close: null,
12141        drag: null,
12142        dragStart: null,
12143        dragStop: null,
12144        focus: null,
12145        open: null,
12146        resize: null,
12147        resizeStart: null,
12148        resizeStop: null
12149    },
12150
12151    sizeRelatedOptions: {
12152        buttons: true,
12153        height: true,
12154        maxHeight: true,
12155        maxWidth: true,
12156        minHeight: true,
12157        minWidth: true,
12158        width: true
12159    },
12160
12161    resizableRelatedOptions: {
12162        maxHeight: true,
12163        maxWidth: true,
12164        minHeight: true,
12165        minWidth: true
12166    },
12167
12168    _create: function() {
12169        this.originalCss = {
12170            display: this.element[ 0 ].style.display,
12171            width: this.element[ 0 ].style.width,
12172            minHeight: this.element[ 0 ].style.minHeight,
12173            maxHeight: this.element[ 0 ].style.maxHeight,
12174            height: this.element[ 0 ].style.height
12175        };
12176        this.originalPosition = {
12177            parent: this.element.parent(),
12178            index: this.element.parent().children().index( this.element )
12179        };
12180        this.originalTitle = this.element.attr( "title" );
12181        if ( this.options.title == null && this.originalTitle != null ) {
12182            this.options.title = this.originalTitle;
12183        }
12184
12185        // Dialogs can't be disabled
12186        if ( this.options.disabled ) {
12187            this.options.disabled = false;
12188        }
12189
12190        this._createWrapper();
12191
12192        this.element
12193            .show()
12194            .removeAttr( "title" )
12195            .appendTo( this.uiDialog );
12196
12197        this._addClass( "ui-dialog-content", "ui-widget-content" );
12198
12199        this._createTitlebar();
12200        this._createButtonPane();
12201
12202        if ( this.options.draggable && $.fn.draggable ) {
12203            this._makeDraggable();
12204        }
12205        if ( this.options.resizable && $.fn.resizable ) {
12206            this._makeResizable();
12207        }
12208
12209        this._isOpen = false;
12210
12211        this._trackFocus();
12212    },
12213
12214    _init: function() {
12215        if ( this.options.autoOpen ) {
12216            this.open();
12217        }
12218    },
12219
12220    _appendTo: function() {
12221        var element = this.options.appendTo;
12222        if ( element && ( element.jquery || element.nodeType ) ) {
12223            return $( element );
12224        }
12225        return this.document.find( element || "body" ).eq( 0 );
12226    },
12227
12228    _destroy: function() {
12229        var next,
12230            originalPosition = this.originalPosition;
12231
12232        this._untrackInstance();
12233        this._destroyOverlay();
12234
12235        this.element
12236            .removeUniqueId()
12237            .css( this.originalCss )
12238
12239            // Without detaching first, the following becomes really slow
12240            .detach();
12241
12242        this.uiDialog.remove();
12243
12244        if ( this.originalTitle ) {
12245            this.element.attr( "title", this.originalTitle );
12246        }
12247
12248        next = originalPosition.parent.children().eq( originalPosition.index );
12249
12250        // Don't try to place the dialog next to itself (#8613)
12251        if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
12252            next.before( this.element );
12253        } else {
12254            originalPosition.parent.append( this.element );
12255        }
12256    },
12257
12258    widget: function() {
12259        return this.uiDialog;
12260    },
12261
12262    disable: $.noop,
12263    enable: $.noop,
12264
12265    close: function( event ) {
12266        var that = this;
12267
12268        if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
12269            return;
12270        }
12271
12272        this._isOpen = false;
12273        this._focusedElement = null;
12274        this._destroyOverlay();
12275        this._untrackInstance();
12276
12277        if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
12278
12279            // Hiding a focused element doesn't trigger blur in WebKit
12280            // so in case we have nothing to focus on, explicitly blur the active element
12281            // https://bugs.webkit.org/show_bug.cgi?id=47182
12282            $( this.document[ 0 ].activeElement ).trigger( "blur" );
12283        }
12284
12285        this._hide( this.uiDialog, this.options.hide, function() {
12286            that._trigger( "close", event );
12287        } );
12288    },
12289
12290    isOpen: function() {
12291        return this._isOpen;
12292    },
12293
12294    moveToTop: function() {
12295        this._moveToTop();
12296    },
12297
12298    _moveToTop: function( event, silent ) {
12299        var moved = false,
12300            zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
12301                return +$( this ).css( "z-index" );
12302            } ).get(),
12303            zIndexMax = Math.max.apply( null, zIndices );
12304
12305        if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
12306            this.uiDialog.css( "z-index", zIndexMax + 1 );
12307            moved = true;
12308        }
12309
12310        if ( moved && !silent ) {
12311            this._trigger( "focus", event );
12312        }
12313        return moved;
12314    },
12315
12316    open: function() {
12317        var that = this;
12318        if ( this._isOpen ) {
12319            if ( this._moveToTop() ) {
12320                this._focusTabbable();
12321            }
12322            return;
12323        }
12324
12325        this._isOpen = true;
12326        this.opener = $( this.document[ 0 ].activeElement );
12327
12328        this._size();
12329        this._position();
12330        this._createOverlay();
12331        this._moveToTop( null, true );
12332
12333        // Ensure the overlay is moved to the top with the dialog, but only when
12334        // opening. The overlay shouldn't move after the dialog is open so that
12335        // modeless dialogs opened after the modal dialog stack properly.
12336        if ( this.overlay ) {
12337            this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
12338        }
12339
12340        this._show( this.uiDialog, this.options.show, function() {
12341            that._focusTabbable();
12342            that._trigger( "focus" );
12343        } );
12344
12345        // Track the dialog immediately upon opening in case a focus event
12346        // somehow occurs outside of the dialog before an element inside the
12347        // dialog is focused (#10152)
12348        this._makeFocusTarget();
12349
12350        this._trigger( "open" );
12351    },
12352
12353    _focusTabbable: function() {
12354
12355        // Set focus to the first match:
12356        // 1. An element that was focused previously
12357        // 2. First element inside the dialog matching [autofocus]
12358        // 3. Tabbable element inside the content element
12359        // 4. Tabbable element inside the buttonpane
12360        // 5. The close button
12361        // 6. The dialog itself
12362        var hasFocus = this._focusedElement;
12363        if ( !hasFocus ) {
12364            hasFocus = this.element.find( "[autofocus]" );
12365        }
12366        if ( !hasFocus.length ) {
12367            hasFocus = this.element.find( ":tabbable" );
12368        }
12369        if ( !hasFocus.length ) {
12370            hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
12371        }
12372        if ( !hasFocus.length ) {
12373            hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
12374        }
12375        if ( !hasFocus.length ) {
12376            hasFocus = this.uiDialog;
12377        }
12378        hasFocus.eq( 0 ).trigger( "focus" );
12379    },
12380
12381    _restoreTabbableFocus: function() {
12382        var activeElement = this.document[ 0 ].activeElement,
12383            isActive = this.uiDialog[ 0 ] === activeElement ||
12384                $.contains( this.uiDialog[ 0 ], activeElement );
12385        if ( !isActive ) {
12386            this._focusTabbable();
12387        }
12388    },
12389
12390    _keepFocus: function( event ) {
12391        event.preventDefault();
12392        this._restoreTabbableFocus();
12393    },
12394
12395    _createWrapper: function() {
12396        this.uiDialog = $( "<div>" )
12397            .hide()
12398            .attr( {
12399
12400                // Setting tabIndex makes the div focusable
12401                tabIndex: -1,
12402                role: "dialog",
12403                "aria-modal": this.options.modal ? "true" : null
12404            } )
12405            .appendTo( this._appendTo() );
12406
12407        this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
12408        this._on( this.uiDialog, {
12409            keydown: function( event ) {
12410                if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
12411                        event.keyCode === $.ui.keyCode.ESCAPE ) {
12412                    event.preventDefault();
12413                    this.close( event );
12414                    return;
12415                }
12416
12417                // Prevent tabbing out of dialogs
12418                if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
12419                    return;
12420                }
12421                var tabbables = this.uiDialog.find( ":tabbable" ),
12422                    first = tabbables.first(),
12423                    last = tabbables.last();
12424
12425                if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
12426                        !event.shiftKey ) {
12427                    this._delay( function() {
12428                        first.trigger( "focus" );
12429                    } );
12430                    event.preventDefault();
12431                } else if ( ( event.target === first[ 0 ] ||
12432                        event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
12433                    this._delay( function() {
12434                        last.trigger( "focus" );
12435                    } );
12436                    event.preventDefault();
12437                }
12438            },
12439            mousedown: function( event ) {
12440                if ( this._moveToTop( event ) ) {
12441                    this._focusTabbable();
12442                }
12443            }
12444        } );
12445
12446        // We assume that any existing aria-describedby attribute means
12447        // that the dialog content is marked up properly
12448        // otherwise we brute force the content as the description
12449        if ( !this.element.find( "[aria-describedby]" ).length ) {
12450            this.uiDialog.attr( {
12451                "aria-describedby": this.element.uniqueId().attr( "id" )
12452            } );
12453        }
12454    },
12455
12456    _createTitlebar: function() {
12457        var uiDialogTitle;
12458
12459        this.uiDialogTitlebar = $( "<div>" );
12460        this._addClass( this.uiDialogTitlebar,
12461            "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
12462        this._on( this.uiDialogTitlebar, {
12463            mousedown: function( event ) {
12464
12465                // Don't prevent click on close button (#8838)
12466                // Focusing a dialog that is partially scrolled out of view
12467                // causes the browser to scroll it into view, preventing the click event
12468                if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
12469
12470                    // Dialog isn't getting focus when dragging (#8063)
12471                    this.uiDialog.trigger( "focus" );
12472                }
12473            }
12474        } );
12475
12476        this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
12477            .button( {
12478                label: $( "<a>" ).text( this.options.closeText ).html(),
12479                icon: "ui-icon-closethick",
12480                showLabel: false
12481            } )
12482            .appendTo( this.uiDialogTitlebar );
12483
12484        this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
12485        this._on( this.uiDialogTitlebarClose, {
12486            click: function( event ) {
12487                event.preventDefault();
12488                this.close( event );
12489            }
12490        } );
12491
12492        var uiDialogHeadingLevel = Number.isInteger( this.options.uiDialogTitleHeadingLevel ) &&
12493            this.options.uiDialogTitleHeadingLevel > 0 &&
12494            this.options.uiDialogTitleHeadingLevel <= 6 ?
12495            "h" + this.options.uiDialogTitleHeadingLevel : "span";
12496
12497        uiDialogTitle = $( "<" + uiDialogHeadingLevel + ">" )
12498            .uniqueId().prependTo( this.uiDialogTitlebar );
12499        this._addClass( uiDialogTitle, "ui-dialog-title" );
12500        this._title( uiDialogTitle );
12501
12502        this.uiDialogTitlebar.prependTo( this.uiDialog );
12503
12504        this.uiDialog.attr( {
12505            "aria-labelledby": uiDialogTitle.attr( "id" )
12506        } );
12507    },
12508
12509    _title: function( title ) {
12510        if ( this.options.title ) {
12511            title.text( this.options.title );
12512        } else {
12513            title.html( "&#160;" );
12514        }
12515    },
12516
12517    _createButtonPane: function() {
12518        this.uiDialogButtonPane = $( "<div>" );
12519        this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
12520            "ui-widget-content ui-helper-clearfix" );
12521
12522        this.uiButtonSet = $( "<div>" )
12523            .appendTo( this.uiDialogButtonPane );
12524        this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
12525
12526        this._createButtons();
12527    },
12528
12529    _createButtons: function() {
12530        var that = this,
12531            buttons = this.options.buttons;
12532
12533        // If we already have a button pane, remove it
12534        this.uiDialogButtonPane.remove();
12535        this.uiButtonSet.empty();
12536
12537        if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) {
12538            this._removeClass( this.uiDialog, "ui-dialog-buttons" );
12539            return;
12540        }
12541
12542        $.each( buttons, function( name, props ) {
12543            var click, buttonOptions;
12544            props = typeof props === "function" ?
12545                { click: props, text: name } :
12546                props;
12547
12548            // Default to a non-submitting button
12549            props = $.extend( { type: "button" }, props );
12550
12551            // Change the context for the click callback to be the main element
12552            click = props.click;
12553            buttonOptions = {
12554                icon: props.icon,
12555                iconPosition: props.iconPosition,
12556                showLabel: props.showLabel,
12557
12558                // Deprecated options
12559                icons: props.icons,
12560                text: props.text
12561            };
12562
12563            delete props.click;
12564            delete props.icon;
12565            delete props.iconPosition;
12566            delete props.showLabel;
12567
12568            // Deprecated options
12569            delete props.icons;
12570            if ( typeof props.text === "boolean" ) {
12571                delete props.text;
12572            }
12573
12574            $( "<button></button>", props )
12575                .button( buttonOptions )
12576                .appendTo( that.uiButtonSet )
12577                .on( "click", function() {
12578                    click.apply( that.element[ 0 ], arguments );
12579                } );
12580        } );
12581        this._addClass( this.uiDialog, "ui-dialog-buttons" );
12582        this.uiDialogButtonPane.appendTo( this.uiDialog );
12583    },
12584
12585    _makeDraggable: function() {
12586        var that = this,
12587            options = this.options;
12588
12589        function filteredUi( ui ) {
12590            return {
12591                position: ui.position,
12592                offset: ui.offset
12593            };
12594        }
12595
12596        this.uiDialog.draggable( {
12597            cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
12598            handle: ".ui-dialog-titlebar",
12599            containment: "document",
12600            start: function( event, ui ) {
12601                that._addClass( $( this ), "ui-dialog-dragging" );
12602                that._blockFrames();
12603                that._trigger( "dragStart", event, filteredUi( ui ) );
12604            },
12605            drag: function( event, ui ) {
12606                that._trigger( "drag", event, filteredUi( ui ) );
12607            },
12608            stop: function( event, ui ) {
12609                var left = ui.offset.left - that.document.scrollLeft(),
12610                    top = ui.offset.top - that.document.scrollTop();
12611
12612                options.position = {
12613                    my: "left top",
12614                    at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12615                        "top" + ( top >= 0 ? "+" : "" ) + top,
12616                    of: that.window
12617                };
12618                that._removeClass( $( this ), "ui-dialog-dragging" );
12619                that._unblockFrames();
12620                that._trigger( "dragStop", event, filteredUi( ui ) );
12621            }
12622        } );
12623    },
12624
12625    _makeResizable: function() {
12626        var that = this,
12627            options = this.options,
12628            handles = options.resizable,
12629
12630            // .ui-resizable has position: relative defined in the stylesheet
12631            // but dialogs have to use absolute or fixed positioning
12632            position = this.uiDialog.css( "position" ),
12633            resizeHandles = typeof handles === "string" ?
12634                handles :
12635                "n,e,s,w,se,sw,ne,nw";
12636
12637        function filteredUi( ui ) {
12638            return {
12639                originalPosition: ui.originalPosition,
12640                originalSize: ui.originalSize,
12641                position: ui.position,
12642                size: ui.size
12643            };
12644        }
12645
12646        this.uiDialog.resizable( {
12647            cancel: ".ui-dialog-content",
12648            containment: "document",
12649            alsoResize: this.element,
12650            maxWidth: options.maxWidth,
12651            maxHeight: options.maxHeight,
12652            minWidth: options.minWidth,
12653            minHeight: this._minHeight(),
12654            handles: resizeHandles,
12655            start: function( event, ui ) {
12656                that._addClass( $( this ), "ui-dialog-resizing" );
12657                that._blockFrames();
12658                that._trigger( "resizeStart", event, filteredUi( ui ) );
12659            },
12660            resize: function( event, ui ) {
12661                that._trigger( "resize", event, filteredUi( ui ) );
12662            },
12663            stop: function( event, ui ) {
12664                var offset = that.uiDialog.offset(),
12665                    left = offset.left - that.document.scrollLeft(),
12666                    top = offset.top - that.document.scrollTop();
12667
12668                options.height = that.uiDialog.height();
12669                options.width = that.uiDialog.width();
12670                options.position = {
12671                    my: "left top",
12672                    at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12673                        "top" + ( top >= 0 ? "+" : "" ) + top,
12674                    of: that.window
12675                };
12676                that._removeClass( $( this ), "ui-dialog-resizing" );
12677                that._unblockFrames();
12678                that._trigger( "resizeStop", event, filteredUi( ui ) );
12679            }
12680        } )
12681            .css( "position", position );
12682    },
12683
12684    _trackFocus: function() {
12685        this._on( this.widget(), {
12686            focusin: function( event ) {
12687                this._makeFocusTarget();
12688                this._focusedElement = $( event.target );
12689            }
12690        } );
12691    },
12692
12693    _makeFocusTarget: function() {
12694        this._untrackInstance();
12695        this._trackingInstances().unshift( this );
12696    },
12697
12698    _untrackInstance: function() {
12699        var instances = this._trackingInstances(),
12700            exists = $.inArray( this, instances );
12701        if ( exists !== -1 ) {
12702            instances.splice( exists, 1 );
12703        }
12704    },
12705
12706    _trackingInstances: function() {
12707        var instances = this.document.data( "ui-dialog-instances" );
12708        if ( !instances ) {
12709            instances = [];
12710            this.document.data( "ui-dialog-instances", instances );
12711        }
12712        return instances;
12713    },
12714
12715    _minHeight: function() {
12716        var options = this.options;
12717
12718        return options.height === "auto" ?
12719            options.minHeight :
12720            Math.min( options.minHeight, options.height );
12721    },
12722
12723    _position: function() {
12724
12725        // Need to show the dialog to get the actual offset in the position plugin
12726        var isVisible = this.uiDialog.is( ":visible" );
12727        if ( !isVisible ) {
12728            this.uiDialog.show();
12729        }
12730        this.uiDialog.position( this.options.position );
12731        if ( !isVisible ) {
12732            this.uiDialog.hide();
12733        }
12734    },
12735
12736    _setOptions: function( options ) {
12737        var that = this,
12738            resize = false,
12739            resizableOptions = {};
12740
12741        $.each( options, function( key, value ) {
12742            that._setOption( key, value );
12743
12744            if ( key in that.sizeRelatedOptions ) {
12745                resize = true;
12746            }
12747            if ( key in that.resizableRelatedOptions ) {
12748                resizableOptions[ key ] = value;
12749            }
12750        } );
12751
12752        if ( resize ) {
12753            this._size();
12754            this._position();
12755        }
12756        if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12757            this.uiDialog.resizable( "option", resizableOptions );
12758        }
12759    },
12760
12761    _setOption: function( key, value ) {
12762        var isDraggable, isResizable,
12763            uiDialog = this.uiDialog;
12764
12765        if ( key === "disabled" ) {
12766            return;
12767        }
12768
12769        this._super( key, value );
12770
12771        if ( key === "appendTo" ) {
12772            this.uiDialog.appendTo( this._appendTo() );
12773        }
12774
12775        if ( key === "buttons" ) {
12776            this._createButtons();
12777        }
12778
12779        if ( key === "closeText" ) {
12780            this.uiDialogTitlebarClose.button( {
12781
12782                // Ensure that we always pass a string
12783                label: $( "<a>" ).text( "" + this.options.closeText ).html()
12784            } );
12785        }
12786
12787        if ( key === "draggable" ) {
12788            isDraggable = uiDialog.is( ":data(ui-draggable)" );
12789            if ( isDraggable && !value ) {
12790                uiDialog.draggable( "destroy" );
12791            }
12792
12793            if ( !isDraggable && value ) {
12794                this._makeDraggable();
12795            }
12796        }
12797
12798        if ( key === "position" ) {
12799            this._position();
12800        }
12801
12802        if ( key === "resizable" ) {
12803
12804            // currently resizable, becoming non-resizable
12805            isResizable = uiDialog.is( ":data(ui-resizable)" );
12806            if ( isResizable && !value ) {
12807                uiDialog.resizable( "destroy" );
12808            }
12809
12810            // Currently resizable, changing handles
12811            if ( isResizable && typeof value === "string" ) {
12812                uiDialog.resizable( "option", "handles", value );
12813            }
12814
12815            // Currently non-resizable, becoming resizable
12816            if ( !isResizable && value !== false ) {
12817                this._makeResizable();
12818            }
12819        }
12820
12821        if ( key === "title" ) {
12822            this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
12823        }
12824
12825        if ( key === "modal" ) {
12826            uiDialog.attr( "aria-modal", value ? "true" : null );
12827        }
12828    },
12829
12830    _size: function() {
12831
12832        // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
12833        // divs will both have width and height set, so we need to reset them
12834        var nonContentHeight, minContentHeight, maxContentHeight,
12835            options = this.options;
12836
12837        // Reset content sizing
12838        this.element.show().css( {
12839            width: "auto",
12840            minHeight: 0,
12841            maxHeight: "none",
12842            height: 0
12843        } );
12844
12845        if ( options.minWidth > options.width ) {
12846            options.width = options.minWidth;
12847        }
12848
12849        // Reset wrapper sizing
12850        // determine the height of all the non-content elements
12851        nonContentHeight = this.uiDialog.css( {
12852            height: "auto",
12853            width: options.width
12854        } )
12855            .outerHeight();
12856        minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
12857        maxContentHeight = typeof options.maxHeight === "number" ?
12858            Math.max( 0, options.maxHeight - nonContentHeight ) :
12859            "none";
12860
12861        if ( options.height === "auto" ) {
12862            this.element.css( {
12863                minHeight: minContentHeight,
12864                maxHeight: maxContentHeight,
12865                height: "auto"
12866            } );
12867        } else {
12868            this.element.height( Math.max( 0, options.height - nonContentHeight ) );
12869        }
12870
12871        if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12872            this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
12873        }
12874    },
12875
12876    _blockFrames: function() {
12877        this.iframeBlocks = this.document.find( "iframe" ).map( function() {
12878            var iframe = $( this );
12879
12880            return $( "<div>" )
12881                .css( {
12882                    position: "absolute",
12883                    width: iframe.outerWidth(),
12884                    height: iframe.outerHeight()
12885                } )
12886                .appendTo( iframe.parent() )
12887                .offset( iframe.offset() )[ 0 ];
12888        } );
12889    },
12890
12891    _unblockFrames: function() {
12892        if ( this.iframeBlocks ) {
12893            this.iframeBlocks.remove();
12894            delete this.iframeBlocks;
12895        }
12896    },
12897
12898    _allowInteraction: function( event ) {
12899        if ( $( event.target ).closest( ".ui-dialog" ).length ) {
12900            return true;
12901        }
12902
12903        // TODO: Remove hack when datepicker implements
12904        // the .ui-front logic (#8989)
12905        return !!$( event.target ).closest( ".ui-datepicker" ).length;
12906    },
12907
12908    _createOverlay: function() {
12909        if ( !this.options.modal ) {
12910            return;
12911        }
12912
12913        // We use a delay in case the overlay is created from an
12914        // event that we're going to be cancelling (#2804)
12915        var isOpening = true;
12916        this._delay( function() {
12917            isOpening = false;
12918        } );
12919
12920        if ( !this.document.data( "ui-dialog-overlays" ) ) {
12921
12922            // Prevent use of anchors and inputs
12923            // This doesn't use `_on()` because it is a shared event handler
12924            // across all open modal dialogs.
12925            this.document.on( "focusin.ui-dialog", function( event ) {
12926                if ( isOpening ) {
12927                    return;
12928                }
12929
12930                var instance = this._trackingInstances()[ 0 ];
12931                if ( !instance._allowInteraction( event ) ) {
12932                    event.preventDefault();
12933                    instance._focusTabbable();
12934                }
12935            }.bind( this ) );
12936        }
12937
12938        this.overlay = $( "<div>" )
12939            .appendTo( this._appendTo() );
12940
12941        this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
12942        this._on( this.overlay, {
12943            mousedown: "_keepFocus"
12944        } );
12945        this.document.data( "ui-dialog-overlays",
12946            ( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
12947    },
12948
12949    _destroyOverlay: function() {
12950        if ( !this.options.modal ) {
12951            return;
12952        }
12953
12954        if ( this.overlay ) {
12955            var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
12956
12957            if ( !overlays ) {
12958                this.document.off( "focusin.ui-dialog" );
12959                this.document.removeData( "ui-dialog-overlays" );
12960            } else {
12961                this.document.data( "ui-dialog-overlays", overlays );
12962            }
12963
12964            this.overlay.remove();
12965            this.overlay = null;
12966        }
12967    }
12968} );
12969
12970// DEPRECATED
12971// TODO: switch return back to widget declaration at top of file when this is removed
12972if ( $.uiBackCompat === true ) {
12973
12974    // Backcompat for dialogClass option
12975    $.widget( "ui.dialog", $.ui.dialog, {
12976        options: {
12977            dialogClass: ""
12978        },
12979        _createWrapper: function() {
12980            this._super();
12981            this.uiDialog.addClass( this.options.dialogClass );
12982        },
12983        _setOption: function( key, value ) {
12984            if ( key === "dialogClass" ) {
12985                this.uiDialog
12986                    .removeClass( this.options.dialogClass )
12987                    .addClass( value );
12988            }
12989            this._superApply( arguments );
12990        }
12991    } );
12992}
12993
12994var widgetsDialog = $.ui.dialog;
12995
12996
12997/*!
12998 * jQuery UI Droppable 1.14.1
12999 * https://jqueryui.com
13000 *
13001 * Copyright OpenJS Foundation and other contributors
13002 * Released under the MIT license.
13003 * https://jquery.org/license
13004 */
13005
13006//>>label: Droppable
13007//>>group: Interactions
13008//>>description: Enables drop targets for draggable elements.
13009//>>docs: https://api.jqueryui.com/droppable/
13010//>>demos: https://jqueryui.com/droppable/
13011
13012
13013$.widget( "ui.droppable", {
13014    version: "1.14.1",
13015    widgetEventPrefix: "drop",
13016    options: {
13017        accept: "*",
13018        addClasses: true,
13019        greedy: false,
13020        scope: "default",
13021        tolerance: "intersect",
13022
13023        // Callbacks
13024        activate: null,
13025        deactivate: null,
13026        drop: null,
13027        out: null,
13028        over: null
13029    },
13030    _create: function() {
13031
13032        var proportions,
13033            o = this.options,
13034            accept = o.accept;
13035
13036        this.isover = false;
13037        this.isout = true;
13038
13039        this.accept = typeof accept === "function" ? accept : function( d ) {
13040            return d.is( accept );
13041        };
13042
13043        this.proportions = function( /* valueToWrite */ ) {
13044            if ( arguments.length ) {
13045
13046                // Store the droppable's proportions
13047                proportions = arguments[ 0 ];
13048            } else {
13049
13050                // Retrieve or derive the droppable's proportions
13051                return proportions ?
13052                    proportions :
13053                    proportions = {
13054                        width: this.element[ 0 ].offsetWidth,
13055                        height: this.element[ 0 ].offsetHeight
13056                    };
13057            }
13058        };
13059
13060        this._addToManager( o.scope );
13061
13062        if ( o.addClasses ) {
13063            this._addClass( "ui-droppable" );
13064        }
13065
13066    },
13067
13068    _addToManager: function( scope ) {
13069
13070        // Add the reference and positions to the manager
13071        $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
13072        $.ui.ddmanager.droppables[ scope ].push( this );
13073    },
13074
13075    _splice: function( drop ) {
13076        var i = 0;
13077        for ( ; i < drop.length; i++ ) {
13078            if ( drop[ i ] === this ) {
13079                drop.splice( i, 1 );
13080            }
13081        }
13082    },
13083
13084    _destroy: function() {
13085        var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13086
13087        this._splice( drop );
13088    },
13089
13090    _setOption: function( key, value ) {
13091
13092        if ( key === "accept" ) {
13093            this.accept = typeof value === "function" ? value : function( d ) {
13094                return d.is( value );
13095            };
13096        } else if ( key === "scope" ) {
13097            var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13098
13099            this._splice( drop );
13100            this._addToManager( value );
13101        }
13102
13103        this._super( key, value );
13104    },
13105
13106    _activate: function( event ) {
13107        var draggable = $.ui.ddmanager.current;
13108
13109        this._addActiveClass();
13110        if ( draggable ) {
13111            this._trigger( "activate", event, this.ui( draggable ) );
13112        }
13113    },
13114
13115    _deactivate: function( event ) {
13116        var draggable = $.ui.ddmanager.current;
13117
13118        this._removeActiveClass();
13119        if ( draggable ) {
13120            this._trigger( "deactivate", event, this.ui( draggable ) );
13121        }
13122    },
13123
13124    _over: function( event ) {
13125
13126        var draggable = $.ui.ddmanager.current;
13127
13128        // Bail if draggable and droppable are same element
13129        if ( !draggable || ( draggable.currentItem ||
13130                draggable.element )[ 0 ] === this.element[ 0 ] ) {
13131            return;
13132        }
13133
13134        if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13135                draggable.element ) ) ) {
13136            this._addHoverClass();
13137            this._trigger( "over", event, this.ui( draggable ) );
13138        }
13139
13140    },
13141
13142    _out: function( event ) {
13143
13144        var draggable = $.ui.ddmanager.current;
13145
13146        // Bail if draggable and droppable are same element
13147        if ( !draggable || ( draggable.currentItem ||
13148                draggable.element )[ 0 ] === this.element[ 0 ] ) {
13149            return;
13150        }
13151
13152        if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13153                draggable.element ) ) ) {
13154            this._removeHoverClass();
13155            this._trigger( "out", event, this.ui( draggable ) );
13156        }
13157
13158    },
13159
13160    _drop: function( event, custom ) {
13161
13162        var draggable = custom || $.ui.ddmanager.current,
13163            childrenIntersection = false;
13164
13165        // Bail if draggable and droppable are same element
13166        if ( !draggable || ( draggable.currentItem ||
13167                draggable.element )[ 0 ] === this.element[ 0 ] ) {
13168            return false;
13169        }
13170
13171        this.element
13172            .find( ":data(ui-droppable)" )
13173            .not( ".ui-draggable-dragging" )
13174            .each( function() {
13175                var inst = $( this ).droppable( "instance" );
13176                if (
13177                    inst.options.greedy &&
13178                    !inst.options.disabled &&
13179                    inst.options.scope === draggable.options.scope &&
13180                    inst.accept.call(
13181                        inst.element[ 0 ], ( draggable.currentItem || draggable.element )
13182                    ) &&
13183                    $.ui.intersect(
13184                        draggable,
13185                        $.extend( inst, { offset: inst.element.offset() } ),
13186                        inst.options.tolerance, event
13187                    )
13188                ) {
13189                    childrenIntersection = true;
13190                    return false;
13191                }
13192            } );
13193        if ( childrenIntersection ) {
13194            return false;
13195        }
13196
13197        if ( this.accept.call( this.element[ 0 ],
13198                ( draggable.currentItem || draggable.element ) ) ) {
13199            this._removeActiveClass();
13200            this._removeHoverClass();
13201
13202            this._trigger( "drop", event, this.ui( draggable ) );
13203            return this.element;
13204        }
13205
13206        return false;
13207
13208    },
13209
13210    ui: function( c ) {
13211        return {
13212            draggable: ( c.currentItem || c.element ),
13213            helper: c.helper,
13214            position: c.position,
13215            offset: c.positionAbs
13216        };
13217    },
13218
13219    // Extension points just to make backcompat sane and avoid duplicating logic
13220    // TODO: Remove in 1.14 along with call to it below
13221    _addHoverClass: function() {
13222        this._addClass( "ui-droppable-hover" );
13223    },
13224
13225    _removeHoverClass: function() {
13226        this._removeClass( "ui-droppable-hover" );
13227    },
13228
13229    _addActiveClass: function() {
13230        this._addClass( "ui-droppable-active" );
13231    },
13232
13233    _removeActiveClass: function() {
13234        this._removeClass( "ui-droppable-active" );
13235    }
13236} );
13237
13238$.ui.intersect = ( function() {
13239    function isOverAxis( x, reference, size ) {
13240        return ( x >= reference ) && ( x < ( reference + size ) );
13241    }
13242
13243    return function( draggable, droppable, toleranceMode, event ) {
13244
13245        if ( !droppable.offset ) {
13246            return false;
13247        }
13248
13249        var x1 = ( draggable.positionAbs ||
13250                draggable.position.absolute ).left + draggable.margins.left,
13251            y1 = ( draggable.positionAbs ||
13252                draggable.position.absolute ).top + draggable.margins.top,
13253            x2 = x1 + draggable.helperProportions.width,
13254            y2 = y1 + draggable.helperProportions.height,
13255            l = droppable.offset.left,
13256            t = droppable.offset.top,
13257            r = l + droppable.proportions().width,
13258            b = t + droppable.proportions().height;
13259
13260        switch ( toleranceMode ) {
13261        case "fit":
13262            return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
13263        case "intersect":
13264            return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
13265                x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
13266                t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
13267                y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
13268        case "pointer":
13269            return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
13270                isOverAxis( event.pageX, l, droppable.proportions().width );
13271        case "touch":
13272            return (
13273                ( y1 >= t && y1 <= b ) || // Top edge touching
13274                ( y2 >= t && y2 <= b ) || // Bottom edge touching
13275                ( y1 < t && y2 > b ) // Surrounded vertically
13276            ) && (
13277                ( x1 >= l && x1 <= r ) || // Left edge touching
13278                ( x2 >= l && x2 <= r ) || // Right edge touching
13279                ( x1 < l && x2 > r ) // Surrounded horizontally
13280            );
13281        default:
13282            return false;
13283        }
13284    };
13285} )();
13286
13287/*
13288    This manager tracks offsets of draggables and droppables
13289*/
13290$.ui.ddmanager = {
13291    current: null,
13292    droppables: { "default": [] },
13293    prepareOffsets: function( t, event ) {
13294
13295        var i, j,
13296            m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
13297            type = event ? event.type : null, // workaround for #2317
13298            list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
13299
13300        droppablesLoop: for ( i = 0; i < m.length; i++ ) {
13301
13302            // No disabled and non-accepted
13303            if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
13304                    ( t.currentItem || t.element ) ) ) ) {
13305                continue;
13306            }
13307
13308            // Filter out elements in the current dragged item
13309            for ( j = 0; j < list.length; j++ ) {
13310                if ( list[ j ] === m[ i ].element[ 0 ] ) {
13311                    m[ i ].proportions().height = 0;
13312                    continue droppablesLoop;
13313                }
13314            }
13315
13316            m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
13317            if ( !m[ i ].visible ) {
13318                continue;
13319            }
13320
13321            // Activate the droppable if used directly from draggables
13322            if ( type === "mousedown" ) {
13323                m[ i ]._activate.call( m[ i ], event );
13324            }
13325
13326            m[ i ].offset = m[ i ].element.offset();
13327            m[ i ].proportions( {
13328                width: m[ i ].element[ 0 ].offsetWidth,
13329                height: m[ i ].element[ 0 ].offsetHeight
13330            } );
13331
13332        }
13333
13334    },
13335    drop: function( draggable, event ) {
13336
13337        var dropped = false;
13338
13339        // Create a copy of the droppables in case the list changes during the drop (#9116)
13340        $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
13341
13342            if ( !this.options ) {
13343                return;
13344            }
13345            if ( !this.options.disabled && this.visible &&
13346                    $.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
13347                dropped = this._drop.call( this, event ) || dropped;
13348            }
13349
13350            if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
13351                    ( draggable.currentItem || draggable.element ) ) ) {
13352                this.isout = true;
13353                this.isover = false;
13354                this._deactivate.call( this, event );
13355            }
13356
13357        } );
13358        return dropped;
13359
13360    },
13361    dragStart: function( draggable, event ) {
13362
13363        // Listen for scrolling so that if the dragging causes scrolling the position of the
13364        // droppables can be recalculated (see #5003)
13365        draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
13366            if ( !draggable.options.refreshPositions ) {
13367                $.ui.ddmanager.prepareOffsets( draggable, event );
13368            }
13369        } );
13370    },
13371    drag: function( draggable, event ) {
13372
13373        // If you have a highly dynamic page, you might try this option. It renders positions
13374        // every time you move the mouse.
13375        if ( draggable.options.refreshPositions ) {
13376            $.ui.ddmanager.prepareOffsets( draggable, event );
13377        }
13378
13379        // Run through all droppables and check their positions based on specific tolerance options
13380        $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
13381
13382            if ( this.options.disabled || this.greedyChild || !this.visible ) {
13383                return;
13384            }
13385
13386            var parentInstance, scope, parent,
13387                intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
13388                c = !intersects && this.isover ?
13389                    "isout" :
13390                    ( intersects && !this.isover ? "isover" : null );
13391            if ( !c ) {
13392                return;
13393            }
13394
13395            if ( this.options.greedy ) {
13396
13397                // find droppable parents with same scope
13398                scope = this.options.scope;
13399                parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
13400                    return $( this ).droppable( "instance" ).options.scope === scope;
13401                } );
13402
13403                if ( parent.length ) {
13404                    parentInstance = $( parent[ 0 ] ).droppable( "instance" );
13405                    parentInstance.greedyChild = ( c === "isover" );
13406                }
13407            }
13408
13409            // We just moved into a greedy child
13410            if ( parentInstance && c === "isover" ) {
13411                parentInstance.isover = false;
13412                parentInstance.isout = true;
13413                parentInstance._out.call( parentInstance, event );
13414            }
13415
13416            this[ c ] = true;
13417            this[ c === "isout" ? "isover" : "isout" ] = false;
13418            this[ c === "isover" ? "_over" : "_out" ].call( this, event );
13419
13420            // We just moved out of a greedy child
13421            if ( parentInstance && c === "isout" ) {
13422                parentInstance.isout = false;
13423                parentInstance.isover = true;
13424                parentInstance._over.call( parentInstance, event );
13425            }
13426        } );
13427
13428    },
13429    dragStop: function( draggable, event ) {
13430        draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
13431
13432        // Call prepareOffsets one final time since IE does not fire return scroll events when
13433        // overflow was caused by drag (see #5003)
13434        if ( !draggable.options.refreshPositions ) {
13435            $.ui.ddmanager.prepareOffsets( draggable, event );
13436        }
13437    }
13438};
13439
13440// DEPRECATED
13441// TODO: switch return back to widget declaration at top of file when this is removed
13442if ( $.uiBackCompat === true ) {
13443
13444    // Backcompat for activeClass and hoverClass options
13445    $.widget( "ui.droppable", $.ui.droppable, {
13446        options: {
13447            hoverClass: false,
13448            activeClass: false
13449        },
13450        _addActiveClass: function() {
13451            this._super();
13452            if ( this.options.activeClass ) {
13453                this.element.addClass( this.options.activeClass );
13454            }
13455        },
13456        _removeActiveClass: function() {
13457            this._super();
13458            if ( this.options.activeClass ) {
13459                this.element.removeClass( this.options.activeClass );
13460            }
13461        },
13462        _addHoverClass: function() {
13463            this._super();
13464            if ( this.options.hoverClass ) {
13465                this.element.addClass( this.options.hoverClass );
13466            }
13467        },
13468        _removeHoverClass: function() {
13469            this._super();
13470            if ( this.options.hoverClass ) {
13471                this.element.removeClass( this.options.hoverClass );
13472            }
13473        }
13474    } );
13475}
13476
13477var widgetsDroppable = $.ui.droppable;
13478
13479
13480/*!
13481 * jQuery UI Progressbar 1.14.1
13482 * https://jqueryui.com
13483 *
13484 * Copyright OpenJS Foundation and other contributors
13485 * Released under the MIT license.
13486 * https://jquery.org/license
13487 */
13488
13489//>>label: Progressbar
13490//>>group: Widgets
13491/* eslint-disable max-len */
13492//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
13493/* eslint-enable max-len */
13494//>>docs: https://api.jqueryui.com/progressbar/
13495//>>demos: https://jqueryui.com/progressbar/
13496//>>css.structure: ../../themes/base/core.css
13497//>>css.structure: ../../themes/base/progressbar.css
13498//>>css.theme: ../../themes/base/theme.css
13499
13500
13501var widgetsProgressbar = $.widget( "ui.progressbar", {
13502    version: "1.14.1",
13503    options: {
13504        classes: {
13505            "ui-progressbar": "ui-corner-all",
13506            "ui-progressbar-value": "ui-corner-left",
13507            "ui-progressbar-complete": "ui-corner-right"
13508        },
13509        max: 100,
13510        value: 0,
13511
13512        change: null,
13513        complete: null
13514    },
13515
13516    min: 0,
13517
13518    _create: function() {
13519
13520        // Constrain initial value
13521        this.oldValue = this.options.value = this._constrainedValue();
13522
13523        this.element.attr( {
13524
13525            // Only set static values; aria-valuenow and aria-valuemax are
13526            // set inside _refreshValue()
13527            role: "progressbar",
13528            "aria-valuemin": this.min
13529        } );
13530        this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
13531
13532        this.valueDiv = $( "<div>" ).appendTo( this.element );
13533        this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
13534        this._refreshValue();
13535    },
13536
13537    _destroy: function() {
13538        this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
13539
13540        this.valueDiv.remove();
13541    },
13542
13543    value: function( newValue ) {
13544        if ( newValue === undefined ) {
13545            return this.options.value;
13546        }
13547
13548        this.options.value = this._constrainedValue( newValue );
13549        this._refreshValue();
13550    },
13551
13552    _constrainedValue: function( newValue ) {
13553        if ( newValue === undefined ) {
13554            newValue = this.options.value;
13555        }
13556
13557        this.indeterminate = newValue === false;
13558
13559        // Sanitize value
13560        if ( typeof newValue !== "number" ) {
13561            newValue = 0;
13562        }
13563
13564        return this.indeterminate ? false :
13565            Math.min( this.options.max, Math.max( this.min, newValue ) );
13566    },
13567
13568    _setOptions: function( options ) {
13569
13570        // Ensure "value" option is set after other values (like max)
13571        var value = options.value;
13572        delete options.value;
13573
13574        this._super( options );
13575
13576        this.options.value = this._constrainedValue( value );
13577        this._refreshValue();
13578    },
13579
13580    _setOption: function( key, value ) {
13581        if ( key === "max" ) {
13582
13583            // Don't allow a max less than min
13584            value = Math.max( this.min, value );
13585        }
13586        this._super( key, value );
13587    },
13588
13589    _setOptionDisabled: function( value ) {
13590        this._super( value );
13591
13592        this.element.attr( "aria-disabled", value );
13593        this._toggleClass( null, "ui-state-disabled", !!value );
13594    },
13595
13596    _percentage: function() {
13597        return this.indeterminate ?
13598            100 :
13599            100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
13600    },
13601
13602    _refreshValue: function() {
13603        var value = this.options.value,
13604            percentage = this._percentage();
13605
13606        this.valueDiv
13607            .toggle( this.indeterminate || value > this.min )
13608            .width( percentage.toFixed( 0 ) + "%" );
13609
13610        this
13611            ._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
13612                value === this.options.max )
13613            ._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
13614
13615        if ( this.indeterminate ) {
13616            this.element.removeAttr( "aria-valuenow" );
13617            if ( !this.overlayDiv ) {
13618                this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
13619                this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
13620            }
13621        } else {
13622            this.element.attr( {
13623                "aria-valuemax": this.options.max,
13624                "aria-valuenow": value
13625            } );
13626            if ( this.overlayDiv ) {
13627                this.overlayDiv.remove();
13628                this.overlayDiv = null;
13629            }
13630        }
13631
13632        if ( this.oldValue !== value ) {
13633            this.oldValue = value;
13634            this._trigger( "change" );
13635        }
13636        if ( value === this.options.max ) {
13637            this._trigger( "complete" );
13638        }
13639    }
13640} );
13641
13642
13643/*!
13644 * jQuery UI Selectable 1.14.1
13645 * https://jqueryui.com
13646 *
13647 * Copyright OpenJS Foundation and other contributors
13648 * Released under the MIT license.
13649 * https://jquery.org/license
13650 */
13651
13652//>>label: Selectable
13653//>>group: Interactions
13654//>>description: Allows groups of elements to be selected with the mouse.
13655//>>docs: https://api.jqueryui.com/selectable/
13656//>>demos: https://jqueryui.com/selectable/
13657//>>css.structure: ../../themes/base/selectable.css
13658
13659
13660var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, {
13661    version: "1.14.1",
13662    options: {
13663        appendTo: "body",
13664        autoRefresh: true,
13665        distance: 0,
13666        filter: "*",
13667        tolerance: "touch",
13668
13669        // Callbacks
13670        selected: null,
13671        selecting: null,
13672        start: null,
13673        stop: null,
13674        unselected: null,
13675        unselecting: null
13676    },
13677    _create: function() {
13678        var that = this;
13679
13680        this._addClass( "ui-selectable" );
13681
13682        this.dragged = false;
13683
13684        // Cache selectee children based on filter
13685        this.refresh = function() {
13686            that.elementPos = $( that.element[ 0 ] ).offset();
13687            that.selectees = $( that.options.filter, that.element[ 0 ] );
13688            that._addClass( that.selectees, "ui-selectee" );
13689            that.selectees.each( function() {
13690                var $this = $( this ),
13691                    selecteeOffset = $this.offset(),
13692                    pos = {
13693                        left: selecteeOffset.left - that.elementPos.left,
13694                        top: selecteeOffset.top - that.elementPos.top
13695                    };
13696                $.data( this, "selectable-item", {
13697                    element: this,
13698                    $element: $this,
13699                    left: pos.left,
13700                    top: pos.top,
13701                    right: pos.left + $this.outerWidth(),
13702                    bottom: pos.top + $this.outerHeight(),
13703                    startselected: false,
13704                    selected: $this.hasClass( "ui-selected" ),
13705                    selecting: $this.hasClass( "ui-selecting" ),
13706                    unselecting: $this.hasClass( "ui-unselecting" )
13707                } );
13708            } );
13709        };
13710        this.refresh();
13711
13712        this._mouseInit();
13713
13714        this.helper = $( "<div>" );
13715        this._addClass( this.helper, "ui-selectable-helper" );
13716    },
13717
13718    _destroy: function() {
13719        this.selectees.removeData( "selectable-item" );
13720        this._mouseDestroy();
13721    },
13722
13723    _mouseStart: function( event ) {
13724        var that = this,
13725            options = this.options;
13726
13727        this.opos = [ event.pageX, event.pageY ];
13728        this.elementPos = $( this.element[ 0 ] ).offset();
13729
13730        if ( this.options.disabled ) {
13731            return;
13732        }
13733
13734        this.selectees = $( options.filter, this.element[ 0 ] );
13735
13736        this._trigger( "start", event );
13737
13738        $( options.appendTo ).append( this.helper );
13739
13740        // position helper (lasso)
13741        this.helper.css( {
13742            "left": event.pageX,
13743            "top": event.pageY,
13744            "width": 0,
13745            "height": 0
13746        } );
13747
13748        if ( options.autoRefresh ) {
13749            this.refresh();
13750        }
13751
13752        this.selectees.filter( ".ui-selected" ).each( function() {
13753            var selectee = $.data( this, "selectable-item" );
13754            selectee.startselected = true;
13755            if ( !event.metaKey && !event.ctrlKey ) {
13756                that._removeClass( selectee.$element, "ui-selected" );
13757                selectee.selected = false;
13758                that._addClass( selectee.$element, "ui-unselecting" );
13759                selectee.unselecting = true;
13760
13761                // selectable UNSELECTING callback
13762                that._trigger( "unselecting", event, {
13763                    unselecting: selectee.element
13764                } );
13765            }
13766        } );
13767
13768        $( event.target ).parents().addBack().each( function() {
13769            var doSelect,
13770                selectee = $.data( this, "selectable-item" );
13771            if ( selectee ) {
13772                doSelect = ( !event.metaKey && !event.ctrlKey ) ||
13773                    !selectee.$element.hasClass( "ui-selected" );
13774                that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
13775                    ._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
13776                selectee.unselecting = !doSelect;
13777                selectee.selecting = doSelect;
13778                selectee.selected = doSelect;
13779
13780                // selectable (UN)SELECTING callback
13781                if ( doSelect ) {
13782                    that._trigger( "selecting", event, {
13783                        selecting: selectee.element
13784                    } );
13785                } else {
13786                    that._trigger( "unselecting", event, {
13787                        unselecting: selectee.element
13788                    } );
13789                }
13790                return false;
13791            }
13792        } );
13793
13794    },
13795
13796    _mouseDrag: function( event ) {
13797
13798        this.dragged = true;
13799
13800        if ( this.options.disabled ) {
13801            return;
13802        }
13803
13804        var tmp,
13805            that = this,
13806            options = this.options,
13807            x1 = this.opos[ 0 ],
13808            y1 = this.opos[ 1 ],
13809            x2 = event.pageX,
13810            y2 = event.pageY;
13811
13812        if ( x1 > x2 ) {
13813            tmp = x2; x2 = x1; x1 = tmp;
13814        }
13815        if ( y1 > y2 ) {
13816            tmp = y2; y2 = y1; y1 = tmp;
13817        }
13818        this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
13819
13820        this.selectees.each( function() {
13821            var selectee = $.data( this, "selectable-item" ),
13822                hit = false,
13823                offset = {};
13824
13825            //prevent helper from being selected if appendTo: selectable
13826            if ( !selectee || selectee.element === that.element[ 0 ] ) {
13827                return;
13828            }
13829
13830            offset.left   = selectee.left   + that.elementPos.left;
13831            offset.right  = selectee.right  + that.elementPos.left;
13832            offset.top    = selectee.top    + that.elementPos.top;
13833            offset.bottom = selectee.bottom + that.elementPos.top;
13834
13835            if ( options.tolerance === "touch" ) {
13836                hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
13837                    offset.bottom < y1 ) );
13838            } else if ( options.tolerance === "fit" ) {
13839                hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
13840                    offset.bottom < y2 );
13841            }
13842
13843            if ( hit ) {
13844
13845                // SELECT
13846                if ( selectee.selected ) {
13847                    that._removeClass( selectee.$element, "ui-selected" );
13848                    selectee.selected = false;
13849                }
13850                if ( selectee.unselecting ) {
13851                    that._removeClass( selectee.$element, "ui-unselecting" );
13852                    selectee.unselecting = false;
13853                }
13854                if ( !selectee.selecting ) {
13855                    that._addClass( selectee.$element, "ui-selecting" );
13856                    selectee.selecting = true;
13857
13858                    // selectable SELECTING callback
13859                    that._trigger( "selecting", event, {
13860                        selecting: selectee.element
13861                    } );
13862                }
13863            } else {
13864
13865                // UNSELECT
13866                if ( selectee.selecting ) {
13867                    if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
13868                        that._removeClass( selectee.$element, "ui-selecting" );
13869                        selectee.selecting = false;
13870                        that._addClass( selectee.$element, "ui-selected" );
13871                        selectee.selected = true;
13872                    } else {
13873                        that._removeClass( selectee.$element, "ui-selecting" );
13874                        selectee.selecting = false;
13875                        if ( selectee.startselected ) {
13876                            that._addClass( selectee.$element, "ui-unselecting" );
13877                            selectee.unselecting = true;
13878                        }
13879
13880                        // selectable UNSELECTING callback
13881                        that._trigger( "unselecting", event, {
13882                            unselecting: selectee.element
13883                        } );
13884                    }
13885                }
13886                if ( selectee.selected ) {
13887                    if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
13888                        that._removeClass( selectee.$element, "ui-selected" );
13889                        selectee.selected = false;
13890
13891                        that._addClass( selectee.$element, "ui-unselecting" );
13892                        selectee.unselecting = true;
13893
13894                        // selectable UNSELECTING callback
13895                        that._trigger( "unselecting", event, {
13896                            unselecting: selectee.element
13897                        } );
13898                    }
13899                }
13900            }
13901        } );
13902
13903        return false;
13904    },
13905
13906    _mouseStop: function( event ) {
13907        var that = this;
13908
13909        this.dragged = false;
13910
13911        $( ".ui-unselecting", this.element[ 0 ] ).each( function() {
13912            var selectee = $.data( this, "selectable-item" );
13913            that._removeClass( selectee.$element, "ui-unselecting" );
13914            selectee.unselecting = false;
13915            selectee.startselected = false;
13916            that._trigger( "unselected", event, {
13917                unselected: selectee.element
13918            } );
13919        } );
13920        $( ".ui-selecting", this.element[ 0 ] ).each( function() {
13921            var selectee = $.data( this, "selectable-item" );
13922            that._removeClass( selectee.$element, "ui-selecting" )
13923                ._addClass( selectee.$element, "ui-selected" );
13924            selectee.selecting = false;
13925            selectee.selected = true;
13926            selectee.startselected = true;
13927            that._trigger( "selected", event, {
13928                selected: selectee.element
13929            } );
13930        } );
13931        this._trigger( "stop", event );
13932
13933        this.helper.remove();
13934
13935        return false;
13936    }
13937
13938} );
13939
13940
13941/*!
13942 * jQuery UI Selectmenu 1.14.1
13943 * https://jqueryui.com
13944 *
13945 * Copyright OpenJS Foundation and other contributors
13946 * Released under the MIT license.
13947 * https://jquery.org/license
13948 */
13949
13950//>>label: Selectmenu
13951//>>group: Widgets
13952/* eslint-disable max-len */
13953//>>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.
13954/* eslint-enable max-len */
13955//>>docs: https://api.jqueryui.com/selectmenu/
13956//>>demos: https://jqueryui.com/selectmenu/
13957//>>css.structure: ../../themes/base/core.css
13958//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
13959//>>css.theme: ../../themes/base/theme.css
13960
13961
13962var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
13963    version: "1.14.1",
13964    defaultElement: "<select>",
13965    options: {
13966        appendTo: null,
13967        classes: {
13968            "ui-selectmenu-button-open": "ui-corner-top",
13969            "ui-selectmenu-button-closed": "ui-corner-all"
13970        },
13971        disabled: null,
13972        icons: {
13973            button: "ui-icon-triangle-1-s"
13974        },
13975        position: {
13976            my: "left top",
13977            at: "left bottom",
13978            collision: "none"
13979        },
13980        width: false,
13981
13982        // Callbacks
13983        change: null,
13984        close: null,
13985        focus: null,
13986        open: null,
13987        select: null
13988    },
13989
13990    _create: function() {
13991        var selectmenuId = this.element.uniqueId().attr( "id" );
13992        this.ids = {
13993            element: selectmenuId,
13994            button: selectmenuId + "-button",
13995            menu: selectmenuId + "-menu"
13996        };
13997
13998        this._drawButton();
13999        this._drawMenu();
14000        this._bindFormResetHandler();
14001
14002        this._rendered = false;
14003        this.menuItems = $();
14004    },
14005
14006    _drawButton: function() {
14007        var icon,
14008            that = this,
14009            item = this._parseOption(
14010                this.element.find( "option:selected" ),
14011                this.element[ 0 ].selectedIndex
14012            );
14013
14014        // Associate existing label with the new button
14015        this.labels = this.element.labels().attr( "for", this.ids.button );
14016        this._on( this.labels, {
14017            click: function( event ) {
14018                this.button.trigger( "focus" );
14019                event.preventDefault();
14020            }
14021        } );
14022
14023        // Hide original select element
14024        this.element.hide();
14025
14026        // Create button
14027        this.button = $( "<span>", {
14028            tabindex: this.options.disabled ? -1 : 0,
14029            id: this.ids.button,
14030            role: "combobox",
14031            "aria-expanded": "false",
14032            "aria-autocomplete": "list",
14033            "aria-owns": this.ids.menu,
14034            "aria-haspopup": "true",
14035            title: this.element.attr( "title" )
14036        } )
14037            .insertAfter( this.element );
14038
14039        this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
14040            "ui-button ui-widget" );
14041
14042        icon = $( "<span>" ).appendTo( this.button );
14043        this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
14044        this.buttonItem = this._renderButtonItem( item )
14045            .appendTo( this.button );
14046
14047        if ( this.options.width !== false ) {
14048            this._resizeButton();
14049        }
14050
14051        this._on( this.button, this._buttonEvents );
14052        this.button.one( "focusin", function() {
14053
14054            // Delay rendering the menu items until the button receives focus.
14055            // The menu may have already been rendered via a programmatic open.
14056            if ( !that._rendered ) {
14057                that._refreshMenu();
14058            }
14059        } );
14060    },
14061
14062    _drawMenu: function() {
14063        var that = this;
14064
14065        // Create menu
14066        this.menu = $( "<ul>", {
14067            "aria-hidden": "true",
14068            "aria-labelledby": this.ids.button,
14069            id: this.ids.menu
14070        } );
14071
14072        // Wrap menu
14073        this.menuWrap = $( "<div>" ).append( this.menu );
14074        this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
14075        this.menuWrap.appendTo( this._appendTo() );
14076
14077        // Initialize menu widget
14078        this.menuInstance = this.menu
14079            .menu( {
14080                classes: {
14081                    "ui-menu": "ui-corner-bottom"
14082                },
14083                role: "listbox",
14084                select: function( event, ui ) {
14085                    event.preventDefault();
14086                    that._select( ui.item.data( "ui-selectmenu-item" ), event );
14087                },
14088                focus: function( event, ui ) {
14089                    var item = ui.item.data( "ui-selectmenu-item" );
14090
14091                    // Prevent inital focus from firing and check if its a newly focused item
14092                    if ( that.focusIndex != null && item.index !== that.focusIndex ) {
14093                        that._trigger( "focus", event, { item: item } );
14094                        if ( !that.isOpen ) {
14095                            that._select( item, event );
14096                        }
14097                    }
14098                    that.focusIndex = item.index;
14099
14100                    that.button.attr( "aria-activedescendant",
14101                        that.menuItems.eq( item.index ).attr( "id" ) );
14102                }
14103            } )
14104            .menu( "instance" );
14105
14106        // Don't close the menu on mouseleave
14107        this.menuInstance._off( this.menu, "mouseleave" );
14108
14109        // Cancel the menu's collapseAll on document click
14110        this.menuInstance._closeOnDocumentClick = function() {
14111            return false;
14112        };
14113
14114        // Selects often contain empty items, but never contain dividers
14115        this.menuInstance._isDivider = function() {
14116            return false;
14117        };
14118    },
14119
14120    refresh: function() {
14121        this._refreshMenu();
14122        this.buttonItem.replaceWith(
14123            this.buttonItem = this._renderButtonItem(
14124
14125                // Fall back to an empty object in case there are no options
14126                this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
14127            )
14128        );
14129        if ( this.options.width === null ) {
14130            this._resizeButton();
14131        }
14132    },
14133
14134    _refreshMenu: function() {
14135        var item,
14136            options = this.element.find( "option" );
14137
14138        this.menu.empty();
14139
14140        this._parseOptions( options );
14141        this._renderMenu( this.menu, this.items );
14142
14143        this.menuInstance.refresh();
14144        this.menuItems = this.menu.find( "li" )
14145            .not( ".ui-selectmenu-optgroup" )
14146                .find( ".ui-menu-item-wrapper" );
14147
14148        this._rendered = true;
14149
14150        if ( !options.length ) {
14151            return;
14152        }
14153
14154        item = this._getSelectedItem();
14155
14156        // Update the menu to have the correct item focused
14157        this.menuInstance.focus( null, item );
14158        this._setAria( item.data( "ui-selectmenu-item" ) );
14159
14160        // Set disabled state
14161        this._setOption( "disabled", this.element.prop( "disabled" ) );
14162    },
14163
14164    open: function( event ) {
14165        if ( this.options.disabled ) {
14166            return;
14167        }
14168
14169        // If this is the first time the menu is being opened, render the items
14170        if ( !this._rendered ) {
14171            this._refreshMenu();
14172        } else {
14173
14174            // Menu clears focus on close, reset focus to selected item
14175            this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
14176            this.menuInstance.focus( null, this._getSelectedItem() );
14177        }
14178
14179        // If there are no options, don't open the menu
14180        if ( !this.menuItems.length ) {
14181            return;
14182        }
14183
14184        this.isOpen = true;
14185        this._toggleAttr();
14186        this._resizeMenu();
14187        this._position();
14188
14189        this._on( this.document, this._documentClick );
14190
14191        this._trigger( "open", event );
14192    },
14193
14194    _position: function() {
14195        this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
14196    },
14197
14198    close: function( event ) {
14199        if ( !this.isOpen ) {
14200            return;
14201        }
14202
14203        this.isOpen = false;
14204        this._toggleAttr();
14205
14206        this.range = null;
14207        this._off( this.document );
14208
14209        this._trigger( "close", event );
14210    },
14211
14212    widget: function() {
14213        return this.button;
14214    },
14215
14216    menuWidget: function() {
14217        return this.menu;
14218    },
14219
14220    _renderButtonItem: function( item ) {
14221        var buttonItem = $( "<span>" );
14222
14223        this._setText( buttonItem, item.label );
14224        this._addClass( buttonItem, "ui-selectmenu-text" );
14225
14226        return buttonItem;
14227    },
14228
14229    _renderMenu: function( ul, items ) {
14230        var that = this,
14231            currentOptgroup = "";
14232
14233        $.each( items, function( index, item ) {
14234            var li;
14235
14236            if ( item.optgroup !== currentOptgroup ) {
14237                li = $( "<li>", {
14238                    text: item.optgroup
14239                } );
14240                that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
14241                    ( item.element.parent( "optgroup" ).prop( "disabled" ) ?
14242                        " ui-state-disabled" :
14243                        "" ) );
14244
14245                li.appendTo( ul );
14246
14247                currentOptgroup = item.optgroup;
14248            }
14249
14250            that._renderItemData( ul, item );
14251        } );
14252    },
14253
14254    _renderItemData: function( ul, item ) {
14255        return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
14256    },
14257
14258    _renderItem: function( ul, item ) {
14259        var li = $( "<li>" ),
14260            wrapper = $( "<div>", {
14261                title: item.element.attr( "title" )
14262            } );
14263
14264        if ( item.disabled ) {
14265            this._addClass( li, null, "ui-state-disabled" );
14266        }
14267
14268        if ( item.hidden ) {
14269            li.prop( "hidden", true );
14270        } else {
14271            this._setText( wrapper, item.label );
14272        }
14273
14274        return li.append( wrapper ).appendTo( ul );
14275    },
14276
14277    _setText: function( element, value ) {
14278        if ( value ) {
14279            element.text( value );
14280        } else {
14281            element.html( "&#160;" );
14282        }
14283    },
14284
14285    _move: function( direction, event ) {
14286        var item, next,
14287            filter = ".ui-menu-item";
14288
14289        if ( this.isOpen ) {
14290            item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14291        } else {
14292            item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14293            filter += ":not(.ui-state-disabled)";
14294        }
14295
14296        if ( direction === "first" || direction === "last" ) {
14297            next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
14298        } else {
14299            next = item[ direction + "All" ]( filter ).eq( 0 );
14300        }
14301
14302        if ( next.length ) {
14303            this.menuInstance.focus( event, next );
14304        }
14305    },
14306
14307    _getSelectedItem: function() {
14308        return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14309    },
14310
14311    _toggle: function( event ) {
14312        this[ this.isOpen ? "close" : "open" ]( event );
14313    },
14314
14315    _setSelection: function() {
14316        var selection;
14317
14318        if ( !this.range ) {
14319            return;
14320        }
14321
14322        selection = window.getSelection();
14323        selection.removeAllRanges();
14324        selection.addRange( this.range );
14325    },
14326
14327    _documentClick: {
14328        mousedown: function( event ) {
14329            if ( !this.isOpen ) {
14330                return;
14331            }
14332
14333            if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
14334                CSS.escape( this.ids.button ) ).length ) {
14335                this.close( event );
14336            }
14337        }
14338    },
14339
14340    _buttonEvents: {
14341
14342        // Prevent text selection from being reset when interacting with the selectmenu (#10144)
14343        mousedown: function() {
14344            var selection = window.getSelection();
14345            if ( selection.rangeCount ) {
14346                this.range = selection.getRangeAt( 0 );
14347            }
14348        },
14349
14350        click: function( event ) {
14351            this._setSelection();
14352            this._toggle( event );
14353        },
14354
14355        keydown: function( event ) {
14356            var preventDefault = true;
14357            switch ( event.keyCode ) {
14358            case $.ui.keyCode.TAB:
14359            case $.ui.keyCode.ESCAPE:
14360                this.close( event );
14361                preventDefault = false;
14362                break;
14363            case $.ui.keyCode.ENTER:
14364                if ( this.isOpen ) {
14365                    this._selectFocusedItem( event );
14366                }
14367                break;
14368            case $.ui.keyCode.UP:
14369                if ( event.altKey ) {
14370                    this._toggle( event );
14371                } else {
14372                    this._move( "prev", event );
14373                }
14374                break;
14375            case $.ui.keyCode.DOWN:
14376                if ( event.altKey ) {
14377                    this._toggle( event );
14378                } else {
14379                    this._move( "next", event );
14380                }
14381                break;
14382            case $.ui.keyCode.SPACE:
14383                if ( this.isOpen ) {
14384                    this._selectFocusedItem( event );
14385                } else {
14386                    this._toggle( event );
14387                }
14388                break;
14389            case $.ui.keyCode.LEFT:
14390                this._move( "prev", event );
14391                break;
14392            case $.ui.keyCode.RIGHT:
14393                this._move( "next", event );
14394                break;
14395            case $.ui.keyCode.HOME:
14396            case $.ui.keyCode.PAGE_UP:
14397                this._move( "first", event );
14398                break;
14399            case $.ui.keyCode.END:
14400            case $.ui.keyCode.PAGE_DOWN:
14401                this._move( "last", event );
14402                break;
14403            default:
14404                this.menu.trigger( event );
14405                preventDefault = false;
14406            }
14407
14408            if ( preventDefault ) {
14409                event.preventDefault();
14410            }
14411        }
14412    },
14413
14414    _selectFocusedItem: function( event ) {
14415        var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14416        if ( !item.hasClass( "ui-state-disabled" ) ) {
14417            this._select( item.data( "ui-selectmenu-item" ), event );
14418        }
14419    },
14420
14421    _select: function( item, event ) {
14422        var oldIndex = this.element[ 0 ].selectedIndex;
14423
14424        // Change native select element
14425        this.element[ 0 ].selectedIndex = item.index;
14426        this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
14427        this._setAria( item );
14428        this._trigger( "select", event, { item: item } );
14429
14430        if ( item.index !== oldIndex ) {
14431            this._trigger( "change", event, { item: item } );
14432        }
14433
14434        this.close( event );
14435    },
14436
14437    _setAria: function( item ) {
14438        var id = this.menuItems.eq( item.index ).attr( "id" );
14439
14440        this.button.attr( {
14441            "aria-labelledby": id,
14442            "aria-activedescendant": id
14443        } );
14444        this.menu.attr( "aria-activedescendant", id );
14445    },
14446
14447    _setOption: function( key, value ) {
14448        if ( key === "icons" ) {
14449            var icon = this.button.find( "span.ui-icon" );
14450            this._removeClass( icon, null, this.options.icons.button )
14451                ._addClass( icon, null, value.button );
14452        }
14453
14454        this._super( key, value );
14455
14456        if ( key === "appendTo" ) {
14457            this.menuWrap.appendTo( this._appendTo() );
14458        }
14459
14460        if ( key === "width" ) {
14461            this._resizeButton();
14462        }
14463    },
14464
14465    _setOptionDisabled: function( value ) {
14466        this._super( value );
14467
14468        this.menuInstance.option( "disabled", value );
14469        this.button.attr( "aria-disabled", value );
14470        this._toggleClass( this.button, null, "ui-state-disabled", value );
14471
14472        this.element.prop( "disabled", value );
14473        if ( value ) {
14474            this.button.attr( "tabindex", -1 );
14475            this.close();
14476        } else {
14477            this.button.attr( "tabindex", 0 );
14478        }
14479    },
14480
14481    _appendTo: function() {
14482        var element = this.options.appendTo;
14483
14484        if ( element ) {
14485            element = element.jquery || element.nodeType ?
14486                $( element ) :
14487                this.document.find( element ).eq( 0 );
14488        }
14489
14490        if ( !element || !element[ 0 ] ) {
14491            element = this.element.closest( ".ui-front, dialog" );
14492        }
14493
14494        if ( !element.length ) {
14495            element = this.document[ 0 ].body;
14496        }
14497
14498        return element;
14499    },
14500
14501    _toggleAttr: function() {
14502        this.button.attr( "aria-expanded", this.isOpen );
14503
14504        // We can't use two _toggleClass() calls here, because we need to make sure
14505        // we always remove classes first and add them second, otherwise if both classes have the
14506        // same theme class, it will be removed after we add it.
14507        this._removeClass( this.button, "ui-selectmenu-button-" +
14508            ( this.isOpen ? "closed" : "open" ) )
14509            ._addClass( this.button, "ui-selectmenu-button-" +
14510                ( this.isOpen ? "open" : "closed" ) )
14511            ._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
14512
14513        this.menu.attr( "aria-hidden", !this.isOpen );
14514    },
14515
14516    _resizeButton: function() {
14517        var width = this.options.width;
14518
14519        // For `width: false`, just remove inline style and stop
14520        if ( width === false ) {
14521            this.button.css( "width", "" );
14522            return;
14523        }
14524
14525        // For `width: null`, match the width of the original element
14526        if ( width === null ) {
14527            width = this.element.show().outerWidth();
14528            this.element.hide();
14529        }
14530
14531        this.button.outerWidth( width );
14532    },
14533
14534    _resizeMenu: function() {
14535        this.menu.outerWidth( Math.max(
14536            this.button.outerWidth(),
14537            this.menu.width( "" ).outerWidth()
14538        ) );
14539    },
14540
14541    _getCreateOptions: function() {
14542        var options = this._super();
14543
14544        options.disabled = this.element.prop( "disabled" );
14545
14546        return options;
14547    },
14548
14549    _parseOptions: function( options ) {
14550        var that = this,
14551            data = [];
14552        options.each( function( index, item ) {
14553            data.push( that._parseOption( $( item ), index ) );
14554        } );
14555        this.items = data;
14556    },
14557
14558    _parseOption: function( option, index ) {
14559        var optgroup = option.parent( "optgroup" );
14560
14561        return {
14562            element: option,
14563            index: index,
14564            value: option.val(),
14565            label: option.text(),
14566            hidden: optgroup.prop( "hidden" ) || option.prop( "hidden" ),
14567            optgroup: optgroup.attr( "label" ) || "",
14568            disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
14569        };
14570    },
14571
14572    _destroy: function() {
14573        this._unbindFormResetHandler();
14574        this.menuWrap.remove();
14575        this.button.remove();
14576        this.element.show();
14577        this.element.removeUniqueId();
14578        this.labels.attr( "for", this.ids.element );
14579    }
14580} ] );
14581
14582
14583/*!
14584 * jQuery UI Slider 1.14.1
14585 * https://jqueryui.com
14586 *
14587 * Copyright OpenJS Foundation and other contributors
14588 * Released under the MIT license.
14589 * https://jquery.org/license
14590 */
14591
14592//>>label: Slider
14593//>>group: Widgets
14594//>>description: Displays a flexible slider with ranges and accessibility via keyboard.
14595//>>docs: https://api.jqueryui.com/slider/
14596//>>demos: https://jqueryui.com/slider/
14597//>>css.structure: ../../themes/base/core.css
14598//>>css.structure: ../../themes/base/slider.css
14599//>>css.theme: ../../themes/base/theme.css
14600
14601
14602var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
14603    version: "1.14.1",
14604    widgetEventPrefix: "slide",
14605
14606    options: {
14607        animate: false,
14608        classes: {
14609            "ui-slider": "ui-corner-all",
14610            "ui-slider-handle": "ui-corner-all",
14611
14612            // Note: ui-widget-header isn't the most fittingly semantic framework class for this
14613            // element, but worked best visually with a variety of themes
14614            "ui-slider-range": "ui-corner-all ui-widget-header"
14615        },
14616        distance: 0,
14617        max: 100,
14618        min: 0,
14619        orientation: "horizontal",
14620        range: false,
14621        step: 1,
14622        value: 0,
14623        values: null,
14624
14625        // Callbacks
14626        change: null,
14627        slide: null,
14628        start: null,
14629        stop: null
14630    },
14631
14632    // Number of pages in a slider
14633    // (how many times can you page up/down to go through the whole range)
14634    numPages: 5,
14635
14636    _create: function() {
14637        this._keySliding = false;
14638        this._mouseSliding = false;
14639        this._animateOff = true;
14640        this._handleIndex = null;
14641        this._detectOrientation();
14642        this._mouseInit();
14643        this._calculateNewMax();
14644
14645        this._addClass( "ui-slider ui-slider-" + this.orientation,
14646            "ui-widget ui-widget-content" );
14647
14648        this._refresh();
14649
14650        this._animateOff = false;
14651    },
14652
14653    _refresh: function() {
14654        this._createRange();
14655        this._createHandles();
14656        this._setupEvents();
14657        this._refreshValue();
14658    },
14659
14660    _createHandles: function() {
14661        var i, handleCount,
14662            options = this.options,
14663            existingHandles = this.element.find( ".ui-slider-handle" ),
14664            handle = "<span tabindex='0'></span>",
14665            handles = [];
14666
14667        handleCount = ( options.values && options.values.length ) || 1;
14668
14669        if ( existingHandles.length > handleCount ) {
14670            existingHandles.slice( handleCount ).remove();
14671            existingHandles = existingHandles.slice( 0, handleCount );
14672        }
14673
14674        for ( i = existingHandles.length; i < handleCount; i++ ) {
14675            handles.push( handle );
14676        }
14677
14678        this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
14679
14680        this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
14681
14682        this.handle = this.handles.eq( 0 );
14683
14684        this.handles.each( function( i ) {
14685            $( this )
14686                .data( "ui-slider-handle-index", i )
14687                .attr( "tabIndex", 0 );
14688        } );
14689    },
14690
14691    _createRange: function() {
14692        var options = this.options;
14693
14694        if ( options.range ) {
14695            if ( options.range === true ) {
14696                if ( !options.values ) {
14697                    options.values = [ this._valueMin(), this._valueMin() ];
14698                } else if ( options.values.length && options.values.length !== 2 ) {
14699                    options.values = [ options.values[ 0 ], options.values[ 0 ] ];
14700                } else if ( Array.isArray( options.values ) ) {
14701                    options.values = options.values.slice( 0 );
14702                }
14703            }
14704
14705            if ( !this.range || !this.range.length ) {
14706                this.range = $( "<div>" )
14707                    .appendTo( this.element );
14708
14709                this._addClass( this.range, "ui-slider-range" );
14710            } else {
14711                this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
14712
14713                // Handle range switching from true to min/max
14714                this.range.css( {
14715                    "left": "",
14716                    "bottom": ""
14717                } );
14718            }
14719            if ( options.range === "min" || options.range === "max" ) {
14720                this._addClass( this.range, "ui-slider-range-" + options.range );
14721            }
14722        } else {
14723            if ( this.range ) {
14724                this.range.remove();
14725            }
14726            this.range = null;
14727        }
14728    },
14729
14730    _setupEvents: function() {
14731        this._off( this.handles );
14732        this._on( this.handles, this._handleEvents );
14733        this._hoverable( this.handles );
14734        this._focusable( this.handles );
14735    },
14736
14737    _destroy: function() {
14738        this.handles.remove();
14739        if ( this.range ) {
14740            this.range.remove();
14741        }
14742
14743        this._mouseDestroy();
14744    },
14745
14746    _mouseCapture: function( event ) {
14747        var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
14748            that = this,
14749            o = this.options;
14750
14751        if ( o.disabled ) {
14752            return false;
14753        }
14754
14755        this.elementSize = {
14756            width: this.element.outerWidth(),
14757            height: this.element.outerHeight()
14758        };
14759        this.elementOffset = this.element.offset();
14760
14761        position = { x: event.pageX, y: event.pageY };
14762        normValue = this._normValueFromMouse( position );
14763        distance = this._valueMax() - this._valueMin() + 1;
14764        this.handles.each( function( i ) {
14765            var thisDistance = Math.abs( normValue - that.values( i ) );
14766            if ( ( distance > thisDistance ) ||
14767                ( distance === thisDistance &&
14768                    ( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
14769                distance = thisDistance;
14770                closestHandle = $( this );
14771                index = i;
14772            }
14773        } );
14774
14775        allowed = this._start( event, index );
14776        if ( allowed === false ) {
14777            return false;
14778        }
14779        this._mouseSliding = true;
14780
14781        this._handleIndex = index;
14782
14783        this._addClass( closestHandle, null, "ui-state-active" );
14784        closestHandle.trigger( "focus" );
14785
14786        offset = closestHandle.offset();
14787        mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
14788        this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
14789            left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
14790            top: event.pageY - offset.top -
14791                ( closestHandle.height() / 2 ) -
14792                ( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
14793                ( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
14794                ( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
14795        };
14796
14797        if ( !this.handles.hasClass( "ui-state-hover" ) ) {
14798            this._slide( event, index, normValue );
14799        }
14800        this._animateOff = true;
14801        return true;
14802    },
14803
14804    _mouseStart: function() {
14805        return true;
14806    },
14807
14808    _mouseDrag: function( event ) {
14809        var position = { x: event.pageX, y: event.pageY },
14810            normValue = this._normValueFromMouse( position );
14811
14812        this._slide( event, this._handleIndex, normValue );
14813
14814        return false;
14815    },
14816
14817    _mouseStop: function( event ) {
14818        this._removeClass( this.handles, null, "ui-state-active" );
14819        this._mouseSliding = false;
14820
14821        this._stop( event, this._handleIndex );
14822        this._change( event, this._handleIndex );
14823
14824        this._handleIndex = null;
14825        this._clickOffset = null;
14826        this._animateOff = false;
14827
14828        return false;
14829    },
14830
14831    _detectOrientation: function() {
14832        this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
14833    },
14834
14835    _normValueFromMouse: function( position ) {
14836        var pixelTotal,
14837            pixelMouse,
14838            percentMouse,
14839            valueTotal,
14840            valueMouse;
14841
14842        if ( this.orientation === "horizontal" ) {
14843            pixelTotal = this.elementSize.width;
14844            pixelMouse = position.x - this.elementOffset.left -
14845                ( this._clickOffset ? this._clickOffset.left : 0 );
14846        } else {
14847            pixelTotal = this.elementSize.height;
14848            pixelMouse = position.y - this.elementOffset.top -
14849                ( this._clickOffset ? this._clickOffset.top : 0 );
14850        }
14851
14852        percentMouse = ( pixelMouse / pixelTotal );
14853        if ( percentMouse > 1 ) {
14854            percentMouse = 1;
14855        }
14856        if ( percentMouse < 0 ) {
14857            percentMouse = 0;
14858        }
14859        if ( this.orientation === "vertical" ) {
14860            percentMouse = 1 - percentMouse;
14861        }
14862
14863        valueTotal = this._valueMax() - this._valueMin();
14864        valueMouse = this._valueMin() + percentMouse * valueTotal;
14865
14866        return this._trimAlignValue( valueMouse );
14867    },
14868
14869    _uiHash: function( index, value, values ) {
14870        var uiHash = {
14871            handle: this.handles[ index ],
14872            handleIndex: index,
14873            value: value !== undefined ? value : this.value()
14874        };
14875
14876        if ( this._hasMultipleValues() ) {
14877            uiHash.value = value !== undefined ? value : this.values( index );
14878            uiHash.values = values || this.values();
14879        }
14880
14881        return uiHash;
14882    },
14883
14884    _hasMultipleValues: function() {
14885        return this.options.values && this.options.values.length;
14886    },
14887
14888    _start: function( event, index ) {
14889        return this._trigger( "start", event, this._uiHash( index ) );
14890    },
14891
14892    _slide: function( event, index, newVal ) {
14893        var allowed, otherVal,
14894            currentValue = this.value(),
14895            newValues = this.values();
14896
14897        if ( this._hasMultipleValues() ) {
14898            otherVal = this.values( index ? 0 : 1 );
14899            currentValue = this.values( index );
14900
14901            if ( this.options.values.length === 2 && this.options.range === true ) {
14902                newVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
14903            }
14904
14905            newValues[ index ] = newVal;
14906        }
14907
14908        if ( newVal === currentValue ) {
14909            return;
14910        }
14911
14912        allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
14913
14914        // A slide can be canceled by returning false from the slide callback
14915        if ( allowed === false ) {
14916            return;
14917        }
14918
14919        if ( this._hasMultipleValues() ) {
14920            this.values( index, newVal );
14921        } else {
14922            this.value( newVal );
14923        }
14924    },
14925
14926    _stop: function( event, index ) {
14927        this._trigger( "stop", event, this._uiHash( index ) );
14928    },
14929
14930    _change: function( event, index ) {
14931        if ( !this._keySliding && !this._mouseSliding ) {
14932
14933            //store the last changed value index for reference when handles overlap
14934            this._lastChangedValue = index;
14935            this._trigger( "change", event, this._uiHash( index ) );
14936        }
14937    },
14938
14939    value: function( newValue ) {
14940        if ( arguments.length ) {
14941            this.options.value = this._trimAlignValue( newValue );
14942            this._refreshValue();
14943            this._change( null, 0 );
14944            return;
14945        }
14946
14947        return this._value();
14948    },
14949
14950    values: function( index, newValue ) {
14951        var vals,
14952            newValues,
14953            i;
14954
14955        if ( arguments.length > 1 ) {
14956            this.options.values[ index ] = this._trimAlignValue( newValue );
14957            this._refreshValue();
14958            this._change( null, index );
14959            return;
14960        }
14961
14962        if ( arguments.length ) {
14963            if ( Array.isArray( arguments[ 0 ] ) ) {
14964                vals = this.options.values;
14965                newValues = arguments[ 0 ];
14966                for ( i = 0; i < vals.length; i += 1 ) {
14967                    vals[ i ] = this._trimAlignValue( newValues[ i ] );
14968                    this._change( null, i );
14969                }
14970                this._refreshValue();
14971            } else {
14972                if ( this._hasMultipleValues() ) {
14973                    return this._values( index );
14974                } else {
14975                    return this.value();
14976                }
14977            }
14978        } else {
14979            return this._values();
14980        }
14981    },
14982
14983    _setOption: function( key, value ) {
14984        var i,
14985            valsLength = 0;
14986
14987        if ( key === "range" && this.options.range === true ) {
14988            if ( value === "min" ) {
14989                this.options.value = this._values( 0 );
14990                this.options.values = null;
14991            } else if ( value === "max" ) {
14992                this.options.value = this._values( this.options.values.length - 1 );
14993                this.options.values = null;
14994            }
14995        }
14996
14997        if ( Array.isArray( this.options.values ) ) {
14998            valsLength = this.options.values.length;
14999        }
15000
15001        this._super( key, value );
15002
15003        switch ( key ) {
15004            case "orientation":
15005                this._detectOrientation();
15006                this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
15007                    ._addClass( "ui-slider-" + this.orientation );
15008                this._refreshValue();
15009                if ( this.options.range ) {
15010                    this._refreshRange( value );
15011                }
15012
15013                // Reset positioning from previous orientation
15014                this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
15015                break;
15016            case "value":
15017                this._animateOff = true;
15018                this._refreshValue();
15019                this._change( null, 0 );
15020                this._animateOff = false;
15021                break;
15022            case "values":
15023                this._animateOff = true;
15024                this._refreshValue();
15025
15026                // Start from the last handle to prevent unreachable handles (#9046)
15027                for ( i = valsLength - 1; i >= 0; i-- ) {
15028                    this._change( null, i );
15029                }
15030                this._animateOff = false;
15031                break;
15032            case "step":
15033            case "min":
15034            case "max":
15035                this._animateOff = true;
15036                this._calculateNewMax();
15037                this._refreshValue();
15038                this._animateOff = false;
15039                break;
15040            case "range":
15041                this._animateOff = true;
15042                this._refresh();
15043                this._animateOff = false;
15044                break;
15045        }
15046    },
15047
15048    _setOptionDisabled: function( value ) {
15049        this._super( value );
15050
15051        this._toggleClass( null, "ui-state-disabled", !!value );
15052    },
15053
15054    //internal value getter
15055    // _value() returns value trimmed by min and max, aligned by step
15056    _value: function() {
15057        var val = this.options.value;
15058        val = this._trimAlignValue( val );
15059
15060        return val;
15061    },
15062
15063    //internal values getter
15064    // _values() returns array of values trimmed by min and max, aligned by step
15065    // _values( index ) returns single value trimmed by min and max, aligned by step
15066    _values: function( index ) {
15067        var val,
15068            vals,
15069            i;
15070
15071        if ( arguments.length ) {
15072            val = this.options.values[ index ];
15073            val = this._trimAlignValue( val );
15074
15075            return val;
15076        } else if ( this._hasMultipleValues() ) {
15077
15078            // .slice() creates a copy of the array
15079            // this copy gets trimmed by min and max and then returned
15080            vals = this.options.values.slice();
15081            for ( i = 0; i < vals.length; i += 1 ) {
15082                vals[ i ] = this._trimAlignValue( vals[ i ] );
15083            }
15084
15085            return vals;
15086        } else {
15087            return [];
15088        }
15089    },
15090
15091    // Returns the step-aligned value that val is closest to, between (inclusive) min and max
15092    _trimAlignValue: function( val ) {
15093        if ( val <= this._valueMin() ) {
15094            return this._valueMin();
15095        }
15096        if ( val >= this._valueMax() ) {
15097            return this._valueMax();
15098        }
15099        var step = ( this.options.step > 0 ) ? this.options.step : 1,
15100            valModStep = ( val - this._valueMin() ) % step,
15101            alignValue = val - valModStep;
15102
15103        if ( Math.abs( valModStep ) * 2 >= step ) {
15104            alignValue += ( valModStep > 0 ) ? step : ( -step );
15105        }
15106
15107        // Since JavaScript has problems with large floats, round
15108        // the final value to 5 digits after the decimal point (see #4124)
15109        return parseFloat( alignValue.toFixed( 5 ) );
15110    },
15111
15112    _calculateNewMax: function() {
15113        var max = this.options.max,
15114            min = this._valueMin(),
15115            step = this.options.step,
15116            aboveMin = Math.round( ( max - min ) / step ) * step;
15117        max = aboveMin + min;
15118        if ( max > this.options.max ) {
15119
15120            //If max is not divisible by step, rounding off may increase its value
15121            max -= step;
15122        }
15123        this.max = parseFloat( max.toFixed( this._precision() ) );
15124    },
15125
15126    _precision: function() {
15127        var precision = this._precisionOf( this.options.step );
15128        if ( this.options.min !== null ) {
15129            precision = Math.max( precision, this._precisionOf( this.options.min ) );
15130        }
15131        return precision;
15132    },
15133
15134    _precisionOf: function( num ) {
15135        var str = num.toString(),
15136            decimal = str.indexOf( "." );
15137        return decimal === -1 ? 0 : str.length - decimal - 1;
15138    },
15139
15140    _valueMin: function() {
15141        return this.options.min;
15142    },
15143
15144    _valueMax: function() {
15145        return this.max;
15146    },
15147
15148    _refreshRange: function( orientation ) {
15149        if ( orientation === "vertical" ) {
15150            this.range.css( { "width": "", "left": "" } );
15151        }
15152        if ( orientation === "horizontal" ) {
15153            this.range.css( { "height": "", "bottom": "" } );
15154        }
15155    },
15156
15157    _refreshValue: function() {
15158        var lastValPercent, valPercent, value, valueMin, valueMax,
15159            oRange = this.options.range,
15160            o = this.options,
15161            that = this,
15162            animate = ( !this._animateOff ) ? o.animate : false,
15163            _set = {};
15164
15165        if ( this._hasMultipleValues() ) {
15166            this.handles.each( function( i ) {
15167                valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
15168                    that._valueMin() ) * 100;
15169                _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15170                $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15171                if ( that.options.range === true ) {
15172                    if ( that.orientation === "horizontal" ) {
15173                        if ( i === 0 ) {
15174                            that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15175                                left: valPercent + "%"
15176                            }, o.animate );
15177                        }
15178                        if ( i === 1 ) {
15179                            that.range[ animate ? "animate" : "css" ]( {
15180                                width: ( valPercent - lastValPercent ) + "%"
15181                            }, {
15182                                queue: false,
15183                                duration: o.animate
15184                            } );
15185                        }
15186                    } else {
15187                        if ( i === 0 ) {
15188                            that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15189                                bottom: ( valPercent ) + "%"
15190                            }, o.animate );
15191                        }
15192                        if ( i === 1 ) {
15193                            that.range[ animate ? "animate" : "css" ]( {
15194                                height: ( valPercent - lastValPercent ) + "%"
15195                            }, {
15196                                queue: false,
15197                                duration: o.animate
15198                            } );
15199                        }
15200                    }
15201                }
15202                lastValPercent = valPercent;
15203            } );
15204        } else {
15205            value = this.value();
15206            valueMin = this._valueMin();
15207            valueMax = this._valueMax();
15208            valPercent = ( valueMax !== valueMin ) ?
15209                    ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
15210                    0;
15211            _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15212            this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15213
15214            if ( oRange === "min" && this.orientation === "horizontal" ) {
15215                this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15216                    width: valPercent + "%"
15217                }, o.animate );
15218            }
15219            if ( oRange === "max" && this.orientation === "horizontal" ) {
15220                this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15221                    width: ( 100 - valPercent ) + "%"
15222                }, o.animate );
15223            }
15224            if ( oRange === "min" && this.orientation === "vertical" ) {
15225                this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15226                    height: valPercent + "%"
15227                }, o.animate );
15228            }
15229            if ( oRange === "max" && this.orientation === "vertical" ) {
15230                this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15231                    height: ( 100 - valPercent ) + "%"
15232                }, o.animate );
15233            }
15234        }
15235    },
15236
15237    _handleEvents: {
15238        keydown: function( event ) {
15239            var allowed, curVal, newVal, step,
15240                index = $( event.target ).data( "ui-slider-handle-index" );
15241
15242            switch ( event.keyCode ) {
15243                case $.ui.keyCode.HOME:
15244                case $.ui.keyCode.END:
15245                case $.ui.keyCode.PAGE_UP:
15246                case $.ui.keyCode.PAGE_DOWN:
15247                case $.ui.keyCode.UP:
15248                case $.ui.keyCode.RIGHT:
15249                case $.ui.keyCode.DOWN:
15250                case $.ui.keyCode.LEFT:
15251                    event.preventDefault();
15252                    if ( !this._keySliding ) {
15253                        this._keySliding = true;
15254                        this._addClass( $( event.target ), null, "ui-state-active" );
15255                        allowed = this._start( event, index );
15256                        if ( allowed === false ) {
15257                            return;
15258                        }
15259                    }
15260                    break;
15261            }
15262
15263            step = this.options.step;
15264            if ( this._hasMultipleValues() ) {
15265                curVal = newVal = this.values( index );
15266            } else {
15267                curVal = newVal = this.value();
15268            }
15269
15270            switch ( event.keyCode ) {
15271                case $.ui.keyCode.HOME:
15272                    newVal = this._valueMin();
15273                    break;
15274                case $.ui.keyCode.END:
15275                    newVal = this._valueMax();
15276                    break;
15277                case $.ui.keyCode.PAGE_UP:
15278                    newVal = this._trimAlignValue(
15279                        curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
15280                    );
15281                    break;
15282                case $.ui.keyCode.PAGE_DOWN:
15283                    newVal = this._trimAlignValue(
15284                        curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
15285                    break;
15286                case $.ui.keyCode.UP:
15287                case $.ui.keyCode.RIGHT:
15288                    if ( curVal === this._valueMax() ) {
15289                        return;
15290                    }
15291                    newVal = this._trimAlignValue( curVal + step );
15292                    break;
15293                case $.ui.keyCode.DOWN:
15294                case $.ui.keyCode.LEFT:
15295                    if ( curVal === this._valueMin() ) {
15296                        return;
15297                    }
15298                    newVal = this._trimAlignValue( curVal - step );
15299                    break;
15300            }
15301
15302            this._slide( event, index, newVal );
15303        },
15304        keyup: function( event ) {
15305            var index = $( event.target ).data( "ui-slider-handle-index" );
15306
15307            if ( this._keySliding ) {
15308                this._keySliding = false;
15309                this._stop( event, index );
15310                this._change( event, index );
15311                this._removeClass( $( event.target ), null, "ui-state-active" );
15312            }
15313        }
15314    }
15315} );
15316
15317
15318/*!
15319 * jQuery UI Sortable 1.14.1
15320 * https://jqueryui.com
15321 *
15322 * Copyright OpenJS Foundation and other contributors
15323 * Released under the MIT license.
15324 * https://jquery.org/license
15325 */
15326
15327//>>label: Sortable
15328//>>group: Interactions
15329//>>description: Enables items in a list to be sorted using the mouse.
15330//>>docs: https://api.jqueryui.com/sortable/
15331//>>demos: https://jqueryui.com/sortable/
15332//>>css.structure: ../../themes/base/sortable.css
15333
15334
15335var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
15336    version: "1.14.1",
15337    widgetEventPrefix: "sort",
15338    ready: false,
15339    options: {
15340        appendTo: "parent",
15341        axis: false,
15342        connectWith: false,
15343        containment: false,
15344        cursor: "auto",
15345        cursorAt: false,
15346        dropOnEmpty: true,
15347        forcePlaceholderSize: false,
15348        forceHelperSize: false,
15349        grid: false,
15350        handle: false,
15351        helper: "original",
15352        items: "> *",
15353        opacity: false,
15354        placeholder: false,
15355        revert: false,
15356        scroll: true,
15357        scrollSensitivity: 20,
15358        scrollSpeed: 20,
15359        scope: "default",
15360        tolerance: "intersect",
15361        zIndex: 1000,
15362
15363        // Callbacks
15364        activate: null,
15365        beforeStop: null,
15366        change: null,
15367        deactivate: null,
15368        out: null,
15369        over: null,
15370        receive: null,
15371        remove: null,
15372        sort: null,
15373        start: null,
15374        stop: null,
15375        update: null
15376    },
15377
15378    _isOverAxis: function( x, reference, size ) {
15379        return ( x >= reference ) && ( x < ( reference + size ) );
15380    },
15381
15382    _isFloating: function( item ) {
15383        return ( /left|right/ ).test( item.css( "float" ) ) ||
15384            ( /inline|table-cell/ ).test( item.css( "display" ) );
15385    },
15386
15387    _create: function() {
15388        this.containerCache = {};
15389        this._addClass( "ui-sortable" );
15390
15391        //Get the items
15392        this.refresh();
15393
15394        //Let's determine the parent's offset
15395        this.offset = this.element.offset();
15396
15397        //Initialize mouse events for interaction
15398        this._mouseInit();
15399
15400        this._setHandleClassName();
15401
15402        //We're ready to go
15403        this.ready = true;
15404
15405    },
15406
15407    _setOption: function( key, value ) {
15408        this._super( key, value );
15409
15410        if ( key === "handle" ) {
15411            this._setHandleClassName();
15412        }
15413    },
15414
15415    _setHandleClassName: function() {
15416        var that = this;
15417        this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
15418        $.each( this.items, function() {
15419            that._addClass(
15420                this.instance.options.handle ?
15421                    this.item.find( this.instance.options.handle ) :
15422                    this.item,
15423                "ui-sortable-handle"
15424            );
15425        } );
15426    },
15427
15428    _destroy: function() {
15429        this._mouseDestroy();
15430
15431        for ( var i = this.items.length - 1; i >= 0; i-- ) {
15432            this.items[ i ].item.removeData( this.widgetName + "-item" );
15433        }
15434
15435        return this;
15436    },
15437
15438    _mouseCapture: function( event, overrideHandle ) {
15439        var currentItem = null,
15440            validHandle = false,
15441            that = this;
15442
15443        if ( this.reverting ) {
15444            return false;
15445        }
15446
15447        if ( this.options.disabled || this.options.type === "static" ) {
15448            return false;
15449        }
15450
15451        //We have to refresh the items data once first
15452        this._refreshItems( event );
15453
15454        //Find out if the clicked node (or one of its parents) is a actual item in this.items
15455        $( event.target ).parents().each( function() {
15456            if ( $.data( this, that.widgetName + "-item" ) === that ) {
15457                currentItem = $( this );
15458                return false;
15459            }
15460        } );
15461        if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
15462            currentItem = $( event.target );
15463        }
15464
15465        if ( !currentItem ) {
15466            return false;
15467        }
15468        if ( this.options.handle && !overrideHandle ) {
15469            $( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
15470                if ( this === event.target ) {
15471                    validHandle = true;
15472                }
15473            } );
15474            if ( !validHandle ) {
15475                return false;
15476            }
15477        }
15478
15479        this.currentItem = currentItem;
15480        this._removeCurrentsFromItems();
15481        return true;
15482
15483    },
15484
15485    _mouseStart: function( event, overrideHandle, noActivation ) {
15486
15487        var i, body,
15488            o = this.options;
15489
15490        this.currentContainer = this;
15491
15492        //We only need to call refreshPositions, because the refreshItems call has been moved to
15493        // mouseCapture
15494        this.refreshPositions();
15495
15496        //Prepare the dragged items parent
15497        this.appendTo = $( o.appendTo !== "parent" ?
15498                o.appendTo :
15499                this.currentItem.parent() );
15500
15501        //Create and append the visible helper
15502        this.helper = this._createHelper( event );
15503
15504        //Cache the helper size
15505        this._cacheHelperProportions();
15506
15507        /*
15508         * - Position generation -
15509         * This block generates everything position related - it's the core of draggables.
15510         */
15511
15512        //Cache the margins of the original element
15513        this._cacheMargins();
15514
15515        //The element's absolute position on the page minus margins
15516        this.offset = this.currentItem.offset();
15517        this.offset = {
15518            top: this.offset.top - this.margins.top,
15519            left: this.offset.left - this.margins.left
15520        };
15521
15522        $.extend( this.offset, {
15523            click: { //Where the click happened, relative to the element
15524                left: event.pageX - this.offset.left,
15525                top: event.pageY - this.offset.top
15526            },
15527
15528            // This is a relative to absolute position minus the actual position calculation -
15529            // only used for relative positioned helper
15530            relative: this._getRelativeOffset()
15531        } );
15532
15533        // After we get the helper offset, but before we get the parent offset we can
15534        // change the helper's position to absolute
15535        // TODO: Still need to figure out a way to make relative sorting possible
15536        this.helper.css( "position", "absolute" );
15537        this.cssPosition = this.helper.css( "position" );
15538
15539        //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
15540        if ( o.cursorAt ) {
15541            this._adjustOffsetFromHelper( o.cursorAt );
15542        }
15543
15544        //Cache the former DOM position
15545        this.domPosition = {
15546            prev: this.currentItem.prev()[ 0 ],
15547            parent: this.currentItem.parent()[ 0 ]
15548        };
15549
15550        // If the helper is not the original, hide the original so it's not playing any role during
15551        // the drag, won't cause anything bad this way
15552        if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
15553            this.currentItem.hide();
15554        }
15555
15556        //Create the placeholder
15557        this._createPlaceholder();
15558
15559        //Get the next scrolling parent
15560        this.scrollParent = this.placeholder.scrollParent();
15561
15562        $.extend( this.offset, {
15563            parent: this._getParentOffset()
15564        } );
15565
15566        //Set a containment if given in the options
15567        if ( o.containment ) {
15568            this._setContainment();
15569        }
15570
15571        if ( o.cursor && o.cursor !== "auto" ) { // cursor option
15572            body = this.document.find( "body" );
15573
15574            this._storedStylesheet =
15575                $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
15576        }
15577
15578        // We need to make sure to grab the zIndex before setting the
15579        // opacity, because setting the opacity to anything lower than 1
15580        // causes the zIndex to change from "auto" to 0.
15581        if ( o.zIndex ) { // zIndex option
15582            if ( this.helper.css( "zIndex" ) ) {
15583                this._storedZIndex = this.helper.css( "zIndex" );
15584            }
15585            this.helper.css( "zIndex", o.zIndex );
15586        }
15587
15588        if ( o.opacity ) { // opacity option
15589            if ( this.helper.css( "opacity" ) ) {
15590                this._storedOpacity = this.helper.css( "opacity" );
15591            }
15592            this.helper.css( "opacity", o.opacity );
15593        }
15594
15595        //Prepare scrolling
15596        if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15597                this.scrollParent[ 0 ].tagName !== "HTML" ) {
15598            this.overflowOffset = this.scrollParent.offset();
15599        }
15600
15601        //Call callbacks
15602        this._trigger( "start", event, this._uiHash() );
15603
15604        //Recache the helper size
15605        if ( !this._preserveHelperProportions ) {
15606            this._cacheHelperProportions();
15607        }
15608
15609        //Post "activate" events to possible containers
15610        if ( !noActivation ) {
15611            for ( i = this.containers.length - 1; i >= 0; i-- ) {
15612                this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
15613            }
15614        }
15615
15616        //Prepare possible droppables
15617        if ( $.ui.ddmanager ) {
15618            $.ui.ddmanager.current = this;
15619        }
15620
15621        if ( $.ui.ddmanager && !o.dropBehaviour ) {
15622            $.ui.ddmanager.prepareOffsets( this, event );
15623        }
15624
15625        this.dragging = true;
15626
15627        this._addClass( this.helper, "ui-sortable-helper" );
15628
15629        //Move the helper, if needed
15630        if ( !this.helper.parent().is( this.appendTo ) ) {
15631            this.helper.detach().appendTo( this.appendTo );
15632
15633            //Update position
15634            this.offset.parent = this._getParentOffset();
15635        }
15636
15637        //Generate the original position
15638        this.position = this.originalPosition = this._generatePosition( event );
15639        this.originalPageX = event.pageX;
15640        this.originalPageY = event.pageY;
15641        this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" );
15642
15643        this._mouseDrag( event );
15644
15645        return true;
15646
15647    },
15648
15649    _scroll: function( event ) {
15650        var o = this.options,
15651            scrolled = false;
15652
15653        if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15654                this.scrollParent[ 0 ].tagName !== "HTML" ) {
15655
15656            if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
15657                    event.pageY < o.scrollSensitivity ) {
15658                this.scrollParent[ 0 ].scrollTop =
15659                    scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
15660            } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
15661                this.scrollParent[ 0 ].scrollTop =
15662                    scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
15663            }
15664
15665            if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
15666                    event.pageX < o.scrollSensitivity ) {
15667                this.scrollParent[ 0 ].scrollLeft = scrolled =
15668                    this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
15669            } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
15670                this.scrollParent[ 0 ].scrollLeft = scrolled =
15671                    this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
15672            }
15673
15674        } else {
15675
15676            if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
15677                scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
15678            } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
15679                    o.scrollSensitivity ) {
15680                scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
15681            }
15682
15683            if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
15684                scrolled = this.document.scrollLeft(
15685                    this.document.scrollLeft() - o.scrollSpeed
15686                );
15687            } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
15688                    o.scrollSensitivity ) {
15689                scrolled = this.document.scrollLeft(
15690                    this.document.scrollLeft() + o.scrollSpeed
15691                );
15692            }
15693
15694        }
15695
15696        return scrolled;
15697    },
15698
15699    _mouseDrag: function( event ) {
15700        var i, item, itemElement, intersection,
15701            o = this.options;
15702
15703        //Compute the helpers position
15704        this.position = this._generatePosition( event );
15705        this.positionAbs = this._convertPositionTo( "absolute" );
15706
15707        //Set the helper position
15708        if ( !this.options.axis || this.options.axis !== "y" ) {
15709            this.helper[ 0 ].style.left = this.position.left + "px";
15710        }
15711        if ( !this.options.axis || this.options.axis !== "x" ) {
15712            this.helper[ 0 ].style.top = this.position.top + "px";
15713        }
15714
15715        //Do scrolling
15716        if ( o.scroll ) {
15717            if ( this._scroll( event ) !== false ) {
15718
15719                //Update item positions used in position checks
15720                this._refreshItemPositions( true );
15721
15722                if ( $.ui.ddmanager && !o.dropBehaviour ) {
15723                    $.ui.ddmanager.prepareOffsets( this, event );
15724                }
15725            }
15726        }
15727
15728        this.dragDirection = {
15729            vertical: this._getDragVerticalDirection(),
15730            horizontal: this._getDragHorizontalDirection()
15731        };
15732
15733        //Rearrange
15734        for ( i = this.items.length - 1; i >= 0; i-- ) {
15735
15736            //Cache variables and intersection, continue if no intersection
15737            item = this.items[ i ];
15738            itemElement = item.item[ 0 ];
15739            intersection = this._intersectsWithPointer( item );
15740            if ( !intersection ) {
15741                continue;
15742            }
15743
15744            // Only put the placeholder inside the current Container, skip all
15745            // items from other containers. This works because when moving
15746            // an item from one container to another the
15747            // currentContainer is switched before the placeholder is moved.
15748            //
15749            // Without this, moving items in "sub-sortables" can cause
15750            // the placeholder to jitter between the outer and inner container.
15751            if ( item.instance !== this.currentContainer ) {
15752                continue;
15753            }
15754
15755            // Cannot intersect with itself
15756            // no useless actions that have been done before
15757            // no action if the item moved is the parent of the item checked
15758            if ( itemElement !== this.currentItem[ 0 ] &&
15759                this.placeholder[ intersection === 1 ?
15760                "next" : "prev" ]()[ 0 ] !== itemElement &&
15761                !$.contains( this.placeholder[ 0 ], itemElement ) &&
15762                ( this.options.type === "semi-dynamic" ?
15763                    !$.contains( this.element[ 0 ], itemElement ) :
15764                    true
15765                )
15766            ) {
15767
15768                this.direction = intersection === 1 ? "down" : "up";
15769
15770                if ( this.options.tolerance === "pointer" ||
15771                        this._intersectsWithSides( item ) ) {
15772                    this._rearrange( event, item );
15773                } else {
15774                    break;
15775                }
15776
15777                this._trigger( "change", event, this._uiHash() );
15778                break;
15779            }
15780        }
15781
15782        //Post events to containers
15783        this._contactContainers( event );
15784
15785        //Interconnect with droppables
15786        if ( $.ui.ddmanager ) {
15787            $.ui.ddmanager.drag( this, event );
15788        }
15789
15790        //Call callbacks
15791        this._trigger( "sort", event, this._uiHash() );
15792
15793        this.lastPositionAbs = this.positionAbs;
15794        return false;
15795
15796    },
15797
15798    _mouseStop: function( event, noPropagation ) {
15799
15800        if ( !event ) {
15801            return;
15802        }
15803
15804        //If we are using droppables, inform the manager about the drop
15805        if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
15806            $.ui.ddmanager.drop( this, event );
15807        }
15808
15809        if ( this.options.revert ) {
15810            var that = this,
15811                cur = this.placeholder.offset(),
15812                axis = this.options.axis,
15813                animation = {};
15814
15815            if ( !axis || axis === "x" ) {
15816                animation.left = cur.left - this.offset.parent.left - this.margins.left +
15817                    ( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15818                        0 :
15819                        this.offsetParent[ 0 ].scrollLeft
15820                    );
15821            }
15822            if ( !axis || axis === "y" ) {
15823                animation.top = cur.top - this.offset.parent.top - this.margins.top +
15824                    ( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15825                        0 :
15826                        this.offsetParent[ 0 ].scrollTop
15827                    );
15828            }
15829            this.reverting = true;
15830            $( this.helper ).animate(
15831                animation,
15832                parseInt( this.options.revert, 10 ) || 500,
15833                function() {
15834                    that._clear( event );
15835                }
15836            );
15837        } else {
15838            this._clear( event, noPropagation );
15839        }
15840
15841        return false;
15842
15843    },
15844
15845    cancel: function() {
15846
15847        if ( this.dragging ) {
15848
15849            this._mouseUp( new $.Event( "mouseup", { target: null } ) );
15850
15851            if ( this.options.helper === "original" ) {
15852                this.currentItem.css( this._storedCSS );
15853                this._removeClass( this.currentItem, "ui-sortable-helper" );
15854            } else {
15855                this.currentItem.show();
15856            }
15857
15858            //Post deactivating events to containers
15859            for ( var i = this.containers.length - 1; i >= 0; i-- ) {
15860                this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
15861                if ( this.containers[ i ].containerCache.over ) {
15862                    this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
15863                    this.containers[ i ].containerCache.over = 0;
15864                }
15865            }
15866
15867        }
15868
15869        if ( this.placeholder ) {
15870
15871            //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
15872            // it unbinds ALL events from the original node!
15873            if ( this.placeholder[ 0 ].parentNode ) {
15874                this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
15875            }
15876            if ( this.options.helper !== "original" && this.helper &&
15877                    this.helper[ 0 ].parentNode ) {
15878                this.helper.remove();
15879            }
15880
15881            $.extend( this, {
15882                helper: null,
15883                dragging: false,
15884                reverting: false,
15885                _noFinalSort: null
15886            } );
15887
15888            if ( this.domPosition.prev ) {
15889                $( this.domPosition.prev ).after( this.currentItem );
15890            } else {
15891                $( this.domPosition.parent ).prepend( this.currentItem );
15892            }
15893        }
15894
15895        return this;
15896
15897    },
15898
15899    serialize: function( o ) {
15900
15901        var items = this._getItemsAsjQuery( o && o.connected ),
15902            str = [];
15903        o = o || {};
15904
15905        $( items ).each( function() {
15906            var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
15907                .match( o.expression || ( /(.+)[\-=_](.+)/ ) );
15908            if ( res ) {
15909                str.push(
15910                    ( o.key || res[ 1 ] + "[]" ) +
15911                    "=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
15912            }
15913        } );
15914
15915        if ( !str.length && o.key ) {
15916            str.push( o.key + "=" );
15917        }
15918
15919        return str.join( "&" );
15920
15921    },
15922
15923    toArray: function( o ) {
15924
15925        var items = this._getItemsAsjQuery( o && o.connected ),
15926            ret = [];
15927
15928        o = o || {};
15929
15930        items.each( function() {
15931            ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
15932        } );
15933        return ret;
15934
15935    },
15936
15937    /* Be careful with the following core functions */
15938    _intersectsWith: function( item ) {
15939
15940        var x1 = this.positionAbs.left,
15941            x2 = x1 + this.helperProportions.width,
15942            y1 = this.positionAbs.top,
15943            y2 = y1 + this.helperProportions.height,
15944            l = item.left,
15945            r = l + item.width,
15946            t = item.top,
15947            b = t + item.height,
15948            dyClick = this.offset.click.top,
15949            dxClick = this.offset.click.left,
15950            isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
15951                ( y1 + dyClick ) < b ),
15952            isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
15953                ( x1 + dxClick ) < r ),
15954            isOverElement = isOverElementHeight && isOverElementWidth;
15955
15956        if ( this.options.tolerance === "pointer" ||
15957            this.options.forcePointerForContainers ||
15958            ( this.options.tolerance !== "pointer" &&
15959                this.helperProportions[ this.floating ? "width" : "height" ] >
15960                item[ this.floating ? "width" : "height" ] )
15961        ) {
15962            return isOverElement;
15963        } else {
15964
15965            return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
15966                x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
15967                t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
15968                y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
15969
15970        }
15971    },
15972
15973    _intersectsWithPointer: function( item ) {
15974        var verticalDirection, horizontalDirection,
15975            isOverElementHeight = ( this.options.axis === "x" ) ||
15976                this._isOverAxis(
15977                    this.positionAbs.top + this.offset.click.top, item.top, item.height ),
15978            isOverElementWidth = ( this.options.axis === "y" ) ||
15979                this._isOverAxis(
15980                    this.positionAbs.left + this.offset.click.left, item.left, item.width ),
15981            isOverElement = isOverElementHeight && isOverElementWidth;
15982
15983        if ( !isOverElement ) {
15984            return false;
15985        }
15986
15987        verticalDirection = this.dragDirection.vertical;
15988        horizontalDirection = this.dragDirection.horizontal;
15989
15990        return this.floating ?
15991            ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) :
15992            ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
15993
15994    },
15995
15996    _intersectsWithSides: function( item ) {
15997
15998        var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
15999                this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
16000            isOverRightHalf = this._isOverAxis( this.positionAbs.left +
16001                this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
16002            verticalDirection = this.dragDirection.vertical,
16003            horizontalDirection = this.dragDirection.horizontal;
16004
16005        if ( this.floating && horizontalDirection ) {
16006            return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
16007                ( horizontalDirection === "left" && !isOverRightHalf ) );
16008        } else {
16009            return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
16010                ( verticalDirection === "up" && !isOverBottomHalf ) );
16011        }
16012
16013    },
16014
16015    _getDragVerticalDirection: function() {
16016        var delta = this.positionAbs.top - this.lastPositionAbs.top;
16017        return delta !== 0 && ( delta > 0 ? "down" : "up" );
16018    },
16019
16020    _getDragHorizontalDirection: function() {
16021        var delta = this.positionAbs.left - this.lastPositionAbs.left;
16022        return delta !== 0 && ( delta > 0 ? "right" : "left" );
16023    },
16024
16025    refresh: function( event ) {
16026        this._refreshItems( event );
16027        this._setHandleClassName();
16028        this.refreshPositions();
16029        return this;
16030    },
16031
16032    _connectWith: function() {
16033        var options = this.options;
16034        return options.connectWith.constructor === String ?
16035            [ options.connectWith ] :
16036            options.connectWith;
16037    },
16038
16039    _getItemsAsjQuery: function( connected ) {
16040
16041        var i, j, cur, inst,
16042            items = [],
16043            queries = [],
16044            connectWith = this._connectWith();
16045
16046        if ( connectWith && connected ) {
16047            for ( i = connectWith.length - 1; i >= 0; i-- ) {
16048                cur = $( connectWith[ i ], this.document[ 0 ] );
16049                for ( j = cur.length - 1; j >= 0; j-- ) {
16050                    inst = $.data( cur[ j ], this.widgetFullName );
16051                    if ( inst && inst !== this && !inst.options.disabled ) {
16052                        queries.push( [ typeof inst.options.items === "function" ?
16053                            inst.options.items.call( inst.element ) :
16054                            $( inst.options.items, inst.element )
16055                                .not( ".ui-sortable-helper" )
16056                                .not( ".ui-sortable-placeholder" ), inst ] );
16057                    }
16058                }
16059            }
16060        }
16061
16062        queries.push( [ typeof this.options.items === "function" ?
16063            this.options.items
16064                .call( this.element, null, { options: this.options, item: this.currentItem } ) :
16065            $( this.options.items, this.element )
16066                .not( ".ui-sortable-helper" )
16067                .not( ".ui-sortable-placeholder" ), this ] );
16068
16069        function addItems() {
16070            items.push( this );
16071        }
16072        for ( i = queries.length - 1; i >= 0; i-- ) {
16073            queries[ i ][ 0 ].each( addItems );
16074        }
16075
16076        return $( items );
16077
16078    },
16079
16080    _removeCurrentsFromItems: function() {
16081
16082        var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
16083
16084        this.items = $.grep( this.items, function( item ) {
16085            for ( var j = 0; j < list.length; j++ ) {
16086                if ( list[ j ] === item.item[ 0 ] ) {
16087                    return false;
16088                }
16089            }
16090            return true;
16091        } );
16092
16093    },
16094
16095    _refreshItems: function( event ) {
16096
16097        this.items = [];
16098        this.containers = [ this ];
16099
16100        var i, j, cur, inst, targetData, _queries, item, queriesLength,
16101            items = this.items,
16102            queries = [ [ typeof this.options.items === "function" ?
16103                this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
16104                $( this.options.items, this.element ), this ] ],
16105            connectWith = this._connectWith();
16106
16107        //Shouldn't be run the first time through due to massive slow-down
16108        if ( connectWith && this.ready ) {
16109            for ( i = connectWith.length - 1; i >= 0; i-- ) {
16110                cur = $( connectWith[ i ], this.document[ 0 ] );
16111                for ( j = cur.length - 1; j >= 0; j-- ) {
16112                    inst = $.data( cur[ j ], this.widgetFullName );
16113                    if ( inst && inst !== this && !inst.options.disabled ) {
16114                        queries.push( [ typeof inst.options.items === "function" ?
16115                            inst.options.items
16116                                .call( inst.element[ 0 ], event, { item: this.currentItem } ) :
16117                            $( inst.options.items, inst.element ), inst ] );
16118                        this.containers.push( inst );
16119                    }
16120                }
16121            }
16122        }
16123
16124        for ( i = queries.length - 1; i >= 0; i-- ) {
16125            targetData = queries[ i ][ 1 ];
16126            _queries = queries[ i ][ 0 ];
16127
16128            for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
16129                item = $( _queries[ j ] );
16130
16131                // Data for target checking (mouse manager)
16132                item.data( this.widgetName + "-item", targetData );
16133
16134                items.push( {
16135                    item: item,
16136                    instance: targetData,
16137                    width: 0, height: 0,
16138                    left: 0, top: 0
16139                } );
16140            }
16141        }
16142
16143    },
16144
16145    _refreshItemPositions: function( fast ) {
16146        var i, item, t, p;
16147
16148        for ( i = this.items.length - 1; i >= 0; i-- ) {
16149            item = this.items[ i ];
16150
16151            //We ignore calculating positions of all connected containers when we're not over them
16152            if ( this.currentContainer && item.instance !== this.currentContainer &&
16153                    item.item[ 0 ] !== this.currentItem[ 0 ] ) {
16154                continue;
16155            }
16156
16157            t = this.options.toleranceElement ?
16158                $( this.options.toleranceElement, item.item ) :
16159                item.item;
16160
16161            if ( !fast ) {
16162                item.width = t.outerWidth();
16163                item.height = t.outerHeight();
16164            }
16165
16166            p = t.offset();
16167            item.left = p.left;
16168            item.top = p.top;
16169        }
16170    },
16171
16172    refreshPositions: function( fast ) {
16173
16174        // Determine whether items are being displayed horizontally
16175        this.floating = this.items.length ?
16176            this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
16177            false;
16178
16179        // This has to be redone because due to the item being moved out/into the offsetParent,
16180        // the offsetParent's position will change
16181        if ( this.offsetParent && this.helper ) {
16182            this.offset.parent = this._getParentOffset();
16183        }
16184
16185        this._refreshItemPositions( fast );
16186
16187        var i, p;
16188
16189        if ( this.options.custom && this.options.custom.refreshContainers ) {
16190            this.options.custom.refreshContainers.call( this );
16191        } else {
16192            for ( i = this.containers.length - 1; i >= 0; i-- ) {
16193                p = this.containers[ i ].element.offset();
16194                this.containers[ i ].containerCache.left = p.left;
16195                this.containers[ i ].containerCache.top = p.top;
16196                this.containers[ i ].containerCache.width =
16197                    this.containers[ i ].element.outerWidth();
16198                this.containers[ i ].containerCache.height =
16199                    this.containers[ i ].element.outerHeight();
16200            }
16201        }
16202
16203        return this;
16204    },
16205
16206    _createPlaceholder: function( that ) {
16207        that = that || this;
16208        var className, nodeName,
16209            o = that.options;
16210
16211        if ( !o.placeholder || o.placeholder.constructor === String ) {
16212            className = o.placeholder;
16213            nodeName = that.currentItem[ 0 ].nodeName.toLowerCase();
16214            o.placeholder = {
16215                element: function() {
16216
16217                    var element = $( "<" + nodeName + ">", that.document[ 0 ] );
16218
16219                    that._addClass( element, "ui-sortable-placeholder",
16220                            className || that.currentItem[ 0 ].className )
16221                        ._removeClass( element, "ui-sortable-helper" );
16222
16223                    if ( nodeName === "tbody" ) {
16224                        that._createTrPlaceholder(
16225                            that.currentItem.find( "tr" ).eq( 0 ),
16226                            $( "<tr>", that.document[ 0 ] ).appendTo( element )
16227                        );
16228                    } else if ( nodeName === "tr" ) {
16229                        that._createTrPlaceholder( that.currentItem, element );
16230                    } else if ( nodeName === "img" ) {
16231                        element.attr( "src", that.currentItem.attr( "src" ) );
16232                    }
16233
16234                    if ( !className ) {
16235                        element.css( "visibility", "hidden" );
16236                    }
16237
16238                    return element;
16239                },
16240                update: function( container, p ) {
16241
16242                    // 1. If a className is set as 'placeholder option, we don't force sizes -
16243                    // the class is responsible for that
16244                    // 2. The option 'forcePlaceholderSize can be enabled to force it even if a
16245                    // class name is specified
16246                    if ( className && !o.forcePlaceholderSize ) {
16247                        return;
16248                    }
16249
16250                    // If the element doesn't have a actual height or width by itself (without
16251                    // styles coming from a stylesheet), it receives the inline height and width
16252                    // from the dragged item. Or, if it's a tbody or tr, it's going to have a height
16253                    // anyway since we're populating them with <td>s above, but they're unlikely to
16254                    // be the correct height on their own if the row heights are dynamic, so we'll
16255                    // always assign the height of the dragged item given forcePlaceholderSize
16256                    // is true.
16257                    if ( !p.height() || ( o.forcePlaceholderSize &&
16258                            ( nodeName === "tbody" || nodeName === "tr" ) ) ) {
16259                        p.height(
vendor: 43,314 bytes, lines 16260-17446
16260                            that.currentItem.innerHeight() -
16261                            parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
16262                            parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
16263                    }
16264                    if ( !p.width() ) {
16265                        p.width(
16266                            that.currentItem.innerWidth() -
16267                            parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
16268                            parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
16269                    }
16270                }
16271            };
16272        }
16273
16274        //Create the placeholder
16275        that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
16276
16277        //Append it after the actual current item
16278        that.currentItem.after( that.placeholder );
16279
16280        //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
16281        o.placeholder.update( that, that.placeholder );
16282
16283    },
16284
16285    _createTrPlaceholder: function( sourceTr, targetTr ) {
16286        var that = this;
16287
16288        sourceTr.children().each( function() {
16289            $( "<td>&#160;</td>", that.document[ 0 ] )
16290                .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
16291                .appendTo( targetTr );
16292        } );
16293    },
16294
16295    _contactContainers: function( event ) {
16296        var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
16297            floating, axis,
16298            innermostContainer = null,
16299            innermostIndex = null;
16300
16301        // Get innermost container that intersects with item
16302        for ( i = this.containers.length - 1; i >= 0; i-- ) {
16303
16304            // Never consider a container that's located within the item itself
16305            if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
16306                continue;
16307            }
16308
16309            if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
16310
16311                // If we've already found a container and it's more "inner" than this, then continue
16312                if ( innermostContainer &&
16313                        $.contains(
16314                            this.containers[ i ].element[ 0 ],
16315                            innermostContainer.element[ 0 ] ) ) {
16316                    continue;
16317                }
16318
16319                innermostContainer = this.containers[ i ];
16320                innermostIndex = i;
16321
16322            } else {
16323
16324                // container doesn't intersect. trigger "out" event if necessary
16325                if ( this.containers[ i ].containerCache.over ) {
16326                    this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
16327                    this.containers[ i ].containerCache.over = 0;
16328                }
16329            }
16330
16331        }
16332
16333        // If no intersecting containers found, return
16334        if ( !innermostContainer ) {
16335            return;
16336        }
16337
16338        // Move the item into the container if it's not there already
16339        if ( this.containers.length === 1 ) {
16340            if ( !this.containers[ innermostIndex ].containerCache.over ) {
16341                this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16342                this.containers[ innermostIndex ].containerCache.over = 1;
16343            }
16344        } else {
16345
16346            // When entering a new container, we will find the item with the least distance and
16347            // append our item near it
16348            dist = 10000;
16349            itemWithLeastDistance = null;
16350            floating = innermostContainer.floating || this._isFloating( this.currentItem );
16351            posProperty = floating ? "left" : "top";
16352            sizeProperty = floating ? "width" : "height";
16353            axis = floating ? "pageX" : "pageY";
16354
16355            for ( j = this.items.length - 1; j >= 0; j-- ) {
16356                if ( !$.contains(
16357                        this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
16358                ) {
16359                    continue;
16360                }
16361                if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
16362                    continue;
16363                }
16364
16365                cur = this.items[ j ].item.offset()[ posProperty ];
16366                nearBottom = false;
16367                if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
16368                    nearBottom = true;
16369                }
16370
16371                if ( Math.abs( event[ axis ] - cur ) < dist ) {
16372                    dist = Math.abs( event[ axis ] - cur );
16373                    itemWithLeastDistance = this.items[ j ];
16374                    this.direction = nearBottom ? "up" : "down";
16375                }
16376            }
16377
16378            //Check if dropOnEmpty is enabled
16379            if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
16380                return;
16381            }
16382
16383            if ( this.currentContainer === this.containers[ innermostIndex ] ) {
16384                if ( !this.currentContainer.containerCache.over ) {
16385                    this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
16386                    this.currentContainer.containerCache.over = 1;
16387                }
16388                return;
16389            }
16390
16391            if ( itemWithLeastDistance ) {
16392                this._rearrange( event, itemWithLeastDistance, null, true );
16393            } else {
16394                this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
16395            }
16396            this._trigger( "change", event, this._uiHash() );
16397            this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
16398            this.currentContainer = this.containers[ innermostIndex ];
16399
16400            //Update the placeholder
16401            this.options.placeholder.update( this.currentContainer, this.placeholder );
16402
16403            //Update scrollParent
16404            this.scrollParent = this.placeholder.scrollParent();
16405
16406            //Update overflowOffset
16407            if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16408                    this.scrollParent[ 0 ].tagName !== "HTML" ) {
16409                this.overflowOffset = this.scrollParent.offset();
16410            }
16411
16412            this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16413            this.containers[ innermostIndex ].containerCache.over = 1;
16414        }
16415
16416    },
16417
16418    _createHelper: function( event ) {
16419
16420        var o = this.options,
16421            helper = typeof o.helper === "function" ?
16422                $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
16423                ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
16424
16425        //Add the helper to the DOM if that didn't happen already
16426        if ( !helper.parents( "body" ).length ) {
16427            this.appendTo[ 0 ].appendChild( helper[ 0 ] );
16428        }
16429
16430        if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
16431            this._storedCSS = {
16432                width: this.currentItem[ 0 ].style.width,
16433                height: this.currentItem[ 0 ].style.height,
16434                position: this.currentItem.css( "position" ),
16435                top: this.currentItem.css( "top" ),
16436                left: this.currentItem.css( "left" )
16437            };
16438        }
16439
16440        if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
16441            helper.width( this.currentItem.width() );
16442        }
16443        if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
16444            helper.height( this.currentItem.height() );
16445        }
16446
16447        return helper;
16448
16449    },
16450
16451    _adjustOffsetFromHelper: function( obj ) {
16452        if ( typeof obj === "string" ) {
16453            obj = obj.split( " " );
16454        }
16455        if ( Array.isArray( obj ) ) {
16456            obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
16457        }
16458        if ( "left" in obj ) {
16459            this.offset.click.left = obj.left + this.margins.left;
16460        }
16461        if ( "right" in obj ) {
16462            this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
16463        }
16464        if ( "top" in obj ) {
16465            this.offset.click.top = obj.top + this.margins.top;
16466        }
16467        if ( "bottom" in obj ) {
16468            this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
16469        }
16470    },
16471
16472    _getParentOffset: function() {
16473
16474        //Get the offsetParent and cache its position
16475        this.offsetParent = this.helper.offsetParent();
16476        var po = this.offsetParent.offset();
16477
16478        // This is a special case where we need to modify a offset calculated on start, since the
16479        // following happened:
16480        // 1. The position of the helper is absolute, so it's position is calculated based on the
16481        // next positioned parent
16482        // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
16483        // the document, which means that the scroll is included in the initial calculation of the
16484        // offset of the parent, and never recalculated upon drag
16485        if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16486                $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
16487            po.left += this.scrollParent.scrollLeft();
16488            po.top += this.scrollParent.scrollTop();
16489        }
16490
16491        // This needs to be actually done for all browsers, since pageX/pageY includes
16492        // this information.
16493        if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ) {
16494            po = { top: 0, left: 0 };
16495        }
16496
16497        return {
16498            top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
16499            left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
16500        };
16501
16502    },
16503
16504    _getRelativeOffset: function() {
16505
16506        if ( this.cssPosition === "relative" ) {
16507            var p = this.currentItem.position();
16508            return {
16509                top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
16510                    this.scrollParent.scrollTop(),
16511                left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
16512                    this.scrollParent.scrollLeft()
16513            };
16514        } else {
16515            return { top: 0, left: 0 };
16516        }
16517
16518    },
16519
16520    _cacheMargins: function() {
16521        this.margins = {
16522            left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
16523            top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
16524        };
16525    },
16526
16527    _cacheHelperProportions: function() {
16528        this.helperProportions = {
16529            width: this.helper.outerWidth(),
16530            height: this.helper.outerHeight()
16531        };
16532    },
16533
16534    _setContainment: function() {
16535
16536        var ce, co, over,
16537            o = this.options;
16538        if ( o.containment === "parent" ) {
16539            o.containment = this.helper[ 0 ].parentNode;
16540        }
16541        if ( o.containment === "document" || o.containment === "window" ) {
16542            this.containment = [
16543                0 - this.offset.relative.left - this.offset.parent.left,
16544                0 - this.offset.relative.top - this.offset.parent.top,
16545                o.containment === "document" ?
16546                    this.document.width() :
16547                    this.window.width() - this.helperProportions.width - this.margins.left,
16548                ( o.containment === "document" ?
16549                    ( this.document.height() || document.body.parentNode.scrollHeight ) :
16550                    this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
16551                ) - this.helperProportions.height - this.margins.top
16552            ];
16553        }
16554
16555        if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
16556            ce = $( o.containment )[ 0 ];
16557            co = $( o.containment ).offset();
16558            over = ( $( ce ).css( "overflow" ) !== "hidden" );
16559
16560            this.containment = [
16561                co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
16562                    ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
16563                co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
16564                    ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
16565                co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
16566                    ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
16567                    ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
16568                    this.helperProportions.width - this.margins.left,
16569                co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
16570                    ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
16571                    ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
16572                    this.helperProportions.height - this.margins.top
16573            ];
16574        }
16575
16576    },
16577
16578    _convertPositionTo: function( d, pos ) {
16579
16580        if ( !pos ) {
16581            pos = this.position;
16582        }
16583        var mod = d === "absolute" ? 1 : -1,
16584            scroll = this.cssPosition === "absolute" &&
16585                !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16586                $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16587                    this.offsetParent :
16588                    this.scrollParent,
16589            scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16590
16591        return {
16592            top: (
16593
16594                // The absolute mouse position
16595                pos.top +
16596
16597                // Only for relative positioned nodes: Relative offset from element to offset parent
16598                this.offset.relative.top * mod +
16599
16600                // The offsetParent's offset without borders (offset + border)
16601                this.offset.parent.top * mod -
16602                ( ( this.cssPosition === "fixed" ?
16603                    -this.scrollParent.scrollTop() :
16604                    ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
16605            ),
16606            left: (
16607
16608                // The absolute mouse position
16609                pos.left +
16610
16611                // Only for relative positioned nodes: Relative offset from element to offset parent
16612                this.offset.relative.left * mod +
16613
16614                // The offsetParent's offset without borders (offset + border)
16615                this.offset.parent.left * mod   -
16616                ( ( this.cssPosition === "fixed" ?
16617                    -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
16618                    scroll.scrollLeft() ) * mod )
16619            )
16620        };
16621
16622    },
16623
16624    _generatePosition: function( event ) {
16625
16626        var top, left,
16627            o = this.options,
16628            pageX = event.pageX,
16629            pageY = event.pageY,
16630            scroll = this.cssPosition === "absolute" &&
16631                !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16632                $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16633                    this.offsetParent :
16634                    this.scrollParent,
16635                scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16636
16637        // This is another very weird special case that only happens for relative elements:
16638        // 1. If the css position is relative
16639        // 2. and the scroll parent is the document or similar to the offset parent
16640        // we have to refresh the relative offset during the scroll so there are no jumps
16641        if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16642                this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
16643            this.offset.relative = this._getRelativeOffset();
16644        }
16645
16646        /*
16647         * - Position constraining -
16648         * Constrain the position to a mix of grid, containment.
16649         */
16650
16651        if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
16652
16653            if ( this.containment ) {
16654                if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
16655                    pageX = this.containment[ 0 ] + this.offset.click.left;
16656                }
16657                if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
16658                    pageY = this.containment[ 1 ] + this.offset.click.top;
16659                }
16660                if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
16661                    pageX = this.containment[ 2 ] + this.offset.click.left;
16662                }
16663                if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
16664                    pageY = this.containment[ 3 ] + this.offset.click.top;
16665                }
16666            }
16667
16668            if ( o.grid ) {
16669                top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
16670                    o.grid[ 1 ] ) * o.grid[ 1 ];
16671                pageY = this.containment ?
16672                    ( ( top - this.offset.click.top >= this.containment[ 1 ] &&
16673                        top - this.offset.click.top <= this.containment[ 3 ] ) ?
16674                            top :
16675                            ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
16676                                top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
16677                                top;
16678
16679                left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
16680                    o.grid[ 0 ] ) * o.grid[ 0 ];
16681                pageX = this.containment ?
16682                    ( ( left - this.offset.click.left >= this.containment[ 0 ] &&
16683                        left - this.offset.click.left <= this.containment[ 2 ] ) ?
16684                            left :
16685                            ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
16686                                left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
16687                                left;
16688            }
16689
16690        }
16691
16692        return {
16693            top: (
16694
16695                // The absolute mouse position
16696                pageY -
16697
16698                // Click offset (relative to the element)
16699                this.offset.click.top -
16700
16701                // Only for relative positioned nodes: Relative offset from element to offset parent
16702                this.offset.relative.top -
16703
16704                // The offsetParent's offset without borders (offset + border)
16705                this.offset.parent.top +
16706                ( ( this.cssPosition === "fixed" ?
16707                    -this.scrollParent.scrollTop() :
16708                    ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
16709            ),
16710            left: (
16711
16712                // The absolute mouse position
16713                pageX -
16714
16715                // Click offset (relative to the element)
16716                this.offset.click.left -
16717
16718                // Only for relative positioned nodes: Relative offset from element to offset parent
16719                this.offset.relative.left -
16720
16721                // The offsetParent's offset without borders (offset + border)
16722                this.offset.parent.left +
16723                ( ( this.cssPosition === "fixed" ?
16724                    -this.scrollParent.scrollLeft() :
16725                    scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
16726            )
16727        };
16728
16729    },
16730
16731    _rearrange: function( event, i, a, hardRefresh ) {
16732
16733        if ( a ) {
16734            a[ 0 ].appendChild( this.placeholder[ 0 ] );
16735        } else {
16736            i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
16737                ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
16738        }
16739
16740        //Various things done here to improve the performance:
16741        // 1. we create a setTimeout, that calls refreshPositions
16742        // 2. on the instance, we have a counter variable, that get's higher after every append
16743        // 3. on the local scope, we copy the counter variable, and check in the timeout,
16744        // if it's still the same
16745        // 4. this lets only the last addition to the timeout stack through
16746        this.counter = this.counter ? ++this.counter : 1;
16747        var counter = this.counter;
16748
16749        this._delay( function() {
16750            if ( counter === this.counter ) {
16751
16752                //Precompute after each DOM insertion, NOT on mousemove
16753                this.refreshPositions( !hardRefresh );
16754            }
16755        } );
16756
16757    },
16758
16759    _clear: function( event, noPropagation ) {
16760
16761        this.reverting = false;
16762
16763        // We delay all events that have to be triggered to after the point where the placeholder
16764        // has been removed and everything else normalized again
16765        var i,
16766            delayedTriggers = [];
16767
16768        // We first have to update the dom position of the actual currentItem
16769        // Note: don't do it if the current item is already removed (by a user), or it gets
16770        // reappended (see #4088)
16771        if ( !this._noFinalSort && this.currentItem.parent().length ) {
16772            this.placeholder.before( this.currentItem );
16773        }
16774        this._noFinalSort = null;
16775
16776        if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
16777            for ( i in this._storedCSS ) {
16778                if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
16779                    this._storedCSS[ i ] = "";
16780                }
16781            }
16782            this.currentItem.css( this._storedCSS );
16783            this._removeClass( this.currentItem, "ui-sortable-helper" );
16784        } else {
16785            this.currentItem.show();
16786        }
16787
16788        if ( this.fromOutside && !noPropagation ) {
16789            delayedTriggers.push( function( event ) {
16790                this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
16791            } );
16792        }
16793        if ( ( this.fromOutside ||
16794                this.domPosition.prev !==
16795                this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
16796                this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
16797
16798            // Trigger update callback if the DOM position has changed
16799            delayedTriggers.push( function( event ) {
16800                this._trigger( "update", event, this._uiHash() );
16801            } );
16802        }
16803
16804        // Check if the items Container has Changed and trigger appropriate
16805        // events.
16806        if ( this !== this.currentContainer ) {
16807            if ( !noPropagation ) {
16808                delayedTriggers.push( function( event ) {
16809                    this._trigger( "remove", event, this._uiHash() );
16810                } );
16811                delayedTriggers.push( ( function( c ) {
16812                    return function( event ) {
16813                        c._trigger( "receive", event, this._uiHash( this ) );
16814                    };
16815                } ).call( this, this.currentContainer ) );
16816                delayedTriggers.push( ( function( c ) {
16817                    return function( event ) {
16818                        c._trigger( "update", event, this._uiHash( this ) );
16819                    };
16820                } ).call( this, this.currentContainer ) );
16821            }
16822        }
16823
16824        //Post events to containers
16825        function delayEvent( type, instance, container ) {
16826            return function( event ) {
16827                container._trigger( type, event, instance._uiHash( instance ) );
16828            };
16829        }
16830        for ( i = this.containers.length - 1; i >= 0; i-- ) {
16831            if ( !noPropagation ) {
16832                delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
16833            }
16834            if ( this.containers[ i ].containerCache.over ) {
16835                delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
16836                this.containers[ i ].containerCache.over = 0;
16837            }
16838        }
16839
16840        //Do what was originally in plugins
16841        if ( this._storedStylesheet ) {
16842            this._storedStylesheet.remove();
16843            this._storedStylesheet = null;
16844        }
16845        if ( this._storedOpacity ) {
16846            this.helper.css( "opacity", this._storedOpacity );
16847        }
16848        if ( this._storedZIndex ) {
16849            this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
16850        }
16851
16852        this.dragging = false;
16853
16854        if ( !noPropagation ) {
16855            this._trigger( "beforeStop", event, this._uiHash() );
16856        }
16857
16858        //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
16859        // it unbinds ALL events from the original node!
16860        this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
16861
16862        if ( !this.cancelHelperRemoval ) {
16863            if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
16864                this.helper.remove();
16865            }
16866            this.helper = null;
16867        }
16868
16869        if ( !noPropagation ) {
16870            for ( i = 0; i < delayedTriggers.length; i++ ) {
16871
16872                // Trigger all delayed events
16873                delayedTriggers[ i ].call( this, event );
16874            }
16875            this._trigger( "stop", event, this._uiHash() );
16876        }
16877
16878        this.fromOutside = false;
16879        return !this.cancelHelperRemoval;
16880
16881    },
16882
16883    _trigger: function() {
16884        if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
16885            this.cancel();
16886        }
16887    },
16888
16889    _uiHash: function( _inst ) {
16890        var inst = _inst || this;
16891        return {
16892            helper: inst.helper,
16893            placeholder: inst.placeholder || $( [] ),
16894            position: inst.position,
16895            originalPosition: inst.originalPosition,
16896            offset: inst.positionAbs,
16897            item: inst.currentItem,
16898            sender: _inst ? _inst.element : null
16899        };
16900    }
16901
16902} );
16903
16904
16905/*!
16906 * jQuery UI Spinner 1.14.1
16907 * https://jqueryui.com
16908 *
16909 * Copyright OpenJS Foundation and other contributors
16910 * Released under the MIT license.
16911 * https://jquery.org/license
16912 */
16913
16914//>>label: Spinner
16915//>>group: Widgets
16916//>>description: Displays buttons to easily input numbers via the keyboard or mouse.
16917//>>docs: https://api.jqueryui.com/spinner/
16918//>>demos: https://jqueryui.com/spinner/
16919//>>css.structure: ../../themes/base/core.css
16920//>>css.structure: ../../themes/base/spinner.css
16921//>>css.theme: ../../themes/base/theme.css
16922
16923
16924function spinnerModifier( fn ) {
16925    return function() {
16926        var previous = this.element.val();
16927        fn.apply( this, arguments );
16928        this._refresh();
16929        if ( previous !== this.element.val() ) {
16930            this._trigger( "change" );
16931        }
16932    };
16933}
16934
16935$.widget( "ui.spinner", {
16936    version: "1.14.1",
16937    defaultElement: "<input>",
16938    widgetEventPrefix: "spin",
16939    options: {
16940        classes: {
16941            "ui-spinner": "ui-corner-all",
16942            "ui-spinner-down": "ui-corner-br",
16943            "ui-spinner-up": "ui-corner-tr"
16944        },
16945        culture: null,
16946        icons: {
16947            down: "ui-icon-triangle-1-s",
16948            up: "ui-icon-triangle-1-n"
16949        },
16950        incremental: true,
16951        max: null,
16952        min: null,
16953        numberFormat: null,
16954        page: 10,
16955        step: 1,
16956
16957        change: null,
16958        spin: null,
16959        start: null,
16960        stop: null
16961    },
16962
16963    _create: function() {
16964
16965        // handle string values that need to be parsed
16966        this._setOption( "max", this.options.max );
16967        this._setOption( "min", this.options.min );
16968        this._setOption( "step", this.options.step );
16969
16970        // Only format if there is a value, prevents the field from being marked
16971        // as invalid in Firefox, see #9573.
16972        if ( this.value() !== "" ) {
16973
16974            // Format the value, but don't constrain.
16975            this._value( this.element.val(), true );
16976        }
16977
16978        this._draw();
16979        this._on( this._events );
16980        this._refresh();
16981
16982        // Turning off autocomplete prevents the browser from remembering the
16983        // value when navigating through history, so we re-enable autocomplete
16984        // if the page is unloaded before the widget is destroyed. #7790
16985        this._on( this.window, {
16986            beforeunload: function() {
16987                this.element.removeAttr( "autocomplete" );
16988            }
16989        } );
16990    },
16991
16992    _getCreateOptions: function() {
16993        var options = this._super();
16994        var element = this.element;
16995
16996        $.each( [ "min", "max", "step" ], function( i, option ) {
16997            var value = element.attr( option );
16998            if ( value != null && value.length ) {
16999                options[ option ] = value;
17000            }
17001        } );
17002
17003        return options;
17004    },
17005
17006    _events: {
17007        keydown: function( event ) {
17008            if ( this._start( event ) && this._keydown( event ) ) {
17009                event.preventDefault();
17010            }
17011        },
17012        keyup: "_stop",
17013        focus: function() {
17014            this.previous = this.element.val();
17015        },
17016        blur: function( event ) {
17017            this._stop();
17018            this._refresh();
17019            if ( this.previous !== this.element.val() ) {
17020                this._trigger( "change", event );
17021            }
17022        },
17023        mousewheel: function( event, delta ) {
17024            var activeElement = this.document[ 0 ].activeElement;
17025            var isActive = this.element[ 0 ] === activeElement;
17026
17027            if ( !isActive || !delta ) {
17028                return;
17029            }
17030
17031            if ( !this.spinning && !this._start( event ) ) {
17032                return false;
17033            }
17034
17035            this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
17036            clearTimeout( this.mousewheelTimer );
17037            this.mousewheelTimer = this._delay( function() {
17038                if ( this.spinning ) {
17039                    this._stop( event );
17040                }
17041            }, 100 );
17042            event.preventDefault();
17043        },
17044        "mousedown .ui-spinner-button": function( event ) {
17045            var previous;
17046
17047            // We never want the buttons to have focus; whenever the user is
17048            // interacting with the spinner, the focus should be on the input.
17049            // If the input is focused then this.previous is properly set from
17050            // when the input first received focus. If the input is not focused
17051            // then we need to set this.previous based on the value before spinning.
17052            previous = this.element[ 0 ] === this.document[ 0 ].activeElement ?
17053                this.previous : this.element.val();
17054            function checkFocus() {
17055                var isActive = this.element[ 0 ] === this.document[ 0 ].activeElement;
17056                if ( !isActive ) {
17057                    this.element.trigger( "focus" );
17058                    this.previous = previous;
17059                }
17060            }
17061
17062            // Ensure focus is on (or stays on) the text field
17063            event.preventDefault();
17064            checkFocus.call( this );
17065
17066            if ( this._start( event ) === false ) {
17067                return;
17068            }
17069
17070            this._repeat( null, $( event.currentTarget )
17071                .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17072        },
17073        "mouseup .ui-spinner-button": "_stop",
17074        "mouseenter .ui-spinner-button": function( event ) {
17075
17076            // button will add ui-state-active if mouse was down while mouseleave and kept down
17077            if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
17078                return;
17079            }
17080
17081            if ( this._start( event ) === false ) {
17082                return false;
17083            }
17084            this._repeat( null, $( event.currentTarget )
17085                .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17086        },
17087
17088        // TODO: do we really want to consider this a stop?
17089        // shouldn't we just stop the repeater and wait until mouseup before
17090        // we trigger the stop event?
17091        "mouseleave .ui-spinner-button": "_stop"
17092    },
17093
17094    // Support mobile enhanced option and make backcompat more sane
17095    _enhance: function() {
17096        this.uiSpinner = this.element
17097            .attr( "autocomplete", "off" )
17098            .wrap( "<span>" )
17099            .parent()
17100
17101                // Add buttons
17102                .append(
17103                    "<a></a><a></a>"
17104                );
17105    },
17106
17107    _draw: function() {
17108        this._enhance();
17109
17110        this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
17111        this._addClass( "ui-spinner-input" );
17112
17113        this.element.attr( "role", "spinbutton" );
17114
17115        // Button bindings
17116        this.buttons = this.uiSpinner.children( "a" )
17117            .attr( "tabIndex", -1 )
17118            .attr( "aria-hidden", true )
17119            .button( {
17120                classes: {
17121                    "ui-button": ""
17122                }
17123            } );
17124
17125        // TODO: Right now button does not support classes this is already updated in button PR
17126        this._removeClass( this.buttons, "ui-corner-all" );
17127
17128        this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
17129        this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
17130        this.buttons.first().button( {
17131            "icon": this.options.icons.up,
17132            "showLabel": false
17133        } );
17134        this.buttons.last().button( {
17135            "icon": this.options.icons.down,
17136            "showLabel": false
17137        } );
17138
17139        // IE 6 doesn't understand height: 50% for the buttons
17140        // unless the wrapper has an explicit height
17141        if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
17142                this.uiSpinner.height() > 0 ) {
17143            this.uiSpinner.height( this.uiSpinner.height() );
17144        }
17145    },
17146
17147    _keydown: function( event ) {
17148        var options = this.options,
17149            keyCode = $.ui.keyCode;
17150
17151        switch ( event.keyCode ) {
17152        case keyCode.UP:
17153            this._repeat( null, 1, event );
17154            return true;
17155        case keyCode.DOWN:
17156            this._repeat( null, -1, event );
17157            return true;
17158        case keyCode.PAGE_UP:
17159            this._repeat( null, options.page, event );
17160            return true;
17161        case keyCode.PAGE_DOWN:
17162            this._repeat( null, -options.page, event );
17163            return true;
17164        }
17165
17166        return false;
17167    },
17168
17169    _start: function( event ) {
17170        if ( !this.spinning && this._trigger( "start", event ) === false ) {
17171            return false;
17172        }
17173
17174        if ( !this.counter ) {
17175            this.counter = 1;
17176        }
17177        this.spinning = true;
17178        return true;
17179    },
17180
17181    _repeat: function( i, steps, event ) {
17182        i = i || 500;
17183
17184        clearTimeout( this.timer );
17185        this.timer = this._delay( function() {
17186            this._repeat( 40, steps, event );
17187        }, i );
17188
17189        this._spin( steps * this.options.step, event );
17190    },
17191
17192    _spin: function( step, event ) {
17193        var value = this.value() || 0;
17194
17195        if ( !this.counter ) {
17196            this.counter = 1;
17197        }
17198
17199        value = this._adjustValue( value + step * this._increment( this.counter ) );
17200
17201        if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
17202            this._value( value );
17203            this.counter++;
17204        }
17205    },
17206
17207    _increment: function( i ) {
17208        var incremental = this.options.incremental;
17209
17210        if ( incremental ) {
17211            return typeof incremental === "function" ?
17212                incremental( i ) :
17213                Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
17214        }
17215
17216        return 1;
17217    },
17218
17219    _precision: function() {
17220        var precision = this._precisionOf( this.options.step );
17221        if ( this.options.min !== null ) {
17222            precision = Math.max( precision, this._precisionOf( this.options.min ) );
17223        }
17224        return precision;
17225    },
17226
17227    _precisionOf: function( num ) {
17228        var str = num.toString(),
17229            decimal = str.indexOf( "." );
17230        return decimal === -1 ? 0 : str.length - decimal - 1;
17231    },
17232
17233    _adjustValue: function( value ) {
17234        var base, aboveMin,
17235            options = this.options;
17236
17237        // Make sure we're at a valid step
17238        // - find out where we are relative to the base (min or 0)
17239        base = options.min !== null ? options.min : 0;
17240        aboveMin = value - base;
17241
17242        // - round to the nearest step
17243        aboveMin = Math.round( aboveMin / options.step ) * options.step;
17244
17245        // - rounding is based on 0, so adjust back to our base
17246        value = base + aboveMin;
17247
17248        // Fix precision from bad JS floating point math
17249        value = parseFloat( value.toFixed( this._precision() ) );
17250
17251        // Clamp the value
17252        if ( options.max !== null && value > options.max ) {
17253            return options.max;
17254        }
17255        if ( options.min !== null && value < options.min ) {
17256            return options.min;
17257        }
17258
17259        return value;
17260    },
17261
17262    _stop: function( event ) {
17263        if ( !this.spinning ) {
17264            return;
17265        }
17266
17267        clearTimeout( this.timer );
17268        clearTimeout( this.mousewheelTimer );
17269        this.counter = 0;
17270        this.spinning = false;
17271        this._trigger( "stop", event );
17272    },
17273
17274    _setOption: function( key, value ) {
17275        var prevValue, first, last;
17276
17277        if ( key === "culture" || key === "numberFormat" ) {
17278            prevValue = this._parse( this.element.val() );
17279            this.options[ key ] = value;
17280            this.element.val( this._format( prevValue ) );
17281            return;
17282        }
17283
17284        if ( key === "max" || key === "min" || key === "step" ) {
17285            if ( typeof value === "string" ) {
17286                value = this._parse( value );
17287            }
17288        }
17289        if ( key === "icons" ) {
17290            first = this.buttons.first().find( ".ui-icon" );
17291            this._removeClass( first, null, this.options.icons.up );
17292            this._addClass( first, null, value.up );
17293            last = this.buttons.last().find( ".ui-icon" );
17294            this._removeClass( last, null, this.options.icons.down );
17295            this._addClass( last, null, value.down );
17296        }
17297
17298        this._super( key, value );
17299    },
17300
17301    _setOptionDisabled: function( value ) {
17302        this._super( value );
17303
17304        this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
17305        this.element.prop( "disabled", !!value );
17306        this.buttons.button( value ? "disable" : "enable" );
17307    },
17308
17309    _setOptions: spinnerModifier( function( options ) {
17310        this._super( options );
17311    } ),
17312
17313    _parse: function( val ) {
17314        if ( typeof val === "string" && val !== "" ) {
17315            val = window.Globalize && this.options.numberFormat ?
17316                Globalize.parseFloat( val, 10, this.options.culture ) : +val;
17317        }
17318        return val === "" || isNaN( val ) ? null : val;
17319    },
17320
17321    _format: function( value ) {
17322        if ( value === "" ) {
17323            return "";
17324        }
17325        return window.Globalize && this.options.numberFormat ?
17326            Globalize.format( value, this.options.numberFormat, this.options.culture ) :
17327            value;
17328    },
17329
17330    _refresh: function() {
17331        this.element.attr( {
17332            "aria-valuemin": this.options.min,
17333            "aria-valuemax": this.options.max,
17334
17335            // TODO: what should we do with values that can't be parsed?
17336            "aria-valuenow": this._parse( this.element.val() )
17337        } );
17338    },
17339
17340    isValid: function() {
17341        var value = this.value();
17342
17343        // Null is invalid
17344        if ( value === null ) {
17345            return false;
17346        }
17347
17348        // If value gets adjusted, it's invalid
17349        return value === this._adjustValue( value );
17350    },
17351
17352    // Update the value without triggering change
17353    _value: function( value, allowAny ) {
17354        var parsed;
17355        if ( value !== "" ) {
17356            parsed = this._parse( value );
17357            if ( parsed !== null ) {
17358                if ( !allowAny ) {
17359                    parsed = this._adjustValue( parsed );
17360                }
17361                value = this._format( parsed );
17362            }
17363        }
17364        this.element.val( value );
17365        this._refresh();
17366    },
17367
17368    _destroy: function() {
17369        this.element
17370            .prop( "disabled", false )
17371            .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
17372
17373        this.uiSpinner.replaceWith( this.element );
17374    },
17375
17376    stepUp: spinnerModifier( function( steps ) {
17377        this._stepUp( steps );
17378    } ),
17379    _stepUp: function( steps ) {
17380        if ( this._start() ) {
17381            this._spin( ( steps || 1 ) * this.options.step );
17382            this._stop();
17383        }
17384    },
17385
17386    stepDown: spinnerModifier( function( steps ) {
17387        this._stepDown( steps );
17388    } ),
17389    _stepDown: function( steps ) {
17390        if ( this._start() ) {
17391            this._spin( ( steps || 1 ) * -this.options.step );
17392            this._stop();
17393        }
17394    },
17395
17396    pageUp: spinnerModifier( function( pages ) {
17397        this._stepUp( ( pages || 1 ) * this.options.page );
17398    } ),
17399
17400    pageDown: spinnerModifier( function( pages ) {
17401        this._stepDown( ( pages || 1 ) * this.options.page );
17402    } ),
17403
17404    value: function( newVal ) {
17405        if ( !arguments.length ) {
17406            return this._parse( this.element.val() );
17407        }
17408        spinnerModifier( this._value ).call( this, newVal );
17409    },
17410
17411    widget: function() {
17412        return this.uiSpinner;
17413    }
17414} );
17415
17416// DEPRECATED
17417// TODO: switch return back to widget declaration at top of file when this is removed
17418if ( $.uiBackCompat === true ) {
17419
17420    // Backcompat for spinner html extension points
17421    $.widget( "ui.spinner", $.ui.spinner, {
17422        _enhance: function() {
17423            this.uiSpinner = this.element
17424                .attr( "autocomplete", "off" )
17425                .wrap( this._uiSpinnerHtml() )
17426                .parent()
17427
17428                    // Add buttons
17429                    .append( this._buttonHtml() );
17430        },
17431        _uiSpinnerHtml: function() {
17432            return "<span>";
17433        },
17434
17435        _buttonHtml: function() {
17436            return "<a></a><a></a>";
17437        }
17438    } );
17439}
17440
17441var widgetsSpinner = $.ui.spinner;
17442
17443
17444/*!
17445 * jQuery UI Tabs 1.14.1
17446 * https://jqueryui.com
vendor: 10,691 bytes, lines 17447-17775
17447 *
17448 * Copyright OpenJS Foundation and other contributors
17449 * Released under the MIT license.
17450 * https://jquery.org/license
17451 */
17452
17453//>>label: Tabs
17454//>>group: Widgets
17455//>>description: Transforms a set of container elements into a tab structure.
17456//>>docs: https://api.jqueryui.com/tabs/
17457//>>demos: https://jqueryui.com/tabs/
17458//>>css.structure: ../../themes/base/core.css
17459//>>css.structure: ../../themes/base/tabs.css
17460//>>css.theme: ../../themes/base/theme.css
17461
17462
17463$.widget( "ui.tabs", {
17464    version: "1.14.1",
17465    delay: 300,
17466    options: {
17467        active: null,
17468        classes: {
17469            "ui-tabs": "ui-corner-all",
17470            "ui-tabs-nav": "ui-corner-all",
17471            "ui-tabs-panel": "ui-corner-bottom",
17472            "ui-tabs-tab": "ui-corner-top"
17473        },
17474        collapsible: false,
17475        event: "click",
17476        heightStyle: "content",
17477        hide: null,
17478        show: null,
17479
17480        // Callbacks
17481        activate: null,
17482        beforeActivate: null,
17483        beforeLoad: null,
17484        load: null
17485    },
17486
17487    _isLocal: ( function() {
17488        var rhash = /#.*$/;
17489
17490        return function( anchor ) {
17491            var anchorUrl, locationUrl;
17492
17493            anchorUrl = anchor.href.replace( rhash, "" );
17494            locationUrl = location.href.replace( rhash, "" );
17495
17496            // Decoding may throw an error if the URL isn't UTF-8 (#9518)
17497            try {
17498                anchorUrl = decodeURIComponent( anchorUrl );
17499            } catch ( error ) {}
17500            try {
17501                locationUrl = decodeURIComponent( locationUrl );
17502            } catch ( error ) {}
17503
17504            return anchor.hash.length > 1 && anchorUrl === locationUrl;
17505        };
17506    } )(),
17507
17508    _create: function() {
17509        var that = this,
17510            options = this.options;
17511
17512        this.running = false;
17513
17514        this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
17515        this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
17516
17517        this._processTabs();
17518        options.active = this._initialActive();
17519
17520        // Take disabling tabs via class attribute from HTML
17521        // into account and update option properly.
17522        if ( Array.isArray( options.disabled ) ) {
17523            options.disabled = $.uniqueSort( options.disabled.concat(
17524                $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
17525                    return that.tabs.index( li );
17526                } )
17527            ) ).sort();
17528        }
17529
17530        // Check for length avoids error when initializing empty list
17531        if ( this.options.active !== false && this.anchors.length ) {
17532            this.active = this._findActive( options.active );
17533        } else {
17534            this.active = $();
17535        }
17536
17537        this._refresh();
17538
17539        if ( this.active.length ) {
17540            this.load( options.active );
17541        }
17542    },
17543
17544    _initialActive: function() {
17545        var active = this.options.active,
17546            collapsible = this.options.collapsible,
17547            locationHashDecoded = decodeURIComponent( location.hash.substring( 1 ) );
17548
17549        if ( active === null ) {
17550
17551            // check the fragment identifier in the URL
17552            if ( locationHashDecoded ) {
17553                this.tabs.each( function( i, tab ) {
17554                    if ( $( tab ).attr( "aria-controls" ) === locationHashDecoded ) {
17555                        active = i;
17556                        return false;
17557                    }
17558                } );
17559            }
17560
17561            // Check for a tab marked active via a class
17562            if ( active === null ) {
17563                active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
17564            }
17565
17566            // No active tab, set to false
17567            if ( active === null || active === -1 ) {
17568                active = this.tabs.length ? 0 : false;
17569            }
17570        }
17571
17572        // Handle numbers: negative, out of range
17573        if ( active !== false ) {
17574            active = this.tabs.index( this.tabs.eq( active ) );
17575            if ( active === -1 ) {
17576                active = collapsible ? false : 0;
17577            }
17578        }
17579
17580        // Don't allow collapsible: false and active: false
17581        if ( !collapsible && active === false && this.anchors.length ) {
17582            active = 0;
17583        }
17584
17585        return active;
17586    },
17587
17588    _getCreateEventData: function() {
17589        return {
17590            tab: this.active,
17591            panel: !this.active.length ? $() : this._getPanelForTab( this.active )
17592        };
17593    },
17594
17595    _tabKeydown: function( event ) {
17596        var focusedTab = $( this.document[ 0 ].activeElement ).closest( "li" ),
17597            selectedIndex = this.tabs.index( focusedTab ),
17598            goingForward = true;
17599
17600        if ( this._handlePageNav( event ) ) {
17601            return;
17602        }
17603
17604        switch ( event.keyCode ) {
17605        case $.ui.keyCode.RIGHT:
17606        case $.ui.keyCode.DOWN:
17607            selectedIndex++;
17608            break;
17609        case $.ui.keyCode.UP:
17610        case $.ui.keyCode.LEFT:
17611            goingForward = false;
17612            selectedIndex--;
17613            break;
17614        case $.ui.keyCode.END:
17615            selectedIndex = this.anchors.length - 1;
17616            break;
17617        case $.ui.keyCode.HOME:
17618            selectedIndex = 0;
17619            break;
17620        case $.ui.keyCode.SPACE:
17621
17622            // Activate only, no collapsing
17623            event.preventDefault();
17624            clearTimeout( this.activating );
17625            this._activate( selectedIndex );
17626            return;
17627        case $.ui.keyCode.ENTER:
17628
17629            // Toggle (cancel delayed activation, allow collapsing)
17630            event.preventDefault();
17631            clearTimeout( this.activating );
17632
17633            // Determine if we should collapse or activate
17634            this._activate( selectedIndex === this.options.active ? false : selectedIndex );
17635            return;
17636        default:
17637            return;
17638        }
17639
17640        // Focus the appropriate tab, based on which key was pressed
17641        event.preventDefault();
17642        clearTimeout( this.activating );
17643        selectedIndex = this._focusNextTab( selectedIndex, goingForward );
17644
17645        // Navigating with control/command key will prevent automatic activation
17646        if ( !event.ctrlKey && !event.metaKey ) {
17647
17648            // Update aria-selected immediately so that AT think the tab is already selected.
17649            // Otherwise AT may confuse the user by stating that they need to activate the tab,
17650            // but the tab will already be activated by the time the announcement finishes.
17651            focusedTab.attr( "aria-selected", "false" );
17652            this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
17653
17654            this.activating = this._delay( function() {
17655                this.option( "active", selectedIndex );
17656            }, this.delay );
17657        }
17658    },
17659
17660    _panelKeydown: function( event ) {
17661        if ( this._handlePageNav( event ) ) {
17662            return;
17663        }
17664
17665        // Ctrl+up moves focus to the current tab
17666        if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
17667            event.preventDefault();
17668            this.active.trigger( "focus" );
17669        }
17670    },
17671
17672    // Alt+page up/down moves focus to the previous/next tab (and activates)
17673    _handlePageNav: function( event ) {
17674        if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
17675            this._activate( this._focusNextTab( this.options.active - 1, false ) );
17676            return true;
17677        }
17678        if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
17679            this._activate( this._focusNextTab( this.options.active + 1, true ) );
17680            return true;
17681        }
17682    },
17683
17684    _findNextTab: function( index, goingForward ) {
17685        var lastTabIndex = this.tabs.length - 1;
17686
17687        function constrain() {
17688            if ( index > lastTabIndex ) {
17689                index = 0;
17690            }
17691            if ( index < 0 ) {
17692                index = lastTabIndex;
17693            }
17694            return index;
17695        }
17696
17697        while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
17698            index = goingForward ? index + 1 : index - 1;
17699        }
17700
17701        return index;
17702    },
17703
17704    _focusNextTab: function( index, goingForward ) {
17705        index = this._findNextTab( index, goingForward );
17706        this.tabs.eq( index ).trigger( "focus" );
17707        return index;
17708    },
17709
17710    _setOption: function( key, value ) {
17711        if ( key === "active" ) {
17712
17713            // _activate() will handle invalid values and update this.options
17714            this._activate( value );
17715            return;
17716        }
17717
17718        this._super( key, value );
17719
17720        if ( key === "collapsible" ) {
17721            this._toggleClass( "ui-tabs-collapsible", null, value );
17722
17723            // Setting collapsible: false while collapsed; open first panel
17724            if ( !value && this.options.active === false ) {
17725                this._activate( 0 );
17726            }
17727        }
17728
17729        if ( key === "event" ) {
17730            this._setupEvents( value );
17731        }
17732
17733        if ( key === "heightStyle" ) {
17734            this._setupHeightStyle( value );
17735        }
17736    },
17737
17738    refresh: function() {
17739        var options = this.options,
17740            lis = this.tablist.children( ":has(a[href])" );
17741
17742        // Get disabled tabs from class attribute from HTML
17743        // this will get converted to a boolean if needed in _refresh()
17744        options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
17745            return lis.index( tab );
17746        } );
17747
17748        this._processTabs();
17749
17750        // Was collapsed or no tabs
17751        if ( options.active === false || !this.anchors.length ) {
17752            options.active = false;
17753            this.active = $();
17754
17755        // was active, but active tab is gone
17756        } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
17757
17758            // all remaining tabs are disabled
17759            if ( this.tabs.length === options.disabled.length ) {
17760                options.active = false;
17761                this.active = $();
17762
17763            // activate previous tab
17764            } else {
17765                this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
17766            }
17767
17768        // was active, active tab still exists
17769        } else {
17770
17771            // make sure active index is correct
17772            options.active = this.tabs.index( this.active );
17773        }
17774
17775        this._refresh();
vendor: 35,423 bytes, lines 17776-18819
17776    },
17777
17778    _refresh: function() {
17779        this._setOptionDisabled( this.options.disabled );
17780        this._setupEvents( this.options.event );
17781        this._setupHeightStyle( this.options.heightStyle );
17782
17783        this.tabs.not( this.active ).attr( {
17784            "aria-selected": "false",
17785            "aria-expanded": "false",
17786            tabIndex: -1
17787        } );
17788        this.panels.not( this._getPanelForTab( this.active ) )
17789            .hide()
17790            .attr( {
17791                "aria-hidden": "true"
17792            } );
17793
17794        // Make sure one tab is in the tab order
17795        if ( !this.active.length ) {
17796            this.tabs.eq( 0 ).attr( "tabIndex", 0 );
17797        } else {
17798            this.active
17799                .attr( {
17800                    "aria-selected": "true",
17801                    "aria-expanded": "true",
17802                    tabIndex: 0
17803                } );
17804            this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
17805            this._getPanelForTab( this.active )
17806                .show()
17807                .attr( {
17808                    "aria-hidden": "false"
17809                } );
17810        }
17811    },
17812
17813    _processTabs: function() {
17814        var that = this,
17815            prevTabs = this.tabs,
17816            prevAnchors = this.anchors,
17817            prevPanels = this.panels;
17818
17819        this.tablist = this._getList().attr( "role", "tablist" );
17820        this._addClass( this.tablist, "ui-tabs-nav",
17821            "ui-helper-reset ui-helper-clearfix ui-widget-header" );
17822
17823        // Prevent users from focusing disabled tabs via click
17824        this.tablist
17825            .on( "mousedown" + this.eventNamespace, "> li", function( event ) {
17826                if ( $( this ).is( ".ui-state-disabled" ) ) {
17827                    event.preventDefault();
17828                }
17829            } );
17830
17831        this.tabs = this.tablist.find( "> li:has(a[href])" )
17832            .attr( {
17833                role: "tab",
17834                tabIndex: -1
17835            } );
17836        this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
17837
17838        this.anchors = this.tabs.map( function() {
17839            return $( "a", this )[ 0 ];
17840        } )
17841            .attr( {
17842                tabIndex: -1
17843            } );
17844        this._addClass( this.anchors, "ui-tabs-anchor" );
17845
17846        this.panels = $();
17847
17848        this.anchors.each( function( i, anchor ) {
17849            var selector, panel, panelId,
17850                anchorId = $( anchor ).uniqueId().attr( "id" ),
17851                tab = $( anchor ).closest( "li" ),
17852                originalAriaControls = tab.attr( "aria-controls" );
17853
17854            // Inline tab
17855            if ( that._isLocal( anchor ) ) {
17856                selector = decodeURIComponent( anchor.hash );
17857                panelId = selector.substring( 1 );
17858                panel = that.element.find( "#" + CSS.escape( panelId ) );
17859
17860            // remote tab
17861            } else {
17862
17863                // If the tab doesn't already have aria-controls,
17864                // generate an id by using a throw-away element
17865                panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
17866                selector = "#" + panelId;
17867                panel = that.element.find( selector );
17868                if ( !panel.length ) {
17869                    panel = that._createPanel( panelId );
17870                    panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
17871                }
17872                panel.attr( "aria-live", "polite" );
17873            }
17874
17875            if ( panel.length ) {
17876                that.panels = that.panels.add( panel );
17877            }
17878            if ( originalAriaControls ) {
17879                tab.data( "ui-tabs-aria-controls", originalAriaControls );
17880            }
17881            tab.attr( {
17882                "aria-controls": panelId,
17883                "aria-labelledby": anchorId
17884            } );
17885            panel.attr( "aria-labelledby", anchorId );
17886        } );
17887
17888        this.panels.attr( "role", "tabpanel" );
17889        this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
17890
17891        // Avoid memory leaks (#10056)
17892        if ( prevTabs ) {
17893            this._off( prevTabs.not( this.tabs ) );
17894            this._off( prevAnchors.not( this.anchors ) );
17895            this._off( prevPanels.not( this.panels ) );
17896        }
17897    },
17898
17899    // Allow overriding how to find the list for rare usage scenarios (#7715)
17900    _getList: function() {
17901        return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
17902    },
17903
17904    _createPanel: function( id ) {
17905        return $( "<div>" )
17906            .attr( "id", id )
17907            .data( "ui-tabs-destroy", true );
17908    },
17909
17910    _setOptionDisabled: function( disabled ) {
17911        var currentItem, li, i;
17912
17913        if ( Array.isArray( disabled ) ) {
17914            if ( !disabled.length ) {
17915                disabled = false;
17916            } else if ( disabled.length === this.anchors.length ) {
17917                disabled = true;
17918            }
17919        }
17920
17921        // Disable tabs
17922        for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
17923            currentItem = $( li );
17924            if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
17925                currentItem.attr( "aria-disabled", "true" );
17926                this._addClass( currentItem, null, "ui-state-disabled" );
17927            } else {
17928                currentItem.removeAttr( "aria-disabled" );
17929                this._removeClass( currentItem, null, "ui-state-disabled" );
17930            }
17931        }
17932
17933        this.options.disabled = disabled;
17934
17935        this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
17936            disabled === true );
17937    },
17938
17939    _setupEvents: function( event ) {
17940        var events = {};
17941        if ( event ) {
17942            $.each( event.split( " " ), function( index, eventName ) {
17943                events[ eventName ] = "_eventHandler";
17944            } );
17945        }
17946
17947        this._off( this.anchors.add( this.tabs ).add( this.panels ) );
17948
17949        // Always prevent the default action, even when disabled
17950        this._on( true, this.anchors, {
17951            click: function( event ) {
17952                event.preventDefault();
17953            }
17954        } );
17955        this._on( this.anchors, events );
17956        this._on( this.tabs, { keydown: "_tabKeydown" } );
17957        this._on( this.panels, { keydown: "_panelKeydown" } );
17958
17959        this._focusable( this.tabs );
17960        this._hoverable( this.tabs );
17961    },
17962
17963    _setupHeightStyle: function( heightStyle ) {
17964        var maxHeight,
17965            parent = this.element.parent();
17966
17967        if ( heightStyle === "fill" ) {
17968            maxHeight = parent.height();
17969            maxHeight -= this.element.outerHeight() - this.element.height();
17970
17971            this.element.siblings( ":visible" ).each( function() {
17972                var elem = $( this ),
17973                    position = elem.css( "position" );
17974
17975                if ( position === "absolute" || position === "fixed" ) {
17976                    return;
17977                }
17978                maxHeight -= elem.outerHeight( true );
17979            } );
17980
17981            this.element.children().not( this.panels ).each( function() {
17982                maxHeight -= $( this ).outerHeight( true );
17983            } );
17984
17985            this.panels.each( function() {
17986                $( this ).height( Math.max( 0, maxHeight -
17987                    $( this ).innerHeight() + $( this ).height() ) );
17988            } )
17989                .css( "overflow", "auto" );
17990        } else if ( heightStyle === "auto" ) {
17991            maxHeight = 0;
17992            this.panels.each( function() {
17993                maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
17994            } ).height( maxHeight );
17995        }
17996    },
17997
17998    _eventHandler: function( event ) {
17999        var options = this.options,
18000            active = this.active,
18001            anchor = $( event.currentTarget ),
18002            tab = anchor.closest( "li" ),
18003            clickedIsActive = tab[ 0 ] === active[ 0 ],
18004            collapsing = clickedIsActive && options.collapsible,
18005            toShow = collapsing ? $() : this._getPanelForTab( tab ),
18006            toHide = !active.length ? $() : this._getPanelForTab( active ),
18007            eventData = {
18008                oldTab: active,
18009                oldPanel: toHide,
18010                newTab: collapsing ? $() : tab,
18011                newPanel: toShow
18012            };
18013
18014        event.preventDefault();
18015
18016        if ( tab.hasClass( "ui-state-disabled" ) ||
18017
18018                // tab is already loading
18019                tab.hasClass( "ui-tabs-loading" ) ||
18020
18021                // can't switch durning an animation
18022                this.running ||
18023
18024                // click on active header, but not collapsible
18025                ( clickedIsActive && !options.collapsible ) ||
18026
18027                // allow canceling activation
18028                ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
18029            return;
18030        }
18031
18032        options.active = collapsing ? false : this.tabs.index( tab );
18033
18034        this.active = clickedIsActive ? $() : tab;
18035        if ( this.xhr ) {
18036            this.xhr.abort();
18037        }
18038
18039        if ( !toHide.length && !toShow.length ) {
18040            $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
18041        }
18042
18043        if ( toShow.length ) {
18044            this.load( this.tabs.index( tab ), event );
18045        }
18046        this._toggle( event, eventData );
18047    },
18048
18049    // Handles show/hide for selecting tabs
18050    _toggle: function( event, eventData ) {
18051        var that = this,
18052            toShow = eventData.newPanel,
18053            toHide = eventData.oldPanel;
18054
18055        this.running = true;
18056
18057        function complete() {
18058            that.running = false;
18059            that._trigger( "activate", event, eventData );
18060        }
18061
18062        function show() {
18063            that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
18064
18065            if ( toShow.length && that.options.show ) {
18066                that._show( toShow, that.options.show, complete );
18067            } else {
18068                toShow.show();
18069                complete();
18070            }
18071        }
18072
18073        // Start out by hiding, then showing, then completing
18074        if ( toHide.length && this.options.hide ) {
18075            this._hide( toHide, this.options.hide, function() {
18076                that._removeClass( eventData.oldTab.closest( "li" ),
18077                    "ui-tabs-active", "ui-state-active" );
18078                show();
18079            } );
18080        } else {
18081            this._removeClass( eventData.oldTab.closest( "li" ),
18082                "ui-tabs-active", "ui-state-active" );
18083            toHide.hide();
18084            show();
18085        }
18086
18087        toHide.attr( "aria-hidden", "true" );
18088        eventData.oldTab.attr( {
18089            "aria-selected": "false",
18090            "aria-expanded": "false"
18091        } );
18092
18093        // If we're switching tabs, remove the old tab from the tab order.
18094        // If we're opening from collapsed state, remove the previous tab from the tab order.
18095        // If we're collapsing, then keep the collapsing tab in the tab order.
18096        if ( toShow.length && toHide.length ) {
18097            eventData.oldTab.attr( "tabIndex", -1 );
18098        } else if ( toShow.length ) {
18099            this.tabs.filter( function() {
18100                return $( this ).attr( "tabIndex" ) === 0;
18101            } )
18102                .attr( "tabIndex", -1 );
18103        }
18104
18105        toShow.attr( "aria-hidden", "false" );
18106        eventData.newTab.attr( {
18107            "aria-selected": "true",
18108            "aria-expanded": "true",
18109            tabIndex: 0
18110        } );
18111    },
18112
18113    _activate: function( index ) {
18114        var anchor,
18115            active = this._findActive( index );
18116
18117        // Trying to activate the already active panel
18118        if ( active[ 0 ] === this.active[ 0 ] ) {
18119            return;
18120        }
18121
18122        // Trying to collapse, simulate a click on the current active header
18123        if ( !active.length ) {
18124            active = this.active;
18125        }
18126
18127        anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
18128        this._eventHandler( {
18129            target: anchor,
18130            currentTarget: anchor,
18131            preventDefault: $.noop
18132        } );
18133    },
18134
18135    _findActive: function( index ) {
18136        return index === false ? $() : this.tabs.eq( index );
18137    },
18138
18139    _getIndex: function( index ) {
18140
18141        // meta-function to give users option to provide a href string instead of a numerical index.
18142        if ( typeof index === "string" ) {
18143            index = this.anchors.index( this.anchors.filter( "[href$='" +
18144                CSS.escape( index ) + "']" ) );
18145        }
18146
18147        return index;
18148    },
18149
18150    _destroy: function() {
18151        if ( this.xhr ) {
18152            this.xhr.abort();
18153        }
18154
18155        this.tablist
18156            .removeAttr( "role" )
18157            .off( this.eventNamespace );
18158
18159        this.anchors
18160            .removeAttr( "role tabIndex" )
18161            .removeUniqueId();
18162
18163        this.tabs.add( this.panels ).each( function() {
18164            if ( $.data( this, "ui-tabs-destroy" ) ) {
18165                $( this ).remove();
18166            } else {
18167                $( this ).removeAttr( "role tabIndex " +
18168                    "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
18169            }
18170        } );
18171
18172        this.tabs.each( function() {
18173            var li = $( this ),
18174                prev = li.data( "ui-tabs-aria-controls" );
18175            if ( prev ) {
18176                li
18177                    .attr( "aria-controls", prev )
18178                    .removeData( "ui-tabs-aria-controls" );
18179            } else {
18180                li.removeAttr( "aria-controls" );
18181            }
18182        } );
18183
18184        this.panels.show();
18185
18186        if ( this.options.heightStyle !== "content" ) {
18187            this.panels.css( "height", "" );
18188        }
18189    },
18190
18191    enable: function( index ) {
18192        var disabled = this.options.disabled;
18193        if ( disabled === false ) {
18194            return;
18195        }
18196
18197        if ( index === undefined ) {
18198            disabled = false;
18199        } else {
18200            index = this._getIndex( index );
18201            if ( Array.isArray( disabled ) ) {
18202                disabled = $.map( disabled, function( num ) {
18203                    return num !== index ? num : null;
18204                } );
18205            } else {
18206                disabled = $.map( this.tabs, function( li, num ) {
18207                    return num !== index ? num : null;
18208                } );
18209            }
18210        }
18211        this._setOptionDisabled( disabled );
18212    },
18213
18214    disable: function( index ) {
18215        var disabled = this.options.disabled;
18216        if ( disabled === true ) {
18217            return;
18218        }
18219
18220        if ( index === undefined ) {
18221            disabled = true;
18222        } else {
18223            index = this._getIndex( index );
18224            if ( $.inArray( index, disabled ) !== -1 ) {
18225                return;
18226            }
18227            if ( Array.isArray( disabled ) ) {
18228                disabled = $.merge( [ index ], disabled ).sort();
18229            } else {
18230                disabled = [ index ];
18231            }
18232        }
18233        this._setOptionDisabled( disabled );
18234    },
18235
18236    load: function( index, event ) {
18237        index = this._getIndex( index );
18238        var that = this,
18239            tab = this.tabs.eq( index ),
18240            anchor = tab.find( ".ui-tabs-anchor" ),
18241            panel = this._getPanelForTab( tab ),
18242            eventData = {
18243                tab: tab,
18244                panel: panel
18245            },
18246            complete = function( jqXHR, status ) {
18247                if ( status === "abort" ) {
18248                    that.panels.stop( false, true );
18249                }
18250
18251                that._removeClass( tab, "ui-tabs-loading" );
18252                panel.removeAttr( "aria-busy" );
18253
18254                if ( jqXHR === that.xhr ) {
18255                    delete that.xhr;
18256                }
18257            };
18258
18259        // Not remote
18260        if ( this._isLocal( anchor[ 0 ] ) ) {
18261            return;
18262        }
18263
18264        this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
18265
18266        if ( this.xhr.statusText !== "canceled" ) {
18267            this._addClass( tab, "ui-tabs-loading" );
18268            panel.attr( "aria-busy", "true" );
18269
18270            this.xhr
18271                .done( function( response, status, jqXHR ) {
18272                    panel.html( response );
18273                    that._trigger( "load", event, eventData );
18274
18275                    complete( jqXHR, status );
18276                } )
18277                .fail( function( jqXHR, status ) {
18278                    complete( jqXHR, status );
18279                } );
18280        }
18281    },
18282
18283    _ajaxSettings: function( anchor, event, eventData ) {
18284        var that = this;
18285        return {
18286            url: anchor.attr( "href" ),
18287            beforeSend: function( jqXHR, settings ) {
18288                return that._trigger( "beforeLoad", event,
18289                    $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
18290            }
18291        };
18292    },
18293
18294    _getPanelForTab: function( tab ) {
18295        var id = $( tab ).attr( "aria-controls" );
18296        return this.element.find( "#" + CSS.escape( id ) );
18297    }
18298} );
18299
18300// DEPRECATED
18301// TODO: Switch return back to widget declaration at top of file when this is removed
18302if ( $.uiBackCompat === true ) {
18303
18304    // Backcompat for ui-tab class (now ui-tabs-tab)
18305    $.widget( "ui.tabs", $.ui.tabs, {
18306        _processTabs: function() {
18307            this._superApply( arguments );
18308            this._addClass( this.tabs, "ui-tab" );
18309        }
18310    } );
18311}
18312
18313var widgetsTabs = $.ui.tabs;
18314
18315
18316/*!
18317 * jQuery UI Tooltip 1.14.1
18318 * https://jqueryui.com
18319 *
18320 * Copyright OpenJS Foundation and other contributors
18321 * Released under the MIT license.
18322 * https://jquery.org/license
18323 */
18324
18325//>>label: Tooltip
18326//>>group: Widgets
18327//>>description: Shows additional information for any element on hover or focus.
18328//>>docs: https://api.jqueryui.com/tooltip/
18329//>>demos: https://jqueryui.com/tooltip/
18330//>>css.structure: ../../themes/base/core.css
18331//>>css.structure: ../../themes/base/tooltip.css
18332//>>css.theme: ../../themes/base/theme.css
18333
18334
18335$.widget( "ui.tooltip", {
18336    version: "1.14.1",
18337    options: {
18338        classes: {
18339            "ui-tooltip": "ui-corner-all ui-widget-shadow"
18340        },
18341        content: function() {
18342            var title = $( this ).attr( "title" );
18343
18344            // Escape title, since we're going from an attribute to raw HTML
18345            return $( "<a>" ).text( title ).html();
18346        },
18347        hide: true,
18348
18349        // Disabled elements have inconsistent behavior across browsers (#8661)
18350        items: "[title]:not([disabled])",
18351        position: {
18352            my: "left top+15",
18353            at: "left bottom",
18354            collision: "flipfit flip"
18355        },
18356        show: true,
18357        track: false,
18358
18359        // Callbacks
18360        close: null,
18361        open: null
18362    },
18363
18364    _addDescribedBy: function( elem, id ) {
18365        var describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ );
18366        describedby.push( id );
18367        elem
18368            .data( "ui-tooltip-id", id )
18369            .attr( "aria-describedby", String.prototype.trim.call( describedby.join( " " ) ) );
18370    },
18371
18372    _removeDescribedBy: function( elem ) {
18373        var id = elem.data( "ui-tooltip-id" ),
18374            describedby = ( elem.attr( "aria-describedby" ) || "" ).split( /\s+/ ),
18375            index = $.inArray( id, describedby );
18376
18377        if ( index !== -1 ) {
18378            describedby.splice( index, 1 );
18379        }
18380
18381        elem.removeData( "ui-tooltip-id" );
18382        describedby = String.prototype.trim.call( describedby.join( " " ) );
18383        if ( describedby ) {
18384            elem.attr( "aria-describedby", describedby );
18385        } else {
18386            elem.removeAttr( "aria-describedby" );
18387        }
18388    },
18389
18390    _create: function() {
18391        this._on( {
18392            mouseover: "open",
18393            focusin: "open"
18394        } );
18395
18396        // IDs of generated tooltips, needed for destroy
18397        this.tooltips = {};
18398
18399        // IDs of parent tooltips where we removed the title attribute
18400        this.parents = {};
18401
18402        // Append the aria-live region so tooltips announce correctly
18403        this.liveRegion = $( "<div>" )
18404            .attr( {
18405                role: "log",
18406                "aria-live": "assertive",
18407                "aria-relevant": "additions"
18408            } )
18409            .appendTo( this.document[ 0 ].body );
18410        this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
18411
18412        this.disabledTitles = $( [] );
18413    },
18414
18415    _setOption: function( key, value ) {
18416        var that = this;
18417
18418        this._super( key, value );
18419
18420        if ( key === "content" ) {
18421            $.each( this.tooltips, function( id, tooltipData ) {
18422                that._updateContent( tooltipData.element );
18423            } );
18424        }
18425    },
18426
18427    _setOptionDisabled: function( value ) {
18428        this[ value ? "_disable" : "_enable" ]();
18429    },
18430
18431    _disable: function() {
18432        var that = this;
18433
18434        // Close open tooltips
18435        $.each( this.tooltips, function( id, tooltipData ) {
18436            var event = $.Event( "blur" );
18437            event.target = event.currentTarget = tooltipData.element[ 0 ];
18438            that.close( event, true );
18439        } );
18440
18441        // Remove title attributes to prevent native tooltips
18442        this.disabledTitles = this.disabledTitles.add(
18443            this.element.find( this.options.items ).addBack()
18444                .filter( function() {
18445                    var element = $( this );
18446                    if ( element.is( "[title]" ) ) {
18447                        return element
18448                            .data( "ui-tooltip-title", element.attr( "title" ) )
18449                            .removeAttr( "title" );
18450                    }
18451                } )
18452        );
18453    },
18454
18455    _enable: function() {
18456
18457        // restore title attributes
18458        this.disabledTitles.each( function() {
18459            var element = $( this );
18460            if ( element.data( "ui-tooltip-title" ) ) {
18461                element.attr( "title", element.data( "ui-tooltip-title" ) );
18462            }
18463        } );
18464        this.disabledTitles = $( [] );
18465    },
18466
18467    open: function( event ) {
18468        var that = this,
18469            target = $( event ? event.target : this.element )
18470
18471                // we need closest here due to mouseover bubbling,
18472                // but always pointing at the same event target
18473                .closest( this.options.items );
18474
18475        // No element to show a tooltip for or the tooltip is already open
18476        if ( !target.length || target.data( "ui-tooltip-id" ) ) {
18477            return;
18478        }
18479
18480        if ( target.attr( "title" ) ) {
18481            target.data( "ui-tooltip-title", target.attr( "title" ) );
18482        }
18483
18484        target.data( "ui-tooltip-open", true );
18485
18486        // Kill parent tooltips, custom or native, for hover
18487        if ( event && event.type === "mouseover" ) {
18488            target.parents().each( function() {
18489                var parent = $( this ),
18490                    blurEvent;
18491                if ( parent.data( "ui-tooltip-open" ) ) {
18492                    blurEvent = $.Event( "blur" );
18493                    blurEvent.target = blurEvent.currentTarget = this;
18494                    that.close( blurEvent, true );
18495                }
18496                if ( parent.attr( "title" ) ) {
18497                    parent.uniqueId();
18498                    that.parents[ this.id ] = {
18499                        element: this,
18500                        title: parent.attr( "title" )
18501                    };
18502                    parent.attr( "title", "" );
18503                }
18504            } );
18505        }
18506
18507        this._registerCloseHandlers( event, target );
18508        this._updateContent( target, event );
18509    },
18510
18511    _updateContent: function( target, event ) {
18512        var content,
18513            contentOption = this.options.content,
18514            that = this,
18515            eventType = event ? event.type : null;
18516
18517        if ( typeof contentOption === "string" || contentOption.nodeType ||
18518                contentOption.jquery ) {
18519            return this._open( event, target, contentOption );
18520        }
18521
18522        content = contentOption.call( target[ 0 ], function( response ) {
18523
18524            // Ignore async response if tooltip was closed already
18525            if ( !target.data( "ui-tooltip-open" ) ) {
18526                return;
18527            }
18528
18529            // JQuery creates a special event for focusin when it doesn't
18530            // exist natively. To improve performance, the native event
18531            // object is reused and the type is changed. Therefore, we can't
18532            // rely on the type being correct after the event finished
18533            // bubbling, so we set it back to the previous value. (#8740)
18534            if ( event ) {
18535                event.type = eventType;
18536            }
18537            that._open( event, target, response );
18538        } );
18539        if ( content ) {
18540            this._open( event, target, content );
18541        }
18542    },
18543
18544    _open: function( event, target, content ) {
18545        var tooltipData, tooltip, delayedShow, a11yContent,
18546            positionOption = $.extend( {}, this.options.position );
18547
18548        if ( !content ) {
18549            return;
18550        }
18551
18552        // Content can be updated multiple times. If the tooltip already
18553        // exists, then just update the content and bail.
18554        tooltipData = this._find( target );
18555        if ( tooltipData ) {
18556            tooltipData.tooltip.find( ".ui-tooltip-content" ).html( content );
18557            return;
18558        }
18559
18560        // If we have a title, clear it to prevent the native tooltip
18561        // we have to check first to avoid defining a title if none exists
18562        // (we don't want to cause an element to start matching [title])
18563        //
18564        // We use removeAttr only for key events, to allow IE to export the correct
18565        // accessible attributes. For mouse events, set to empty string to avoid
18566        // native tooltip showing up (happens only when removing inside mouseover).
18567        if ( target.is( "[title]" ) ) {
18568            if ( event && event.type === "mouseover" ) {
18569                target.attr( "title", "" );
18570            } else {
18571                target.removeAttr( "title" );
18572            }
18573        }
18574
18575        tooltipData = this._tooltip( target );
18576        tooltip = tooltipData.tooltip;
18577        this._addDescribedBy( target, tooltip.attr( "id" ) );
18578        tooltip.find( ".ui-tooltip-content" ).html( content );
18579
18580        // Support: Voiceover on OS X, JAWS on IE <= 9
18581        // JAWS announces deletions even when aria-relevant="additions"
18582        // Voiceover will sometimes re-read the entire log region's contents from the beginning
18583        this.liveRegion.children().hide();
18584        a11yContent = $( "<div>" ).html( tooltip.find( ".ui-tooltip-content" ).html() );
18585        a11yContent.removeAttr( "name" ).find( "[name]" ).removeAttr( "name" );
18586        a11yContent.removeAttr( "id" ).find( "[id]" ).removeAttr( "id" );
18587        a11yContent.appendTo( this.liveRegion );
18588
18589        function position( event ) {
18590            positionOption.of = event;
18591            if ( tooltip.is( ":hidden" ) ) {
18592                return;
18593            }
18594            tooltip.position( positionOption );
18595        }
18596        if ( this.options.track && event && /^mouse/.test( event.type ) ) {
18597            this._on( this.document, {
18598                mousemove: position
18599            } );
18600
18601            // trigger once to override element-relative positioning
18602            position( event );
18603        } else {
18604            tooltip.position( $.extend( {
18605                of: target
18606            }, this.options.position ) );
18607        }
18608
18609        tooltip.hide();
18610
18611        this._show( tooltip, this.options.show );
18612
18613        // Handle tracking tooltips that are shown with a delay (#8644). As soon
18614        // as the tooltip is visible, position the tooltip using the most recent
18615        // event.
18616        // Adds the check to add the timers only when both delay and track options are set (#14682)
18617        if ( this.options.track && this.options.show && this.options.show.delay ) {
18618            delayedShow = this.delayedShow = setInterval( function() {
18619                if ( tooltip.is( ":visible" ) ) {
18620                    position( positionOption.of );
18621                    clearInterval( delayedShow );
18622                }
18623            }, 13 );
18624        }
18625
18626        this._trigger( "open", event, { tooltip: tooltip } );
18627    },
18628
18629    _registerCloseHandlers: function( event, target ) {
18630        var events = {
18631            keyup: function( event ) {
18632                if ( event.keyCode === $.ui.keyCode.ESCAPE ) {
18633                    var fakeEvent = $.Event( event );
18634                    fakeEvent.currentTarget = target[ 0 ];
18635                    this.close( fakeEvent, true );
18636                }
18637            }
18638        };
18639
18640        // Only bind remove handler for delegated targets. Non-delegated
18641        // tooltips will handle this in destroy.
18642        if ( target[ 0 ] !== this.element[ 0 ] ) {
18643            events.remove = function() {
18644                var targetElement = this._find( target );
18645                if ( targetElement ) {
18646                    this._removeTooltip( targetElement.tooltip );
18647                }
18648            };
18649        }
18650
18651        if ( !event || event.type === "mouseover" ) {
18652            events.mouseleave = "close";
18653        }
18654        if ( !event || event.type === "focusin" ) {
18655            events.focusout = "close";
18656        }
18657        this._on( true, target, events );
18658    },
18659
18660    close: function( event ) {
18661        var tooltip,
18662            that = this,
18663            target = $( event ? event.currentTarget : this.element ),
18664            tooltipData = this._find( target );
18665
18666        // The tooltip may already be closed
18667        if ( !tooltipData ) {
18668
18669            // We set ui-tooltip-open immediately upon open (in open()), but only set the
18670            // additional data once there's actually content to show (in _open()). So even if the
18671            // tooltip doesn't have full data, we always remove ui-tooltip-open in case we're in
18672            // the period between open() and _open().
18673            target.removeData( "ui-tooltip-open" );
18674            return;
18675        }
18676
18677        tooltip = tooltipData.tooltip;
18678
18679        // Disabling closes the tooltip, so we need to track when we're closing
18680        // to avoid an infinite loop in case the tooltip becomes disabled on close
18681        if ( tooltipData.closing ) {
18682            return;
18683        }
18684
18685        // Clear the interval for delayed tracking tooltips
18686        clearInterval( this.delayedShow );
18687
18688        // Only set title if we had one before (see comment in _open())
18689        // If the title attribute has changed since open(), don't restore
18690        if ( target.data( "ui-tooltip-title" ) && !target.attr( "title" ) ) {
18691            target.attr( "title", target.data( "ui-tooltip-title" ) );
18692        }
18693
18694        this._removeDescribedBy( target );
18695
18696        tooltipData.hiding = true;
18697        tooltip.stop( true );
18698        this._hide( tooltip, this.options.hide, function() {
18699            that._removeTooltip( $( this ) );
18700        } );
18701
18702        target.removeData( "ui-tooltip-open" );
18703        this._off( target, "mouseleave focusout keyup" );
18704
18705        // Remove 'remove' binding only on delegated targets
18706        if ( target[ 0 ] !== this.element[ 0 ] ) {
18707            this._off( target, "remove" );
18708        }
18709        this._off( this.document, "mousemove" );
18710
18711        if ( event && event.type === "mouseleave" ) {
18712            $.each( this.parents, function( id, parent ) {
18713                $( parent.element ).attr( "title", parent.title );
18714                delete that.parents[ id ];
18715            } );
18716        }
18717
18718        tooltipData.closing = true;
18719        this._trigger( "close", event, { tooltip: tooltip } );
18720        if ( !tooltipData.hiding ) {
18721            tooltipData.closing = false;
18722        }
18723    },
18724
18725    _tooltip: function( element ) {
18726        var tooltip = $( "<div>" ).attr( "role", "tooltip" ),
18727            content = $( "<div>" ).appendTo( tooltip ),
18728            id = tooltip.uniqueId().attr( "id" );
18729
18730        this._addClass( content, "ui-tooltip-content" );
18731        this._addClass( tooltip, "ui-tooltip", "ui-widget ui-widget-content" );
18732
18733        tooltip.appendTo( this._appendTo( element ) );
18734
18735        return this.tooltips[ id ] = {
18736            element: element,
18737            tooltip: tooltip
18738        };
18739    },
18740
18741    _find: function( target ) {
18742        var id = target.data( "ui-tooltip-id" );
18743        return id ? this.tooltips[ id ] : null;
18744    },
18745
18746    _removeTooltip: function( tooltip ) {
18747
18748        // Clear the interval for delayed tracking tooltips
18749        clearInterval( this.delayedShow );
18750
18751        tooltip.remove();
18752        delete this.tooltips[ tooltip.attr( "id" ) ];
18753    },
18754
18755    _appendTo: function( target ) {
18756        var element = target.closest( ".ui-front, dialog" );
18757
18758        if ( !element.length ) {
18759            element = this.document[ 0 ].body;
18760        }
18761
18762        return element;
18763    },
18764
18765    _destroy: function() {
18766        var that = this;
18767
18768        // Close open tooltips
18769        $.each( this.tooltips, function( id, tooltipData ) {
18770
18771            // Delegate to close method to handle common cleanup
18772            var event = $.Event( "blur" ),
18773                element = tooltipData.element;
18774            event.target = event.currentTarget = element[ 0 ];
18775            that.close( event, true );
18776
18777            // Remove immediately; destroying an open tooltip doesn't use the
18778            // hide animation
18779            $( "#" + id ).remove();
18780
18781            // Restore the title
18782            if ( element.data( "ui-tooltip-title" ) ) {
18783
18784                // If the title attribute has changed since open(), don't restore
18785                if ( !element.attr( "title" ) ) {
18786                    element.attr( "title", element.data( "ui-tooltip-title" ) );
18787                }
18788                element.removeData( "ui-tooltip-title" );
18789            }
18790        } );
18791        this.liveRegion.remove();
18792    }
18793} );
18794
18795// DEPRECATED
18796// TODO: Switch return back to widget declaration at top of file when this is removed
18797if ( $.uiBackCompat === true ) {
18798
18799    // Backcompat for tooltipClass option
18800    $.widget( "ui.tooltip", $.ui.tooltip, {
18801        options: {
18802            tooltipClass: null
18803        },
18804        _tooltip: function() {
18805            var tooltipData = this._superApply( arguments );
18806            if ( this.options.tooltipClass ) {
18807                tooltipData.tooltip.addClass( this.options.tooltipClass );
18808            }
18809            return tooltipData;
18810        }
18811    } );
18812}
18813
18814var widgetsTooltip = $.ui.tooltip;
18815
18816
18817
18818
18819} );

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.