PageSourceSearch

https://langfordplanning.com/concrete/js/jquery-ui.js?_v=1.14.1

js langfordplanning.com collected 2026-09-30 13:56:14 UTC 629,028 bytes, 18,310 lines download raw bytes

vendor: 558,056 bytes, lines 1-16235
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
4* Copyright OpenJS Foundation and other contributors; Licensed MIT */
5
6// enable 1.11 API
7$.uiBackCompat = true;
8
9( function( factory ) {
10    "use strict";
11
12    if ( typeof define === "function" && define.amd ) {
13
14        // AMD. Register as an anonymous module.
15        define( [ "jquery" ], factory );
16    } else {
17
18        // Browser globals
19        factory( jQuery );
20    }
21} )( function( $ ) {
22"use strict";
23
24$.ui = $.ui || {};
25
26var version = $.ui.version = "1.14.1";
27
28/*!
29 * jQuery UI Widget 1.14.1
30 * https://jqueryui.com
31 *
32 * Copyright OpenJS Foundation and other contributors
33 * Released under the MIT license.
34 * https://jquery.org/license
35 */
36
37//>>label: Widget
38//>>group: Core
39//>>description: Provides a factory for creating stateful widgets with a common API.
40//>>docs: https://api.jqueryui.com/jQuery.widget/
41//>>demos: https://jqueryui.com/widget/
42
43
44var widgetUuid = 0;
45var widgetHasOwnProperty = Array.prototype.hasOwnProperty;
46var widgetSlice = Array.prototype.slice;
47
48$.cleanData = ( function( orig ) {
49    return function( elems ) {
50        var events, elem, i;
51        for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
52
53            // Only trigger remove when necessary to save time
54            events = $._data( elem, "events" );
55            if ( events && events.remove ) {
56                $( elem ).triggerHandler( "remove" );
57            }
58        }
59        orig( elems );
60    };
61} )( $.cleanData );
62
63$.widget = function( name, base, prototype ) {
64    var existingConstructor, constructor, basePrototype;
65
66    // ProxiedPrototype allows the provided prototype to remain unmodified
67    // so that it can be used as a mixin for multiple widgets (#8876)
68    var proxiedPrototype = {};
69
70    var namespace = name.split( "." )[ 0 ];
71    name = name.split( "." )[ 1 ];
72    if ( name === "__proto__" || name === "constructor" ) {
73        return $.error( "Invalid widget name: " + name );
74    }
75    var fullName = namespace + "-" + name;
76
77    if ( !prototype ) {
78        prototype = base;
79        base = $.Widget;
80    }
81
82    if ( Array.isArray( prototype ) ) {
83        prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
84    }
85
86    // Create selector for plugin
87    $.expr.pseudos[ fullName.toLowerCase() ] = function( elem ) {
88        return !!$.data( elem, fullName );
89    };
90
91    $[ namespace ] = $[ namespace ] || {};
92    existingConstructor = $[ namespace ][ name ];
93    constructor = $[ namespace ][ name ] = function( options, element ) {
94
95        // Allow instantiation without "new" keyword
96        if ( !this || !this._createWidget ) {
97            return new constructor( options, element );
98        }
99
100        // Allow instantiation without initializing for simple inheritance
101        // must use "new" keyword (the code above always passes args)
102        if ( arguments.length ) {
103            this._createWidget( options, element );
104        }
105    };
106
107    // Extend with the existing constructor to carry over any static properties
108    $.extend( constructor, existingConstructor, {
109        version: prototype.version,
110
111        // Copy the object used to create the prototype in case we need to
112        // redefine the widget later
113        _proto: $.extend( {}, prototype ),
114
115        // Track widgets that inherit from this widget in case this widget is
116        // redefined after a widget inherits from it
117        _childConstructors: []
118    } );
119
120    basePrototype = new base();
121
122    // We need to make the options hash a property directly on the new instance
123    // otherwise we'll modify the options hash on the prototype that we're
124    // inheriting from
125    basePrototype.options = $.widget.extend( {}, basePrototype.options );
126    $.each( prototype, function( prop, value ) {
127        if ( typeof value !== "function" ) {
128            proxiedPrototype[ prop ] = value;
129            return;
130        }
131        proxiedPrototype[ prop ] = ( function() {
132            function _super() {
133                return base.prototype[ prop ].apply( this, arguments );
134            }
135
136            function _superApply( args ) {
137                return base.prototype[ prop ].apply( this, args );
138            }
139
140            return function() {
141                var __super = this._super;
142                var __superApply = this._superApply;
143                var returnValue;
144
145                this._super = _super;
146                this._superApply = _superApply;
147
148                returnValue = value.apply( this, arguments );
149
150                this._super = __super;
151                this._superApply = __superApply;
152
153                return returnValue;
154            };
155        } )();
156    } );
157    constructor.prototype = $.widget.extend( basePrototype, {
158
159        // TODO: remove support for widgetEventPrefix
160        // always use the name + a colon as the prefix, e.g., draggable:start
161        // don't prefix for widgets that aren't DOM-based
162        widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
163    }, proxiedPrototype, {
164        constructor: constructor,
165        namespace: namespace,
166        widgetName: name,
167        widgetFullName: fullName
168    } );
169
170    // If this widget is being redefined then we need to find all widgets that
171    // are inheriting from it and redefine all of them so that they inherit from
172    // the new version of this widget. We're essentially trying to replace one
173    // level in the prototype chain.
174    if ( existingConstructor ) {
175        $.each( existingConstructor._childConstructors, function( i, child ) {
176            var childPrototype = child.prototype;
177
178            // Redefine the child widget using the same prototype that was
179            // originally used, but inherit from the new version of the base
180            $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
181                child._proto );
182        } );
183
184        // Remove the list of existing child constructors from the old constructor
185        // so the old child constructors can be garbage collected
186        delete existingConstructor._childConstructors;
187    } else {
188        base._childConstructors.push( constructor );
189    }
190
191    $.widget.bridge( name, constructor );
192
193    return constructor;
194};
195
196$.widget.extend = function( target ) {
197    var input = widgetSlice.call( arguments, 1 );
198    var inputIndex = 0;
199    var inputLength = input.length;
200    var key;
201    var value;
202
203    for ( ; inputIndex < inputLength; inputIndex++ ) {
204        for ( key in input[ inputIndex ] ) {
205            value = input[ inputIndex ][ key ];
206            if ( widgetHasOwnProperty.call( input[ inputIndex ], key ) && value !== undefined ) {
207
208                // Clone objects
209                if ( $.isPlainObject( value ) ) {
210                    target[ key ] = $.isPlainObject( target[ key ] ) ?
211                        $.widget.extend( {}, target[ key ], value ) :
212
213                        // Don't extend strings, arrays, etc. with objects
214                        $.widget.extend( {}, value );
215
216                // Copy everything else by reference
217                } else {
218                    target[ key ] = value;
219                }
220            }
221        }
222    }
223    return target;
224};
225
226$.widget.bridge = function( name, object ) {
227    var fullName = object.prototype.widgetFullName || name;
228    $.fn[ name ] = function( options ) {
229        var isMethodCall = typeof options === "string";
230        var args = widgetSlice.call( arguments, 1 );
231        var returnValue = this;
232
233        if ( isMethodCall ) {
234
235            // If this is an empty collection, we need to have the instance method
236            // return undefined instead of the jQuery instance
237            if ( !this.length && options === "instance" ) {
238                returnValue = undefined;
239            } else {
240                this.each( function() {
241                    var methodValue;
242                    var instance = $.data( this, fullName );
243
244                    if ( options === "instance" ) {
245                        returnValue = instance;
246                        return false;
247                    }
248
249                    if ( !instance ) {
250                        return $.error( "cannot call methods on " + name +
251                            " prior to initialization; " +
252                            "attempted to call method '" + options + "'" );
253                    }
254
255                    if ( typeof instance[ options ] !== "function" ||
256                        options.charAt( 0 ) === "_" ) {
257                        return $.error( "no such method '" + options + "' for " + name +
258                            " widget instance" );
259                    }
260
261                    methodValue = instance[ options ].apply( instance, args );
262
263                    if ( methodValue !== instance && methodValue !== undefined ) {
264                        returnValue = methodValue && methodValue.jquery ?
265                            returnValue.pushStack( methodValue.get() ) :
266                            methodValue;
267                        return false;
268                    }
269                } );
270            }
271        } else {
272
273            // Allow multiple hashes to be passed on init
274            if ( args.length ) {
275                options = $.widget.extend.apply( null, [ options ].concat( args ) );
276            }
277
278            this.each( function() {
279                var instance = $.data( this, fullName );
280                if ( instance ) {
281                    instance.option( options || {} );
282                    if ( instance._init ) {
283                        instance._init();
284                    }
285                } else {
286                    $.data( this, fullName, new object( options, this ) );
287                }
288            } );
289        }
290
291        return returnValue;
292    };
293};
294
295$.Widget = function( /* options, element */ ) {};
296$.Widget._childConstructors = [];
297
298$.Widget.prototype = {
299    widgetName: "widget",
300    widgetEventPrefix: "",
301    defaultElement: "<div>",
302
303    options: {
304        classes: {},
305        disabled: false,
306
307        // Callbacks
308        create: null
309    },
310
311    _createWidget: function( options, element ) {
312        element = $( element || this.defaultElement || this )[ 0 ];
313        this.element = $( element );
314        this.uuid = widgetUuid++;
315        this.eventNamespace = "." + this.widgetName + this.uuid;
316
317        this.bindings = $();
318        this.hoverable = $();
319        this.focusable = $();
320        this.classesElementLookup = {};
321
322        if ( element !== this ) {
323            $.data( element, this.widgetFullName, this );
324            this._on( true, this.element, {
325                remove: function( event ) {
326                    if ( event.target === element ) {
327                        this.destroy();
328                    }
329                }
330            } );
331            this.document = $( element.style ?
332
333                // Element within the document
334                element.ownerDocument :
335
336                // Element is window or document
337                element.document || element );
338            this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
339        }
340
341        this.options = $.widget.extend( {},
342            this.options,
343            this._getCreateOptions(),
344            options );
345
346        this._create();
347
348        if ( this.options.disabled ) {
349            this._setOptionDisabled( this.options.disabled );
350        }
351
352        this._trigger( "create", null, this._getCreateEventData() );
353        this._init();
354    },
355
356    _getCreateOptions: function() {
357        return {};
358    },
359
360    _getCreateEventData: $.noop,
361
362    _create: $.noop,
363
364    _init: $.noop,
365
366    destroy: function() {
367        var that = this;
368
369        this._destroy();
370        $.each( this.classesElementLookup, function( key, value ) {
371            that._removeClass( value, key );
372        } );
373
374        // We can probably remove the unbind calls in 2.0
375        // all event bindings should go through this._on()
376        this.element
377            .off( this.eventNamespace )
378            .removeData( this.widgetFullName );
379        this.widget()
380            .off( this.eventNamespace )
381            .removeAttr( "aria-disabled" );
382
383        // Clean up events and states
384        this.bindings.off( this.eventNamespace );
385    },
386
387    _destroy: $.noop,
388
389    widget: function() {
390        return this.element;
391    },
392
393    option: function( key, value ) {
394        var options = key;
395        var parts;
396        var curOption;
397        var i;
398
399        if ( arguments.length === 0 ) {
400
401            // Don't return a reference to the internal hash
402            return $.widget.extend( {}, this.options );
403        }
404
405        if ( typeof key === "string" ) {
406
407            // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
408            options = {};
409            parts = key.split( "." );
410            key = parts.shift();
411            if ( parts.length ) {
412                curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
413                for ( i = 0; i < parts.length - 1; i++ ) {
414                    curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
415                    curOption = curOption[ parts[ i ] ];
416                }
417                key = parts.pop();
418                if ( arguments.length === 1 ) {
419                    return curOption[ key ] === undefined ? null : curOption[ key ];
420                }
421                curOption[ key ] = value;
422            } else {
423                if ( arguments.length === 1 ) {
424                    return this.options[ key ] === undefined ? null : this.options[ key ];
425                }
426                options[ key ] = value;
427            }
428        }
429
430        this._setOptions( options );
431
432        return this;
433    },
434
435    _setOptions: function( options ) {
436        var key;
437
438        for ( key in options ) {
439            this._setOption( key, options[ key ] );
440        }
441
442        return this;
443    },
444
445    _setOption: function( key, value ) {
446        if ( key === "classes" ) {
447            this._setOptionClasses( value );
448        }
449
450        this.options[ key ] = value;
451
452        if ( key === "disabled" ) {
453            this._setOptionDisabled( value );
454        }
455
456        return this;
457    },
458
459    _setOptionClasses: function( value ) {
460        var classKey, elements, currentElements;
461
462        for ( classKey in value ) {
463            currentElements = this.classesElementLookup[ classKey ];
464            if ( value[ classKey ] === this.options.classes[ classKey ] ||
465                    !currentElements ||
466                    !currentElements.length ) {
467                continue;
468            }
469
470            // We are doing this to create a new jQuery object because the _removeClass() call
471            // on the next line is going to destroy the reference to the current elements being
472            // tracked. We need to save a copy of this collection so that we can add the new classes
473            // below.
474            elements = $( currentElements.get() );
475            this._removeClass( currentElements, classKey );
476
477            // We don't use _addClass() here, because that uses this.options.classes
478            // for generating the string of classes. We want to use the value passed in from
479            // _setOption(), this is the new value of the classes option which was passed to
480            // _setOption(). We pass this value directly to _classes().
481            elements.addClass( this._classes( {
482                element: elements,
483                keys: classKey,
484                classes: value,
485                add: true
486            } ) );
487        }
488    },
489
490    _setOptionDisabled: function( value ) {
491        this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );
492
493        // If the widget is becoming disabled, then nothing is interactive
494        if ( value ) {
495            this._removeClass( this.hoverable, null, "ui-state-hover" );
496            this._removeClass( this.focusable, null, "ui-state-focus" );
497        }
498    },
499
500    enable: function() {
501        return this._setOptions( { disabled: false } );
502    },
503
504    disable: function() {
505        return this._setOptions( { disabled: true } );
506    },
507
508    _classes: function( options ) {
509        var full = [];
510        var that = this;
511
512        options = $.extend( {
513            element: this.element,
514            classes: this.options.classes || {}
515        }, options );
516
517        function bindRemoveEvent() {
518            var nodesToBind = [];
519
520            options.element.each( function( _, element ) {
521                var isTracked = $.map( that.classesElementLookup, function( elements ) {
522                    return elements;
523                } )
524                    .some( function( elements ) {
525                        return elements.is( element );
526                    } );
527
528                if ( !isTracked ) {
529                    nodesToBind.push( element );
530                }
531            } );
532
533            that._on( $( nodesToBind ), {
534                remove: "_untrackClassesElement"
535            } );
536        }
537
538        function processClassString( classes, checkOption ) {
539            var current, i;
540            for ( i = 0; i < classes.length; i++ ) {
541                current = that.classesElementLookup[ classes[ i ] ] || $();
542                if ( options.add ) {
543                    bindRemoveEvent();
544                    current = $( $.uniqueSort( current.get().concat( options.element.get() ) ) );
545                } else {
546                    current = $( current.not( options.element ).get() );
547                }
548                that.classesElementLookup[ classes[ i ] ] = current;
549                full.push( classes[ i ] );
550                if ( checkOption && options.classes[ classes[ i ] ] ) {
551                    full.push( options.classes[ classes[ i ] ] );
552                }
553            }
554        }
555
556        if ( options.keys ) {
557            processClassString( options.keys.match( /\S+/g ) || [], true );
558        }
559        if ( options.extra ) {
560            processClassString( options.extra.match( /\S+/g ) || [] );
561        }
562
563        return full.join( " " );
564    },
565
566    _untrackClassesElement: function( event ) {
567        var that = this;
568        $.each( that.classesElementLookup, function( key, value ) {
569            if ( $.inArray( event.target, value ) !== -1 ) {
570                that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
571            }
572        } );
573
574        this._off( $( event.target ) );
575    },
576
577    _removeClass: function( element, keys, extra ) {
578        return this._toggleClass( element, keys, extra, false );
579    },
580
581    _addClass: function( element, keys, extra ) {
582        return this._toggleClass( element, keys, extra, true );
583    },
584
585    _toggleClass: function( element, keys, extra, add ) {
586        add = ( typeof add === "boolean" ) ? add : extra;
587        var shift = ( typeof element === "string" || element === null ),
588            options = {
589                extra: shift ? keys : extra,
590                keys: shift ? element : keys,
591                element: shift ? this.element : element,
592                add: add
593            };
594        options.element.toggleClass( this._classes( options ), add );
595        return this;
596    },
597
598    _on: function( suppressDisabledCheck, element, handlers ) {
599        var delegateElement;
600        var instance = this;
601
602        // No suppressDisabledCheck flag, shuffle arguments
603        if ( typeof suppressDisabledCheck !== "boolean" ) {
604            handlers = element;
605            element = suppressDisabledCheck;
606            suppressDisabledCheck = false;
607        }
608
609        // No element argument, shuffle and use this.element
610        if ( !handlers ) {
611            handlers = element;
612            element = this.element;
613            delegateElement = this.widget();
614        } else {
615            element = delegateElement = $( element );
616            this.bindings = this.bindings.add( element );
617        }
618
619        $.each( handlers, function( event, handler ) {
620            function handlerProxy() {
621
622                // Allow widgets to customize the disabled handling
623                // - disabled as an array instead of boolean
624                // - disabled class as method for disabling individual parts
625                if ( !suppressDisabledCheck &&
626                        ( instance.options.disabled === true ||
627                        $( this ).hasClass( "ui-state-disabled" ) ) ) {
628                    return;
629                }
630                return ( typeof handler === "string" ? instance[ handler ] : handler )
631                    .apply( instance, arguments );
632            }
633
634            // Copy the guid so direct unbinding works
635            if ( typeof handler !== "string" ) {
636                handlerProxy.guid = handler.guid =
637                    handler.guid || handlerProxy.guid || $.guid++;
638            }
639
640            var match = event.match( /^([\w:-]*)\s*(.*)$/ );
641            var eventName = match[ 1 ] + instance.eventNamespace;
642            var selector = match[ 2 ];
643
644            if ( selector ) {
645                delegateElement.on( eventName, selector, handlerProxy );
646            } else {
647                element.on( eventName, handlerProxy );
648            }
649        } );
650    },
651
652    _off: function( element, eventName ) {
653        eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
654            this.eventNamespace;
655        element.off( eventName );
656
657        // Clear the stack to avoid memory leaks (#10056)
658        this.bindings = $( this.bindings.not( element ).get() );
659        this.focusable = $( this.focusable.not( element ).get() );
660        this.hoverable = $( this.hoverable.not( element ).get() );
661    },
662
663    _delay: function( handler, delay ) {
664        function handlerProxy() {
665            return ( typeof handler === "string" ? instance[ handler ] : handler )
666                .apply( instance, arguments );
667        }
668        var instance = this;
669        return setTimeout( handlerProxy, delay || 0 );
670    },
671
672    _hoverable: function( element ) {
673        this.hoverable = this.hoverable.add( element );
674        this._on( element, {
675            mouseenter: function( event ) {
676                this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
677            },
678            mouseleave: function( event ) {
679                this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
680            }
681        } );
682    },
683
684    _focusable: function( element ) {
685        this.focusable = this.focusable.add( element );
686        this._on( element, {
687            focusin: function( event ) {
688                this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
689            },
690            focusout: function( event ) {
691                this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
692            }
693        } );
694    },
695
696    _trigger: function( type, event, data ) {
697        var prop, orig;
698        var callback = this.options[ type ];
699
700        data = data || {};
701        event = $.Event( event );
702        event.type = ( type === this.widgetEventPrefix ?
703            type :
704            this.widgetEventPrefix + type ).toLowerCase();
705
706        // The original event may come from any element
707        // so we need to reset the target on the new event
708        event.target = this.element[ 0 ];
709
710        // Copy original event properties over to the new event
711        orig = event.originalEvent;
712        if ( orig ) {
713            for ( prop in orig ) {
714                if ( !( prop in event ) ) {
715                    event[ prop ] = orig[ prop ];
716                }
717            }
718        }
719
720        this.element.trigger( event, data );
721        return !( typeof callback === "function" &&
722            callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
723            event.isDefaultPrevented() );
724    }
725};
726
727$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
728    $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
729        if ( typeof options === "string" ) {
730            options = { effect: options };
731        }
732
733        var hasOptions;
734        var effectName = !options ?
735            method :
736            options === true || typeof options === "number" ?
737                defaultEffect :
738                options.effect || defaultEffect;
739
740        options = options || {};
741        if ( typeof options === "number" ) {
742            options = { duration: options };
743        } else if ( options === true ) {
744            options = {};
745        }
746
747        hasOptions = !$.isEmptyObject( options );
748        options.complete = callback;
749
750        if ( options.delay ) {
751            element.delay( options.delay );
752        }
753
754        if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
755            element[ method ]( options );
756        } else if ( effectName !== method && element[ effectName ] ) {
757            element[ effectName ]( options.duration, options.easing, callback );
758        } else {
759            element.queue( function( next ) {
760                $( this )[ method ]();
761                if ( callback ) {
762                    callback.call( element[ 0 ] );
763                }
764                next();
765            } );
766        }
767    };
768} );
769
770var widget = $.widget;
771
772
773/*!
774 * jQuery UI Position 1.14.1
775 * https://jqueryui.com
776 *
777 * Copyright OpenJS Foundation and other contributors
778 * Released under the MIT license.
779 * https://jquery.org/license
780 *
781 * https://api.jqueryui.com/position/
782 */
783
784//>>label: Position
785//>>group: Core
786//>>description: Positions elements relative to other elements.
787//>>docs: https://api.jqueryui.com/position/
788//>>demos: https://jqueryui.com/position/
789
790
791( function() {
792var cachedScrollbarWidth,
793    max = Math.max,
794    abs = Math.abs,
795    rhorizontal = /left|center|right/,
796    rvertical = /top|center|bottom/,
797    roffset = /[\+\-]\d+(\.[\d]+)?%?/,
798    rposition = /^\w+/,
799    rpercent = /%$/,
800    _position = $.fn.position;
801
802function getOffsets( offsets, width, height ) {
803    return [
804        parseFloat( offsets[ 0 ] ) * ( rpercent.test( offsets[ 0 ] ) ? width / 100 : 1 ),
805        parseFloat( offsets[ 1 ] ) * ( rpercent.test( offsets[ 1 ] ) ? height / 100 : 1 )
806    ];
807}
808
809function parseCss( element, property ) {
810    return parseInt( $.css( element, property ), 10 ) || 0;
811}
812
813function isWindow( obj ) {
814    return obj != null && obj === obj.window;
815}
816
817function getDimensions( elem ) {
818    var raw = elem[ 0 ];
819    if ( raw.nodeType === 9 ) {
820        return {
821            width: elem.width(),
822            height: elem.height(),
823            offset: { top: 0, left: 0 }
824        };
825    }
826    if ( isWindow( raw ) ) {
827        return {
828            width: elem.width(),
829            height: elem.height(),
830            offset: { top: elem.scrollTop(), left: elem.scrollLeft() }
831        };
832    }
833    if ( raw.preventDefault ) {
834        return {
835            width: 0,
836            height: 0,
837            offset: { top: raw.pageY, left: raw.pageX }
838        };
839    }
840    return {
841        width: elem.outerWidth(),
842        height: elem.outerHeight(),
843        offset: elem.offset()
844    };
845}
846
847$.position = {
848    scrollbarWidth: function() {
849        if ( cachedScrollbarWidth !== undefined ) {
850            return cachedScrollbarWidth;
851        }
852        var w1, w2,
853            div = $( "<div style=" +
854                "'display:block;position:absolute;width:200px;height:200px;overflow:hidden;'>" +
855                "<div style='height:300px;width:auto;'></div></div>" ),
856            innerDiv = div.children()[ 0 ];
857
858        $( "body" ).append( div );
859        w1 = innerDiv.offsetWidth;
860        div.css( "overflow", "scroll" );
861
862        w2 = innerDiv.offsetWidth;
863
864        if ( w1 === w2 ) {
865            w2 = div[ 0 ].clientWidth;
866        }
867
868        div.remove();
869
870        return ( cachedScrollbarWidth = w1 - w2 );
871    },
872    getScrollInfo: function( within ) {
873        var overflowX = within.isWindow || within.isDocument ? "" :
874                within.element.css( "overflow-x" ),
875            overflowY = within.isWindow || within.isDocument ? "" :
876                within.element.css( "overflow-y" ),
877            hasOverflowX = overflowX === "scroll" ||
878                ( overflowX === "auto" && within.width < within.element[ 0 ].scrollWidth ),
879            hasOverflowY = overflowY === "scroll" ||
880                ( overflowY === "auto" && within.height < within.element[ 0 ].scrollHeight );
881        return {
882            width: hasOverflowY ? $.position.scrollbarWidth() : 0,
883            height: hasOverflowX ? $.position.scrollbarWidth() : 0
884        };
885    },
886    getWithinInfo: function( element ) {
887        var withinElement = $( element || window ),
888            isElemWindow = isWindow( withinElement[ 0 ] ),
889            isDocument = !!withinElement[ 0 ] && withinElement[ 0 ].nodeType === 9,
890            hasOffset = !isElemWindow && !isDocument;
891        return {
892            element: withinElement,
893            isWindow: isElemWindow,
894            isDocument: isDocument,
895            offset: hasOffset ? $( element ).offset() : { left: 0, top: 0 },
896            scrollLeft: withinElement.scrollLeft(),
897            scrollTop: withinElement.scrollTop(),
898            width: withinElement.outerWidth(),
899            height: withinElement.outerHeight()
900        };
901    }
902};
903
904$.fn.position = function( options ) {
905    if ( !options || !options.of ) {
906        return _position.apply( this, arguments );
907    }
908
909    // Make a copy, we don't want to modify arguments
910    options = $.extend( {}, options );
911
912    var atOffset, targetWidth, targetHeight, targetOffset, basePosition, dimensions,
913
914        // Make sure string options are treated as CSS selectors
915        target = typeof options.of === "string" ?
916            $( document ).find( options.of ) :
917            $( options.of ),
918
919        within = $.position.getWithinInfo( options.within ),
920        scrollInfo = $.position.getScrollInfo( within ),
921        collision = ( options.collision || "flip" ).split( " " ),
922        offsets = {};
923
924    dimensions = getDimensions( target );
925    if ( target[ 0 ].preventDefault ) {
926
927        // Force left top to allow flipping
928        options.at = "left top";
929    }
930    targetWidth = dimensions.width;
931    targetHeight = dimensions.height;
932    targetOffset = dimensions.offset;
933
934    // Clone to reuse original targetOffset later
935    basePosition = $.extend( {}, targetOffset );
936
937    // Force my and at to have valid horizontal and vertical positions
938    // if a value is missing or invalid, it will be converted to center
939    $.each( [ "my", "at" ], function() {
940        var pos = ( options[ this ] || "" ).split( " " ),
941            horizontalOffset,
942            verticalOffset;
943
944        if ( pos.length === 1 ) {
945            pos = rhorizontal.test( pos[ 0 ] ) ?
946                pos.concat( [ "center" ] ) :
947                rvertical.test( pos[ 0 ] ) ?
948                    [ "center" ].concat( pos ) :
949                    [ "center", "center" ];
950        }
951        pos[ 0 ] = rhorizontal.test( pos[ 0 ] ) ? pos[ 0 ] : "center";
952        pos[ 1 ] = rvertical.test( pos[ 1 ] ) ? pos[ 1 ] : "center";
953
954        // Calculate offsets
955        horizontalOffset = roffset.exec( pos[ 0 ] );
956        verticalOffset = roffset.exec( pos[ 1 ] );
957        offsets[ this ] = [
958            horizontalOffset ? horizontalOffset[ 0 ] : 0,
959            verticalOffset ? verticalOffset[ 0 ] : 0
960        ];
961
962        // Reduce to just the positions without the offsets
963        options[ this ] = [
964            rposition.exec( pos[ 0 ] )[ 0 ],
965            rposition.exec( pos[ 1 ] )[ 0 ]
966        ];
967    } );
968
969    // Normalize collision option
970    if ( collision.length === 1 ) {
971        collision[ 1 ] = collision[ 0 ];
972    }
973
974    if ( options.at[ 0 ] === "right" ) {
975        basePosition.left += targetWidth;
976    } else if ( options.at[ 0 ] === "center" ) {
977        basePosition.left += targetWidth / 2;
978    }
979
980    if ( options.at[ 1 ] === "bottom" ) {
981        basePosition.top += targetHeight;
982    } else if ( options.at[ 1 ] === "center" ) {
983        basePosition.top += targetHeight / 2;
984    }
985
986    atOffset = getOffsets( offsets.at, targetWidth, targetHeight );
987    basePosition.left += atOffset[ 0 ];
988    basePosition.top += atOffset[ 1 ];
989
990    return this.each( function() {
991        var collisionPosition, using,
992            elem = $( this ),
993            elemWidth = elem.outerWidth(),
994            elemHeight = elem.outerHeight(),
995            marginLeft = parseCss( this, "marginLeft" ),
996            marginTop = parseCss( this, "marginTop" ),
997            collisionWidth = elemWidth + marginLeft + parseCss( this, "marginRight" ) +
998                scrollInfo.width,
999            collisionHeight = elemHeight + marginTop + parseCss( this, "marginBottom" ) +
1000                scrollInfo.height,
1001            position = $.extend( {}, basePosition ),
1002            myOffset = getOffsets( offsets.my, elem.outerWidth(), elem.outerHeight() );
1003
1004        if ( options.my[ 0 ] === "right" ) {
1005            position.left -= elemWidth;
1006        } else if ( options.my[ 0 ] === "center" ) {
1007            position.left -= elemWidth / 2;
1008        }
1009
1010        if ( options.my[ 1 ] === "bottom" ) {
1011            position.top -= elemHeight;
1012        } else if ( options.my[ 1 ] === "center" ) {
1013            position.top -= elemHeight / 2;
1014        }
1015
1016        position.left += myOffset[ 0 ];
1017        position.top += myOffset[ 1 ];
1018
1019        collisionPosition = {
1020            marginLeft: marginLeft,
1021            marginTop: marginTop
1022        };
1023
1024        $.each( [ "left", "top" ], function( i, dir ) {
1025            if ( $.ui.position[ collision[ i ] ] ) {
1026                $.ui.position[ collision[ i ] ][ dir ]( position, {
1027                    targetWidth: targetWidth,
1028                    targetHeight: targetHeight,
1029                    elemWidth: elemWidth,
1030                    elemHeight: elemHeight,
1031                    collisionPosition: collisionPosition,
1032                    collisionWidth: collisionWidth,
1033                    collisionHeight: collisionHeight,
1034                    offset: [ atOffset[ 0 ] + myOffset[ 0 ], atOffset [ 1 ] + myOffset[ 1 ] ],
1035                    my: options.my,
1036                    at: options.at,
1037                    within: within,
1038                    elem: elem
1039                } );
1040            }
1041        } );
1042
1043        if ( options.using ) {
1044
1045            // Adds feedback as second argument to using callback, if present
1046            using = function( props ) {
1047                var left = targetOffset.left - position.left,
1048                    right = left + targetWidth - elemWidth,
1049                    top = targetOffset.top - position.top,
1050                    bottom = top + targetHeight - elemHeight,
1051                    feedback = {
1052                        target: {
1053                            element: target,
1054                            left: targetOffset.left,
1055                            top: targetOffset.top,
1056                            width: targetWidth,
1057                            height: targetHeight
1058                        },
1059                        element: {
1060                            element: elem,
1061                            left: position.left,
1062                            top: position.top,
1063                            width: elemWidth,
1064                            height: elemHeight
1065                        },
1066                        horizontal: right < 0 ? "left" : left > 0 ? "right" : "center",
1067                        vertical: bottom < 0 ? "top" : top > 0 ? "bottom" : "middle"
1068                    };
1069                if ( targetWidth < elemWidth && abs( left + right ) < targetWidth ) {
1070                    feedback.horizontal = "center";
1071                }
1072                if ( targetHeight < elemHeight && abs( top + bottom ) < targetHeight ) {
1073                    feedback.vertical = "middle";
1074                }
1075                if ( max( abs( left ), abs( right ) ) > max( abs( top ), abs( bottom ) ) ) {
1076                    feedback.important = "horizontal";
1077                } else {
1078                    feedback.important = "vertical";
1079                }
1080                options.using.call( this, props, feedback );
1081            };
1082        }
1083
1084        elem.offset( $.extend( position, { using: using } ) );
1085    } );
1086};
1087
1088$.ui.position = {
1089    fit: {
1090        left: function( position, data ) {
1091            var within = data.within,
1092                withinOffset = within.isWindow ? within.scrollLeft : within.offset.left,
1093                outerWidth = within.width,
1094                collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1095                overLeft = withinOffset - collisionPosLeft,
1096                overRight = collisionPosLeft + data.collisionWidth - outerWidth - withinOffset,
1097                newOverRight;
1098
1099            // Element is wider than within
1100            if ( data.collisionWidth > outerWidth ) {
1101
1102                // Element is initially over the left side of within
1103                if ( overLeft > 0 && overRight <= 0 ) {
1104                    newOverRight = position.left + overLeft + data.collisionWidth - outerWidth -
1105                        withinOffset;
1106                    position.left += overLeft - newOverRight;
1107
1108                // Element is initially over right side of within
1109                } else if ( overRight > 0 && overLeft <= 0 ) {
1110                    position.left = withinOffset;
1111
1112                // Element is initially over both left and right sides of within
1113                } else {
1114                    if ( overLeft > overRight ) {
1115                        position.left = withinOffset + outerWidth - data.collisionWidth;
1116                    } else {
1117                        position.left = withinOffset;
1118                    }
1119                }
1120
1121            // Too far left -> align with left edge
1122            } else if ( overLeft > 0 ) {
1123                position.left += overLeft;
1124
1125            // Too far right -> align with right edge
1126            } else if ( overRight > 0 ) {
1127                position.left -= overRight;
1128
1129            // Adjust based on position and margin
1130            } else {
1131                position.left = max( position.left - collisionPosLeft, position.left );
1132            }
1133        },
1134        top: function( position, data ) {
1135            var within = data.within,
1136                withinOffset = within.isWindow ? within.scrollTop : within.offset.top,
1137                outerHeight = data.within.height,
1138                collisionPosTop = position.top - data.collisionPosition.marginTop,
1139                overTop = withinOffset - collisionPosTop,
1140                overBottom = collisionPosTop + data.collisionHeight - outerHeight - withinOffset,
1141                newOverBottom;
1142
1143            // Element is taller than within
1144            if ( data.collisionHeight > outerHeight ) {
1145
1146                // Element is initially over the top of within
1147                if ( overTop > 0 && overBottom <= 0 ) {
1148                    newOverBottom = position.top + overTop + data.collisionHeight - outerHeight -
1149                        withinOffset;
1150                    position.top += overTop - newOverBottom;
1151
1152                // Element is initially over bottom of within
1153                } else if ( overBottom > 0 && overTop <= 0 ) {
1154                    position.top = withinOffset;
1155
1156                // Element is initially over both top and bottom of within
1157                } else {
1158                    if ( overTop > overBottom ) {
1159                        position.top = withinOffset + outerHeight - data.collisionHeight;
1160                    } else {
1161                        position.top = withinOffset;
1162                    }
1163                }
1164
1165            // Too far up -> align with top
1166            } else if ( overTop > 0 ) {
1167                position.top += overTop;
1168
1169            // Too far down -> align with bottom edge
1170            } else if ( overBottom > 0 ) {
1171                position.top -= overBottom;
1172
1173            // Adjust based on position and margin
1174            } else {
1175                position.top = max( position.top - collisionPosTop, position.top );
1176            }
1177        }
1178    },
1179    flip: {
1180        left: function( position, data ) {
1181            var within = data.within,
1182                withinOffset = within.offset.left + within.scrollLeft,
1183                outerWidth = within.width,
1184                offsetLeft = within.isWindow ? within.scrollLeft : within.offset.left,
1185                collisionPosLeft = position.left - data.collisionPosition.marginLeft,
1186                overLeft = collisionPosLeft - offsetLeft,
1187                overRight = collisionPosLeft + data.collisionWidth - outerWidth - offsetLeft,
1188                myOffset = data.my[ 0 ] === "left" ?
1189                    -data.elemWidth :
1190                    data.my[ 0 ] === "right" ?
1191                        data.elemWidth :
1192                        0,
1193                atOffset = data.at[ 0 ] === "left" ?
1194                    data.targetWidth :
1195                    data.at[ 0 ] === "right" ?
1196                        -data.targetWidth :
1197                        0,
1198                offset = -2 * data.offset[ 0 ],
1199                newOverRight,
1200                newOverLeft;
1201
1202            if ( overLeft < 0 ) {
1203                newOverRight = position.left + myOffset + atOffset + offset + data.collisionWidth -
1204                    outerWidth - withinOffset;
1205                if ( newOverRight < 0 || newOverRight < abs( overLeft ) ) {
1206                    position.left += myOffset + atOffset + offset;
1207                }
1208            } else if ( overRight > 0 ) {
1209                newOverLeft = position.left - data.collisionPosition.marginLeft + myOffset +
1210                    atOffset + offset - offsetLeft;
1211                if ( newOverLeft > 0 || abs( newOverLeft ) < overRight ) {
1212                    position.left += myOffset + atOffset + offset;
1213                }
1214            }
1215        },
1216        top: function( position, data ) {
1217            var within = data.within,
1218                withinOffset = within.offset.top + within.scrollTop,
1219                outerHeight = within.height,
1220                offsetTop = within.isWindow ? within.scrollTop : within.offset.top,
1221                collisionPosTop = position.top - data.collisionPosition.marginTop,
1222                overTop = collisionPosTop - offsetTop,
1223                overBottom = collisionPosTop + data.collisionHeight - outerHeight - offsetTop,
1224                top = data.my[ 1 ] === "top",
1225                myOffset = top ?
1226                    -data.elemHeight :
1227                    data.my[ 1 ] === "bottom" ?
1228                        data.elemHeight :
1229                        0,
1230                atOffset = data.at[ 1 ] === "top" ?
1231                    data.targetHeight :
1232                    data.at[ 1 ] === "bottom" ?
1233                        -data.targetHeight :
1234                        0,
1235                offset = -2 * data.offset[ 1 ],
1236                newOverTop,
1237                newOverBottom;
1238            if ( overTop < 0 ) {
1239                newOverBottom = position.top + myOffset + atOffset + offset + data.collisionHeight -
1240                    outerHeight - withinOffset;
1241                if ( newOverBottom < 0 || newOverBottom < abs( overTop ) ) {
1242                    position.top += myOffset + atOffset + offset;
1243                }
1244            } else if ( overBottom > 0 ) {
1245                newOverTop = position.top - data.collisionPosition.marginTop + myOffset + atOffset +
1246                    offset - offsetTop;
1247                if ( newOverTop > 0 || abs( newOverTop ) < overBottom ) {
1248                    position.top += myOffset + atOffset + offset;
1249                }
1250            }
1251        }
1252    },
1253    flipfit: {
1254        left: function() {
1255            $.ui.position.flip.left.apply( this, arguments );
1256            $.ui.position.fit.left.apply( this, arguments );
1257        },
1258        top: function() {
1259            $.ui.position.flip.top.apply( this, arguments );
1260            $.ui.position.fit.top.apply( this, arguments );
1261        }
1262    }
1263};
1264
1265} )();
1266
1267var position = $.ui.position;
1268
1269
1270/*!
1271 * jQuery UI :data 1.14.1
1272 * https://jqueryui.com
1273 *
1274 * Copyright OpenJS Foundation and other contributors
1275 * Released under the MIT license.
1276 * https://jquery.org/license
1277 */
1278
1279//>>label: :data Selector
1280//>>group: Core
1281//>>description: Selects elements which have data stored under the specified key.
1282//>>docs: https://api.jqueryui.com/data-selector/
1283
1284
1285var data = $.extend( $.expr.pseudos, {
1286    data: $.expr.createPseudo( function( dataName ) {
1287        return function( elem ) {
1288            return !!$.data( elem, dataName );
1289        };
1290    } )
1291} );
1292
1293/*!
1294 * jQuery UI Disable Selection 1.14.1
1295 * https://jqueryui.com
1296 *
1297 * Copyright OpenJS Foundation and other contributors
1298 * Released under the MIT license.
1299 * https://jquery.org/license
1300 */
1301
1302//>>label: disableSelection
1303//>>group: Core
1304//>>description: Disable selection of text content within the set of matched elements.
1305//>>docs: https://api.jqueryui.com/disableSelection/
1306
1307// This file is deprecated
1308
1309var disableSelection = $.fn.extend( {
1310    disableSelection: ( function() {
1311        var eventType = "onselectstart" in document.createElement( "div" ) ?
1312            "selectstart" :
1313            "mousedown";
1314
1315        return function() {
1316            return this.on( eventType + ".ui-disableSelection", function( event ) {
1317                event.preventDefault();
1318            } );
1319        };
1320    } )(),
1321
1322    enableSelection: function() {
1323        return this.off( ".ui-disableSelection" );
1324    }
1325} );
1326
1327
1328
1329// Create a local jQuery because jQuery Color relies on it and the
1330// global may not exist with AMD and a custom build (#10199).
1331// This module is a noop if used as a regular AMD module.
1332// eslint-disable-next-line no-unused-vars
1333var jQuery = $;
1334
1335
1336/*!
1337 * jQuery Color Animations v3.0.0
1338 * https://github.com/jquery/jquery-color
1339 *
1340 * Copyright OpenJS Foundation and other contributors
1341 * Released under the MIT license.
1342 * https://jquery.org/license
1343 *
1344 * Date: Wed May 15 16:49:44 2024 +0200
1345 */
1346
1347
1348    var stepHooks = "backgroundColor borderBottomColor borderLeftColor borderRightColor " +
1349        "borderTopColor color columnRuleColor outlineColor textDecorationColor textEmphasisColor",
1350
1351    class2type = {},
1352    toString = class2type.toString,
1353
1354    // plusequals test for += 100 -= 100
1355    rplusequals = /^([\-+])=\s*(\d+\.?\d*)/,
1356
1357    // a set of RE's that can match strings and generate color tuples.
1358    stringParsers = [ {
1359            re: /rgba?\(\s*(\d{1,3})\s*,\s*(\d{1,3})\s*,\s*(\d{1,3})\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1360            parse: function( execResult ) {
1361                return [
1362                    execResult[ 1 ],
1363                    execResult[ 2 ],
1364                    execResult[ 3 ],
1365                    execResult[ 4 ]
1366                ];
1367            }
1368        }, {
1369            re: /rgba?\(\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1370            parse: function( execResult ) {
1371                return [
1372                    execResult[ 1 ] * 2.55,
1373                    execResult[ 2 ] * 2.55,
1374                    execResult[ 3 ] * 2.55,
1375                    execResult[ 4 ]
1376                ];
1377            }
1378        }, {
1379
1380            // this regex ignores A-F because it's compared against an already lowercased string
1381            re: /#([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})([a-f0-9]{2})?/,
1382            parse: function( execResult ) {
1383                return [
1384                    parseInt( execResult[ 1 ], 16 ),
1385                    parseInt( execResult[ 2 ], 16 ),
1386                    parseInt( execResult[ 3 ], 16 ),
1387                    execResult[ 4 ] ?
1388                        ( parseInt( execResult[ 4 ], 16 ) / 255 ).toFixed( 2 ) :
1389                        1
1390                ];
1391            }
1392        }, {
1393
1394            // this regex ignores A-F because it's compared against an already lowercased string
1395            re: /#([a-f0-9])([a-f0-9])([a-f0-9])([a-f0-9])?/,
1396            parse: function( execResult ) {
1397                return [
1398                    parseInt( execResult[ 1 ] + execResult[ 1 ], 16 ),
1399                    parseInt( execResult[ 2 ] + execResult[ 2 ], 16 ),
1400                    parseInt( execResult[ 3 ] + execResult[ 3 ], 16 ),
1401                    execResult[ 4 ] ?
1402                        ( parseInt( execResult[ 4 ] + execResult[ 4 ], 16 ) / 255 )
1403                            .toFixed( 2 ) :
1404                        1
1405                ];
1406            }
1407        }, {
1408            re: /hsla?\(\s*(\d+(?:\.\d+)?)\s*,\s*(\d+(?:\.\d+)?)\%\s*,\s*(\d+(?:\.\d+)?)\%\s*(?:,\s*(\d?(?:\.\d+)?)\s*)?\)/,
1409            space: "hsla",
1410            parse: function( execResult ) {
1411                return [
1412                    execResult[ 1 ],
1413                    execResult[ 2 ] / 100,
1414                    execResult[ 3 ] / 100,
1415                    execResult[ 4 ]
1416                ];
1417            }
1418        } ],
1419
1420    // jQuery.Color( )
1421    color = jQuery.Color = function( color, green, blue, alpha ) {
1422        return new jQuery.Color.fn.parse( color, green, blue, alpha );
1423    },
1424    spaces = {
1425        rgba: {
1426            props: {
1427                red: {
1428                    idx: 0,
1429                    type: "byte"
1430                },
1431                green: {
1432                    idx: 1,
1433                    type: "byte"
1434                },
1435                blue: {
1436                    idx: 2,
1437                    type: "byte"
1438                }
1439            }
1440        },
1441
1442        hsla: {
1443            props: {
1444                hue: {
1445                    idx: 0,
1446                    type: "degrees"
1447                },
1448                saturation: {
1449                    idx: 1,
1450                    type: "percent"
1451                },
1452                lightness: {
1453                    idx: 2,
1454                    type: "percent"
1455                }
1456            }
1457        }
1458    },
1459    propTypes = {
1460        "byte": {
1461            floor: true,
1462            max: 255
1463        },
1464        "percent": {
1465            max: 1
1466        },
1467        "degrees": {
1468            mod: 360,
1469            floor: true
1470        }
1471    },
1472
1473    // colors = jQuery.Color.names
1474    colors,
1475
1476    // local aliases of functions called often
1477    each = jQuery.each;
1478
1479// define cache name and alpha properties
1480// for rgba and hsla spaces
1481each( spaces, function( spaceName, space ) {
1482    space.cache = "_" + spaceName;
1483    space.props.alpha = {
1484        idx: 3,
1485        type: "percent",
1486        def: 1
1487    };
1488} );
1489
1490// Populate the class2type map
1491jQuery.each( "Boolean Number String Function Array Date RegExp Object Error Symbol".split( " " ),
1492    function( _i, name ) {
1493        class2type[ "[object " + name + "]" ] = name.toLowerCase();
1494    } );
1495
1496function getType( obj ) {
1497    if ( obj == null ) {
1498        return obj + "";
1499    }
1500
1501    return typeof obj === "object" ?
1502        class2type[ toString.call( obj ) ] || "object" :
1503        typeof obj;
1504}
1505
1506function clamp( value, prop, allowEmpty ) {
1507    var type = propTypes[ prop.type ] || {};
1508
1509    if ( value == null ) {
1510        return ( allowEmpty || !prop.def ) ? null : prop.def;
1511    }
1512
1513    // ~~ is an short way of doing floor for positive numbers
1514    value = type.floor ? ~~value : parseFloat( value );
1515
1516    if ( type.mod ) {
1517
1518        // we add mod before modding to make sure that negatives values
1519        // get converted properly: -10 -> 350
1520        return ( value + type.mod ) % type.mod;
1521    }
1522
1523    // for now all property types without mod have min and max
1524    return Math.min( type.max, Math.max( 0, value ) );
1525}
1526
1527function stringParse( string ) {
1528    var inst = color(),
1529        rgba = inst._rgba = [];
1530
1531    string = string.toLowerCase();
1532
1533    each( stringParsers, function( _i, parser ) {
1534        var parsed,
1535            match = parser.re.exec( string ),
1536            values = match && parser.parse( match ),
1537            spaceName = parser.space || "rgba";
1538
1539        if ( values ) {
1540            parsed = inst[ spaceName ]( values );
1541
1542            // if this was an rgba parse the assignment might happen twice
1543            // oh well....
1544            inst[ spaces[ spaceName ].cache ] = parsed[ spaces[ spaceName ].cache ];
1545            rgba = inst._rgba = parsed._rgba;
1546
1547            // exit each( stringParsers ) here because we matched
1548            return false;
1549        }
1550    } );
1551
1552    // Found a stringParser that handled it
1553    if ( rgba.length ) {
1554
1555        // if this came from a parsed string, force "transparent" when alpha is 0
1556        // chrome, (and maybe others) return "transparent" as rgba(0,0,0,0)
1557        if ( rgba.join() === "0,0,0,0" ) {
1558            jQuery.extend( rgba, colors.transparent );
1559        }
1560        return inst;
1561    }
1562
1563    // named colors
1564    return colors[ string ];
1565}
1566
1567color.fn = jQuery.extend( color.prototype, {
1568    parse: function( red, green, blue, alpha ) {
1569        if ( red === undefined ) {
1570            this._rgba = [ null, null, null, null ];
1571            return this;
1572        }
1573        if ( red.jquery || red.nodeType ) {
1574            red = jQuery( red ).css( green );
1575            green = undefined;
1576        }
1577
1578        var inst = this,
1579            type = getType( red ),
1580            rgba = this._rgba = [];
1581
1582        // more than 1 argument specified - assume ( red, green, blue, alpha )
1583        if ( green !== undefined ) {
1584            red = [ red, green, blue, alpha ];
1585            type = "array";
1586        }
1587
1588        if ( type === "string" ) {
1589            return this.parse( stringParse( red ) || colors._default );
1590        }
1591
1592        if ( type === "array" ) {
1593            each( spaces.rgba.props, function( _key, prop ) {
1594                rgba[ prop.idx ] = clamp( red[ prop.idx ], prop );
1595            } );
1596            return this;
1597        }
1598
1599        if ( type === "object" ) {
1600            if ( red instanceof color ) {
1601                each( spaces, function( _spaceName, space ) {
1602                    if ( red[ space.cache ] ) {
1603                        inst[ space.cache ] = red[ space.cache ].slice();
1604                    }
1605                } );
1606            } else {
1607                each( spaces, function( _spaceName, space ) {
1608                    var cache = space.cache;
1609                    each( space.props, function( key, prop ) {
1610
1611                        // if the cache doesn't exist, and we know how to convert
1612                        if ( !inst[ cache ] && space.to ) {
1613
1614                            // if the value was null, we don't need to copy it
1615                            // if the key was alpha, we don't need to copy it either
1616                            if ( key === "alpha" || red[ key ] == null ) {
1617                                return;
1618                            }
1619                            inst[ cache ] = space.to( inst._rgba );
1620                        }
1621
1622                        // this is the only case where we allow nulls for ALL properties.
1623                        // call clamp with alwaysAllowEmpty
1624                        inst[ cache ][ prop.idx ] = clamp( red[ key ], prop, true );
1625                    } );
1626
1627                    // everything defined but alpha?
1628                    if ( inst[ cache ] && jQuery.inArray(
1629                        null,
1630                        inst[ cache ].slice( 0, 3 )
1631                    ) < 0 ) {
1632
1633                        // use the default of 1
1634                        if ( inst[ cache ][ 3 ] == null ) {
1635                            inst[ cache ][ 3 ] = 1;
1636                        }
1637
1638                        if ( space.from ) {
1639                            inst._rgba = space.from( inst[ cache ] );
1640                        }
1641                    }
1642                } );
1643            }
1644            return this;
1645        }
1646    },
1647    is: function( compare ) {
1648        var is = color( compare ),
1649            same = true,
1650            inst = this;
1651
1652        each( spaces, function( _, space ) {
1653            var localCache,
1654                isCache = is[ space.cache ];
1655            if ( isCache ) {
1656                localCache = inst[ space.cache ] || space.to && space.to( inst._rgba ) || [];
1657                each( space.props, function( _, prop ) {
1658                    if ( isCache[ prop.idx ] != null ) {
1659                        same = ( isCache[ prop.idx ] === localCache[ prop.idx ] );
1660                        return same;
1661                    }
1662                } );
1663            }
1664            return same;
1665        } );
1666        return same;
1667    },
1668    _space: function() {
1669        var used = [],
1670            inst = this;
1671        each( spaces, function( spaceName, space ) {
1672            if ( inst[ space.cache ] ) {
1673                used.push( spaceName );
1674            }
1675        } );
1676        return used.pop();
1677    },
1678    transition: function( other, distance ) {
1679        var end = color( other ),
1680            spaceName = end._space(),
1681            space = spaces[ spaceName ],
1682            startColor = this.alpha() === 0 ? color( "transparent" ) : this,
1683            start = startColor[ space.cache ] || space.to( startColor._rgba ),
1684            result = start.slice();
1685
1686        end = end[ space.cache ];
1687        each( space.props, function( _key, prop ) {
1688            var index = prop.idx,
1689                startValue = start[ index ],
1690                endValue = end[ index ],
1691                type = propTypes[ prop.type ] || {};
1692
1693            // if null, don't override start value
1694            if ( endValue === null ) {
1695                return;
1696            }
1697
1698            // if null - use end
1699            if ( startValue === null ) {
1700                result[ index ] = endValue;
1701            } else {
1702                if ( type.mod ) {
1703                    if ( endValue - startValue > type.mod / 2 ) {
1704                        startValue += type.mod;
1705                    } else if ( startValue - endValue > type.mod / 2 ) {
1706                        startValue -= type.mod;
1707                    }
1708                }
1709                result[ index ] = clamp( ( endValue - startValue ) * distance + startValue, prop );
1710            }
1711        } );
1712        return this[ spaceName ]( result );
1713    },
1714    blend: function( opaque ) {
1715
1716        // if we are already opaque - return ourself
1717        if ( this._rgba[ 3 ] === 1 ) {
1718            return this;
1719        }
1720
1721        var rgb = this._rgba.slice(),
1722            a = rgb.pop(),
1723            blend = color( opaque )._rgba;
1724
1725        return color( jQuery.map( rgb, function( v, i ) {
1726            return ( 1 - a ) * blend[ i ] + a * v;
1727        } ) );
1728    },
1729    toRgbaString: function() {
1730        var prefix = "rgba(",
1731            rgba = jQuery.map( this._rgba, function( v, i ) {
1732                if ( v != null ) {
1733                    return v;
1734                }
1735                return i > 2 ? 1 : 0;
1736            } );
1737
1738        if ( rgba[ 3 ] === 1 ) {
1739            rgba.pop();
1740            prefix = "rgb(";
1741        }
1742
1743        return prefix + rgba.join( ", " ) + ")";
1744    },
1745    toHslaString: function() {
1746        var prefix = "hsla(",
1747            hsla = jQuery.map( this.hsla(), function( v, i ) {
1748                if ( v == null ) {
1749                    v = i > 2 ? 1 : 0;
1750                }
1751
1752                // catch 1 and 2
1753                if ( i && i < 3 ) {
1754                    v = Math.round( v * 100 ) + "%";
1755                }
1756                return v;
1757            } );
1758
1759        if ( hsla[ 3 ] === 1 ) {
1760            hsla.pop();
1761            prefix = "hsl(";
1762        }
1763        return prefix + hsla.join( ", " ) + ")";
1764    },
1765    toHexString: function( includeAlpha ) {
1766        var rgba = this._rgba.slice(),
1767            alpha = rgba.pop();
1768
1769        if ( includeAlpha ) {
1770            rgba.push( ~~( alpha * 255 ) );
1771        }
1772
1773        return "#" + jQuery.map( rgba, function( v ) {
1774
1775            // default to 0 when nulls exist
1776            return ( "0" + ( v || 0 ).toString( 16 ) ).substr( -2 );
1777        } ).join( "" );
1778    },
1779    toString: function() {
1780        return this.toRgbaString();
1781    }
1782} );
1783color.fn.parse.prototype = color.fn;
1784
1785// hsla conversions adapted from:
1786// https://code.google.com/p/maashaack/source/browse/packages/graphics/trunk/src/graphics/colors/HUE2RGB.as?r=5021
1787
1788function hue2rgb( p, q, h ) {
1789    h = ( h + 1 ) % 1;
1790    if ( h * 6 < 1 ) {
1791        return p + ( q - p ) * h * 6;
1792    }
1793    if ( h * 2 < 1 ) {
1794        return q;
1795    }
1796    if ( h * 3 < 2 ) {
1797        return p + ( q - p ) * ( ( 2 / 3 ) - h ) * 6;
1798    }
1799    return p;
1800}
1801
1802spaces.hsla.to = function( rgba ) {
1803    if ( rgba[ 0 ] == null || rgba[ 1 ] == null || rgba[ 2 ] == null ) {
1804        return [ null, null, null, rgba[ 3 ] ];
1805    }
1806    var r = rgba[ 0 ] / 255,
1807        g = rgba[ 1 ] / 255,
1808        b = rgba[ 2 ] / 255,
1809        a = rgba[ 3 ],
1810        max = Math.max( r, g, b ),
1811        min = Math.min( r, g, b ),
1812        diff = max - min,
1813        add = max + min,
1814        l = add * 0.5,
1815        h, s;
1816
1817    if ( min === max ) {
1818        h = 0;
1819    } else if ( r === max ) {
1820        h = ( 60 * ( g - b ) / diff ) + 360;
1821    } else if ( g === max ) {
1822        h = ( 60 * ( b - r ) / diff ) + 120;
1823    } else {
1824        h = ( 60 * ( r - g ) / diff ) + 240;
1825    }
1826
1827    // chroma (diff) == 0 means greyscale which, by definition, saturation = 0%
1828    // otherwise, saturation is based on the ratio of chroma (diff) to lightness (add)
1829    if ( diff === 0 ) {
1830        s = 0;
1831    } else if ( l <= 0.5 ) {
1832        s = diff / add;
1833    } else {
1834        s = diff / ( 2 - add );
1835    }
1836    return [ Math.round( h ) % 360, s, l, a == null ? 1 : a ];
1837};
1838
1839spaces.hsla.from = function( hsla ) {
1840    if ( hsla[ 0 ] == null || hsla[ 1 ] == null || hsla[ 2 ] == null ) {
1841        return [ null, null, null, hsla[ 3 ] ];
1842    }
1843    var h = hsla[ 0 ] / 360,
1844        s = hsla[ 1 ],
1845        l = hsla[ 2 ],
1846        a = hsla[ 3 ],
1847        q = l <= 0.5 ? l * ( 1 + s ) : l + s - l * s,
1848        p = 2 * l - q;
1849
1850    return [
1851        Math.round( hue2rgb( p, q, h + ( 1 / 3 ) ) * 255 ),
1852        Math.round( hue2rgb( p, q, h ) * 255 ),
1853        Math.round( hue2rgb( p, q, h - ( 1 / 3 ) ) * 255 ),
1854        a
1855    ];
1856};
1857
1858
1859each( spaces, function( spaceName, space ) {
1860    var props = space.props,
1861        cache = space.cache,
1862        to = space.to,
1863        from = space.from;
1864
1865    // makes rgba() and hsla()
1866    color.fn[ spaceName ] = function( value ) {
1867
1868        // generate a cache for this space if it doesn't exist
1869        if ( to && !this[ cache ] ) {
1870            this[ cache ] = to( this._rgba );
1871        }
1872        if ( value === undefined ) {
1873            return this[ cache ].slice();
1874        }
1875
1876        var ret,
1877            type = getType( value ),
1878            arr = ( type === "array" || type === "object" ) ? value : arguments,
1879            local = this[ cache ].slice();
1880
1881        each( props, function( key, prop ) {
1882            var val = arr[ type === "object" ? key : prop.idx ];
1883            if ( val == null ) {
1884                val = local[ prop.idx ];
1885            }
1886            local[ prop.idx ] = clamp( val, prop );
1887        } );
1888
1889        if ( from ) {
1890            ret = color( from( local ) );
1891            ret[ cache ] = local;
1892            return ret;
1893        } else {
1894            return color( local );
1895        }
1896    };
1897
1898    // makes red() green() blue() alpha() hue() saturation() lightness()
1899    each( props, function( key, prop ) {
1900
1901        // alpha is included in more than one space
1902        if ( color.fn[ key ] ) {
1903            return;
1904        }
1905        color.fn[ key ] = function( value ) {
1906            var local, cur, match, fn,
1907                vtype = getType( value );
1908
1909            if ( key === "alpha" ) {
1910                fn = this._hsla ? "hsla" : "rgba";
1911            } else {
1912                fn = spaceName;
1913            }
1914            local = this[ fn ]();
1915            cur = local[ prop.idx ];
1916
1917            if ( vtype === "undefined" ) {
1918                return cur;
1919            }
1920
1921            if ( vtype === "function" ) {
1922                value = value.call( this, cur );
1923                vtype = getType( value );
1924            }
1925            if ( value == null && prop.empty ) {
1926                return this;
1927            }
1928            if ( vtype === "string" ) {
1929                match = rplusequals.exec( value );
1930                if ( match ) {
1931                    value = cur + parseFloat( match[ 2 ] ) * ( match[ 1 ] === "+" ? 1 : -1 );
1932                }
1933            }
1934            local[ prop.idx ] = value;
1935            return this[ fn ]( local );
1936        };
1937    } );
1938} );
1939
1940// add cssHook and .fx.step function for each named hook.
1941// accept a space separated string of properties
1942color.hook = function( hook ) {
1943    var hooks = hook.split( " " );
1944    each( hooks, function( _i, hook ) {
1945        jQuery.cssHooks[ hook ] = {
1946            set: function( elem, value ) {
1947                var parsed;
1948
1949                if ( value !== "transparent" &&
1950                    ( getType( value ) !== "string" ||
1951                        ( parsed = stringParse( value ) ) ) ) {
1952                    value = color( parsed || value );
1953                    value = value.toRgbaString();
1954                }
1955                elem.style[ hook ] = value;
1956            }
1957        };
1958        jQuery.fx.step[ hook ] = function( fx ) {
1959            if ( !fx.colorInit ) {
1960                fx.start = color( fx.elem, hook );
1961                fx.end = color( fx.end );
1962                fx.colorInit = true;
1963            }
1964            jQuery.cssHooks[ hook ].set( fx.elem, fx.start.transition( fx.end, fx.pos ) );
1965        };
1966    } );
1967
1968};
1969
1970color.hook( stepHooks );
1971
1972jQuery.cssHooks.borderColor = {
1973    expand: function( value ) {
1974        var expanded = {};
1975
1976        each( [ "Top", "Right", "Bottom", "Left" ], function( _i, part ) {
1977            expanded[ "border" + part + "Color" ] = value;
1978        } );
1979        return expanded;
1980    }
1981};
1982
1983// Basic color names only.
1984// Usage of any of the other color names requires adding yourself or including
1985// jquery.color.svg-names.js.
1986colors = jQuery.Color.names = {
1987
1988    // 4.1. Basic color keywords
1989    aqua: "#00ffff",
1990    black: "#000000",
1991    blue: "#0000ff",
1992    fuchsia: "#ff00ff",
1993    gray: "#808080",
1994    green: "#008000",
1995    lime: "#00ff00",
1996    maroon: "#800000",
1997    navy: "#000080",
1998    olive: "#808000",
1999    purple: "#800080",
2000    red: "#ff0000",
2001    silver: "#c0c0c0",
2002    teal: "#008080",
2003    white: "#ffffff",
2004    yellow: "#ffff00",
2005
2006    // 4.2.3. "transparent" color keyword
2007    transparent: [ null, null, null, 0 ],
2008
2009    _default: "#ffffff"
2010};
2011
2012
2013/*!
2014 * jQuery UI Effects 1.14.1
2015 * https://jqueryui.com
2016 *
2017 * Copyright OpenJS Foundation and other contributors
2018 * Released under the MIT license.
2019 * https://jquery.org/license
2020 */
2021
2022//>>label: Effects Core
2023//>>group: Effects
2024/* eslint-disable max-len */
2025//>>description: Extends the internal jQuery effects. Includes morphing and easing. Required by all other effects.
2026/* eslint-enable max-len */
2027//>>docs: https://api.jqueryui.com/category/effects-core/
2028//>>demos: https://jqueryui.com/effect/
2029
2030
2031var dataSpace = "ui-effects-",
2032    dataSpaceStyle = "ui-effects-style",
2033    dataSpaceAnimated = "ui-effects-animated";
2034
2035$.effects = {
2036    effect: {}
2037};
2038
2039/******************************************************************************/
2040/****************************** CLASS ANIMATIONS ******************************/
2041/******************************************************************************/
2042( function() {
2043
2044var classAnimationActions = [ "add", "remove", "toggle" ],
2045    shorthandStyles = {
2046        border: 1,
2047        borderBottom: 1,
2048        borderColor: 1,
2049        borderLeft: 1,
2050        borderRight: 1,
2051        borderTop: 1,
2052        borderWidth: 1,
2053        margin: 1,
2054        padding: 1
2055    };
2056
2057$.each(
2058    [ "borderLeftStyle", "borderRightStyle", "borderBottomStyle", "borderTopStyle" ],
2059    function( _, prop ) {
2060        $.fx.step[ prop ] = function( fx ) {
2061            if ( fx.end !== "none" && !fx.setAttr || fx.pos === 1 && !fx.setAttr ) {
2062                jQuery.style( fx.elem, prop, fx.end );
2063                fx.setAttr = true;
2064            }
2065        };
2066    }
2067);
2068
2069function camelCase( string ) {
2070    return string.replace( /-([\da-z])/gi, function( all, letter ) {
2071        return letter.toUpperCase();
2072    } );
2073}
2074
2075function getElementStyles( elem ) {
2076    var key, len,
2077        style = elem.ownerDocument.defaultView.getComputedStyle( elem ),
2078        styles = {};
2079
2080    len = style.length;
2081    while ( len-- ) {
2082        key = style[ len ];
2083        if ( typeof style[ key ] === "string" ) {
2084            styles[ camelCase( key ) ] = style[ key ];
2085        }
2086    }
2087
2088    return styles;
2089}
2090
2091function styleDifference( oldStyle, newStyle ) {
2092    var diff = {},
2093        name, value;
2094
2095    for ( name in newStyle ) {
2096        value = newStyle[ name ];
2097        if ( oldStyle[ name ] !== value ) {
2098            if ( !shorthandStyles[ name ] ) {
2099                if ( $.fx.step[ name ] || !isNaN( parseFloat( value ) ) ) {
2100                    diff[ name ] = value;
2101                }
2102            }
2103        }
2104    }
2105
2106    return diff;
2107}
2108
2109$.effects.animateClass = function( value, duration, easing, callback ) {
2110    var o = $.speed( duration, easing, callback );
2111
2112    return this.queue( function() {
2113        var animated = $( this ),
2114            baseClass = animated.attr( "class" ) || "",
2115            applyClassChange,
2116            allAnimations = o.children ? animated.find( "*" ).addBack() : animated;
2117
2118        // Map the animated objects to store the original styles.
2119        allAnimations = allAnimations.map( function() {
2120            var el = $( this );
2121            return {
2122                el: el,
2123                start: getElementStyles( this )
2124            };
2125        } );
2126
2127        // Apply class change
2128        applyClassChange = function() {
2129            $.each( classAnimationActions, function( i, action ) {
2130                if ( value[ action ] ) {
2131                    animated[ action + "Class" ]( value[ action ] );
2132                }
2133            } );
2134        };
2135        applyClassChange();
2136
2137        // Map all animated objects again - calculate new styles and diff
2138        allAnimations = allAnimations.map( function() {
2139            this.end = getElementStyles( this.el[ 0 ] );
2140            this.diff = styleDifference( this.start, this.end );
2141            return this;
2142        } );
2143
2144        // Apply original class
2145        animated.attr( "class", baseClass );
2146
2147        // Map all animated objects again - this time collecting a promise
2148        allAnimations = allAnimations.map( function() {
2149            var styleInfo = this,
2150                dfd = $.Deferred(),
2151                opts = $.extend( {}, o, {
2152                    queue: false,
2153                    complete: function() {
2154                        dfd.resolve( styleInfo );
2155                    }
2156                } );
2157
2158            this.el.animate( this.diff, opts );
2159            return dfd.promise();
2160        } );
2161
2162        // Once all animations have completed:
2163        $.when.apply( $, allAnimations.get() ).done( function() {
2164
2165            // Set the final class
2166            applyClassChange();
2167
2168            // For each animated element,
2169            // clear all css properties that were animated
2170            $.each( arguments, function() {
2171                var el = this.el;
2172                $.each( this.diff, function( key ) {
2173                    el.css( key, "" );
2174                } );
2175            } );
2176
2177            // This is guarnteed to be there if you use jQuery.speed()
2178            // it also handles dequeuing the next anim...
2179            o.complete.call( animated[ 0 ] );
2180        } );
2181    } );
2182};
2183
2184$.fn.extend( {
2185    addClass: ( function( orig ) {
2186        return function( classNames, speed, easing, callback ) {
2187            return speed ?
2188                $.effects.animateClass.call( this,
2189                    { add: classNames }, speed, easing, callback ) :
2190                orig.apply( this, arguments );
2191        };
2192    } )( $.fn.addClass ),
2193
2194    removeClass: ( function( orig ) {
2195        return function( classNames, speed, easing, callback ) {
2196            return arguments.length > 1 ?
2197                $.effects.animateClass.call( this,
2198                    { remove: classNames }, speed, easing, callback ) :
2199                orig.apply( this, arguments );
2200        };
2201    } )( $.fn.removeClass ),
2202
2203    toggleClass: ( function( orig ) {
2204        return function( classNames, force, speed, easing, callback ) {
2205            if ( typeof force === "boolean" || force === undefined ) {
2206                if ( !speed ) {
2207
2208                    // Without speed parameter
2209                    return orig.apply( this, arguments );
2210                } else {
2211                    return $.effects.animateClass.call( this,
2212                        ( force ? { add: classNames } : { remove: classNames } ),
2213                        speed, easing, callback );
2214                }
2215            } else {
2216
2217                // Without force parameter
2218                return $.effects.animateClass.call( this,
2219                    { toggle: classNames }, force, speed, easing );
2220            }
2221        };
2222    } )( $.fn.toggleClass ),
2223
2224    switchClass: function( remove, add, speed, easing, callback ) {
2225        return $.effects.animateClass.call( this, {
2226            add: add,
2227            remove: remove
2228        }, speed, easing, callback );
2229    }
2230} );
2231
2232} )();
2233
2234/******************************************************************************/
2235/*********************************** EFFECTS **********************************/
2236/******************************************************************************/
2237
2238( function() {
2239
2240if ( $.expr && $.expr.pseudos && $.expr.pseudos.animated ) {
2241    $.expr.pseudos.animated = ( function( orig ) {
2242        return function( elem ) {
2243            return !!$( elem ).data( dataSpaceAnimated ) || orig( elem );
2244        };
2245    } )( $.expr.pseudos.animated );
2246}
2247
2248if ( $.uiBackCompat === true ) {
2249    $.extend( $.effects, {
2250
2251        // Saves a set of properties in a data storage
2252        save: function( element, set ) {
2253            var i = 0, length = set.length;
2254            for ( ; i < length; i++ ) {
2255                if ( set[ i ] !== null ) {
2256                    element.data( dataSpace + set[ i ], element[ 0 ].style[ set[ i ] ] );
2257                }
2258            }
2259        },
2260
2261        // Restores a set of previously saved properties from a data storage
2262        restore: function( element, set ) {
2263            var val, i = 0, length = set.length;
2264            for ( ; i < length; i++ ) {
2265                if ( set[ i ] !== null ) {
2266                    val = element.data( dataSpace + set[ i ] );
2267                    element.css( set[ i ], val );
2268                }
2269            }
2270        },
2271
2272        setMode: function( el, mode ) {
2273            if ( mode === "toggle" ) {
2274                mode = el.is( ":hidden" ) ? "show" : "hide";
2275            }
2276            return mode;
2277        },
2278
2279        // Wraps the element around a wrapper that copies position properties
2280        createWrapper: function( element ) {
2281
2282            // If the element is already wrapped, return it
2283            if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2284                return element.parent();
2285            }
2286
2287            // Wrap the element
2288            var props = {
2289                    width: element.outerWidth( true ),
2290                    height: element.outerHeight( true ),
2291                    "float": element.css( "float" )
2292                },
2293                wrapper = $( "<div></div>" )
2294                    .addClass( "ui-effects-wrapper" )
2295                    .css( {
2296                        fontSize: "100%",
2297                        background: "transparent",
2298                        border: "none",
2299                        margin: 0,
2300                        padding: 0
2301                    } ),
2302
2303                // Store the size in case width/height are defined in % - Fixes #5245
2304                size = {
2305                    width: element.width(),
2306                    height: element.height()
2307                },
2308                active = document.activeElement;
2309
2310            // Support: Firefox
2311            // Firefox incorrectly exposes anonymous content
2312            // https://bugzilla.mozilla.org/show_bug.cgi?id=561664
2313            try {
2314                // eslint-disable-next-line no-unused-expressions
2315                active.id;
2316            } catch ( e ) {
2317                active = document.body;
2318            }
2319
2320            element.wrap( wrapper );
2321
2322            // Fixes #7595 - Elements lose focus when wrapped.
2323            if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2324                $( active ).trigger( "focus" );
2325            }
2326
2327            // Hotfix for jQuery 1.4 since some change in wrap() seems to actually
2328            // lose the reference to the wrapped element
2329            wrapper = element.parent();
2330
2331            // Transfer positioning properties to the wrapper
2332            if ( element.css( "position" ) === "static" ) {
2333                wrapper.css( { position: "relative" } );
2334                element.css( { position: "relative" } );
2335            } else {
2336                $.extend( props, {
2337                    position: element.css( "position" ),
2338                    zIndex: element.css( "z-index" )
2339                } );
2340                $.each( [ "top", "left", "bottom", "right" ], function( i, pos ) {
2341                    props[ pos ] = element.css( pos );
2342                    if ( isNaN( parseInt( props[ pos ], 10 ) ) ) {
2343                        props[ pos ] = "auto";
2344                    }
2345                } );
2346                element.css( {
2347                    position: "relative",
2348                    top: 0,
2349                    left: 0,
2350                    right: "auto",
2351                    bottom: "auto"
2352                } );
2353            }
2354            element.css( size );
2355
2356            return wrapper.css( props ).show();
2357        },
2358
2359        removeWrapper: function( element ) {
2360            var active = document.activeElement;
2361
2362            if ( element.parent().is( ".ui-effects-wrapper" ) ) {
2363                element.parent().replaceWith( element );
2364
2365                // Fixes #7595 - Elements lose focus when wrapped.
2366                if ( element[ 0 ] === active || $.contains( element[ 0 ], active ) ) {
2367                    $( active ).trigger( "focus" );
2368                }
2369            }
2370
2371            return element;
2372        }
2373    } );
2374}
2375
2376$.extend( $.effects, {
2377    version: "1.14.1",
2378
2379    define: function( name, mode, effect ) {
2380        if ( !effect ) {
2381            effect = mode;
2382            mode = "effect";
2383        }
2384
2385        $.effects.effect[ name ] = effect;
2386        $.effects.effect[ name ].mode = mode;
2387
2388        return effect;
2389    },
2390
2391    scaledDimensions: function( element, percent, direction ) {
2392        if ( percent === 0 ) {
2393            return {
2394                height: 0,
2395                width: 0,
2396                outerHeight: 0,
2397                outerWidth: 0
2398            };
2399        }
2400
2401        var x = direction !== "horizontal" ? ( ( percent || 100 ) / 100 ) : 1,
2402            y = direction !== "vertical" ? ( ( percent || 100 ) / 100 ) : 1;
2403
2404        return {
2405            height: element.height() * y,
2406            width: element.width() * x,
2407            outerHeight: element.outerHeight() * y,
2408            outerWidth: element.outerWidth() * x
2409        };
2410
2411    },
2412
2413    clipToBox: function( animation ) {
2414        return {
2415            width: animation.clip.right - animation.clip.left,
2416            height: animation.clip.bottom - animation.clip.top,
2417            left: animation.clip.left,
2418            top: animation.clip.top
2419        };
2420    },
2421
2422    // Injects recently queued functions to be first in line (after "inprogress")
2423    unshift: function( element, queueLength, count ) {
2424        var queue = element.queue();
2425
2426        if ( queueLength > 1 ) {
2427            queue.splice.apply( queue,
2428                [ 1, 0 ].concat( queue.splice( queueLength, count ) ) );
2429        }
2430        element.dequeue();
2431    },
2432
2433    saveStyle: function( element ) {
2434        element.data( dataSpaceStyle, element[ 0 ].style.cssText );
2435    },
2436
2437    restoreStyle: function( element ) {
2438        element[ 0 ].style.cssText = element.data( dataSpaceStyle ) || "";
2439        element.removeData( dataSpaceStyle );
2440    },
2441
2442    mode: function( element, mode ) {
2443        var hidden = element.is( ":hidden" );
2444
2445        if ( mode === "toggle" ) {
2446            mode = hidden ? "show" : "hide";
2447        }
2448        if ( hidden ? mode === "hide" : mode === "show" ) {
2449            mode = "none";
2450        }
2451        return mode;
2452    },
2453
2454    // Translates a [top,left] array into a baseline value
2455    getBaseline: function( origin, original ) {
2456        var y, x;
2457
2458        switch ( origin[ 0 ] ) {
2459        case "top":
2460            y = 0;
2461            break;
2462        case "middle":
2463            y = 0.5;
2464            break;
2465        case "bottom":
2466            y = 1;
2467            break;
2468        default:
2469            y = origin[ 0 ] / original.height;
2470        }
2471
2472        switch ( origin[ 1 ] ) {
2473        case "left":
2474            x = 0;
2475            break;
2476        case "center":
2477            x = 0.5;
2478            break;
2479        case "right":
2480            x = 1;
2481            break;
2482        default:
2483            x = origin[ 1 ] / original.width;
2484        }
2485
2486        return {
2487            x: x,
2488            y: y
2489        };
2490    },
2491
2492    // Creates a placeholder element so that the original element can be made absolute
2493    createPlaceholder: function( element ) {
2494        var placeholder,
2495            cssPosition = element.css( "position" ),
2496            position = element.position();
2497
2498        // Lock in margins first to account for form elements, which
2499        // will change margin if you explicitly set height
2500        // see: https://jsfiddle.net/JZSMt/3/ https://bugs.webkit.org/show_bug.cgi?id=107380
2501        // Support: Safari
2502        element.css( {
2503            marginTop: element.css( "marginTop" ),
2504            marginBottom: element.css( "marginBottom" ),
2505            marginLeft: element.css( "marginLeft" ),
2506            marginRight: element.css( "marginRight" )
2507        } )
2508        .outerWidth( element.outerWidth() )
2509        .outerHeight( element.outerHeight() );
2510
2511        if ( /^(static|relative)/.test( cssPosition ) ) {
2512            cssPosition = "absolute";
2513
2514            placeholder = $( "<" + element[ 0 ].nodeName + ">" ).insertAfter( element ).css( {
2515
2516                // Convert inline to inline block to account for inline elements
2517                // that turn to inline block based on content (like img)
2518                display: /^(inline|ruby)/.test( element.css( "display" ) ) ?
2519                    "inline-block" :
2520                    "block",
2521                visibility: "hidden",
2522
2523                // Margins need to be set to account for margin collapse
2524                marginTop: element.css( "marginTop" ),
2525                marginBottom: element.css( "marginBottom" ),
2526                marginLeft: element.css( "marginLeft" ),
2527                marginRight: element.css( "marginRight" ),
2528                "float": element.css( "float" )
2529            } )
2530            .outerWidth( element.outerWidth() )
2531            .outerHeight( element.outerHeight() )
2532            .addClass( "ui-effects-placeholder" );
2533
2534            element.data( dataSpace + "placeholder", placeholder );
2535        }
2536
2537        element.css( {
2538            position: cssPosition,
2539            left: position.left,
2540            top: position.top
2541        } );
2542
2543        return placeholder;
2544    },
2545
2546    removePlaceholder: function( element ) {
2547        var dataKey = dataSpace + "placeholder",
2548                placeholder = element.data( dataKey );
2549
2550        if ( placeholder ) {
2551            placeholder.remove();
2552            element.removeData( dataKey );
2553        }
2554    },
2555
2556    // Removes a placeholder if it exists and restores
2557    // properties that were modified during placeholder creation
2558    cleanUp: function( element ) {
2559        $.effects.restoreStyle( element );
2560        $.effects.removePlaceholder( element );
2561    },
2562
2563    setTransition: function( element, list, factor, value ) {
2564        value = value || {};
2565        $.each( list, function( i, x ) {
2566            var unit = element.cssUnit( x );
2567            if ( unit[ 0 ] > 0 ) {
2568                value[ x ] = unit[ 0 ] * factor + unit[ 1 ];
2569            }
2570        } );
2571        return value;
2572    }
2573} );
2574
2575// Return an effect options object for the given parameters:
2576function _normalizeArguments( effect, options, speed, callback ) {
2577
2578    // Allow passing all options as the first parameter
2579    if ( $.isPlainObject( effect ) ) {
2580        options = effect;
2581        effect = effect.effect;
2582    }
2583
2584    // Convert to an object
2585    effect = { effect: effect };
2586
2587    // Catch (effect, null, ...)
2588    if ( options == null ) {
2589        options = {};
2590    }
2591
2592    // Catch (effect, callback)
2593    if ( typeof options === "function" ) {
2594        callback = options;
2595        speed = null;
2596        options = {};
2597    }
2598
2599    // Catch (effect, speed, ?)
2600    if ( typeof options === "number" || $.fx.speeds[ options ] ) {
2601        callback = speed;
2602        speed = options;
2603        options = {};
2604    }
2605
2606    // Catch (effect, options, callback)
2607    if ( typeof speed === "function" ) {
2608        callback = speed;
2609        speed = null;
2610    }
2611
2612    // Add options to effect
2613    if ( options ) {
2614        $.extend( effect, options );
2615    }
2616
2617    speed = speed || options.duration;
2618    effect.duration = $.fx.off ? 0 :
2619        typeof speed === "number" ? speed :
2620        speed in $.fx.speeds ? $.fx.speeds[ speed ] :
2621        $.fx.speeds._default;
2622
2623    effect.complete = callback || options.complete;
2624
2625    return effect;
2626}
2627
2628function standardAnimationOption( option ) {
2629
2630    // Valid standard speeds (nothing, number, named speed)
2631    if ( !option || typeof option === "number" || $.fx.speeds[ option ] ) {
2632        return true;
2633    }
2634
2635    // Invalid strings - treat as "normal" speed
2636    if ( typeof option === "string" && !$.effects.effect[ option ] ) {
2637        return true;
2638    }
2639
2640    // Complete callback
2641    if ( typeof option === "function" ) {
2642        return true;
2643    }
2644
2645    // Options hash (but not naming an effect)
2646    if ( typeof option === "object" && !option.effect ) {
2647        return true;
2648    }
2649
2650    // Didn't match any standard API
2651    return false;
2652}
2653
2654$.fn.extend( {
2655    effect: function( /* effect, options, speed, callback */ ) {
2656        var args = _normalizeArguments.apply( this, arguments ),
2657            effectMethod = $.effects.effect[ args.effect ],
2658            defaultMode = effectMethod.mode,
2659            queue = args.queue,
2660            queueName = queue || "fx",
2661            complete = args.complete,
2662            mode = args.mode,
2663            modes = [],
2664            prefilter = function( next ) {
2665                var el = $( this ),
2666                    normalizedMode = $.effects.mode( el, mode ) || defaultMode;
2667
2668                // Sentinel for duck-punching the :animated pseudo-selector
2669                el.data( dataSpaceAnimated, true );
2670
2671                // Save effect mode for later use,
2672                // we can't just call $.effects.mode again later,
2673                // as the .show() below destroys the initial state
2674                modes.push( normalizedMode );
2675
2676                // See $.uiBackCompat inside of run() for removal of defaultMode in 1.14
2677                if ( defaultMode && ( normalizedMode === "show" ||
2678                        ( normalizedMode === defaultMode && normalizedMode === "hide" ) ) ) {
2679                    el.show();
2680                }
2681
2682                if ( !defaultMode || normalizedMode !== "none" ) {
2683                    $.effects.saveStyle( el );
2684                }
2685
2686                if ( typeof next === "function" ) {
2687                    next();
2688                }
2689            };
2690
2691        if ( $.fx.off || !effectMethod ) {
2692
2693            // Delegate to the original method (e.g., .show()) if possible
2694            if ( mode ) {
2695                return this[ mode ]( args.duration, complete );
2696            } else {
2697                return this.each( function() {
2698                    if ( complete ) {
2699                        complete.call( this );
2700                    }
2701                } );
2702            }
2703        }
2704
2705        function run( next ) {
2706            var elem = $( this );
2707
2708            function cleanup() {
2709                elem.removeData( dataSpaceAnimated );
2710
2711                $.effects.cleanUp( elem );
2712
2713                if ( args.mode === "hide" ) {
2714                    elem.hide();
2715                }
2716
2717                done();
2718            }
2719
2720            function done() {
2721                if ( typeof complete === "function" ) {
2722                    complete.call( elem[ 0 ] );
2723                }
2724
2725                if ( typeof next === "function" ) {
2726                    next();
2727                }
2728            }
2729
2730            // Override mode option on a per element basis,
2731            // as toggle can be either show or hide depending on element state
2732            args.mode = modes.shift();
2733
2734            if ( $.uiBackCompat === true && !defaultMode ) {
2735                if ( elem.is( ":hidden" ) ? mode === "hide" : mode === "show" ) {
2736
2737                    // Call the core method to track "olddisplay" properly
2738                    elem[ mode ]();
2739                    done();
2740                } else {
2741                    effectMethod.call( elem[ 0 ], args, done );
2742                }
2743            } else {
2744                if ( args.mode === "none" ) {
2745
2746                    // Call the core method to track "olddisplay" properly
2747                    elem[ mode ]();
2748                    done();
2749                } else {
2750                    effectMethod.call( elem[ 0 ], args, cleanup );
2751                }
2752            }
2753        }
2754
2755        // Run prefilter on all elements first to ensure that
2756        // any showing or hiding happens before placeholder creation,
2757        // which ensures that any layout changes are correctly captured.
2758        return queue === false ?
2759            this.each( prefilter ).each( run ) :
2760            this.queue( queueName, prefilter ).queue( queueName, run );
2761    },
2762
2763    show: ( function( orig ) {
2764        return function( option ) {
2765            if ( standardAnimationOption( option ) ) {
2766                return orig.apply( this, arguments );
2767            } else {
2768                var args = _normalizeArguments.apply( this, arguments );
2769                args.mode = "show";
2770                return this.effect.call( this, args );
2771            }
2772        };
2773    } )( $.fn.show ),
2774
2775    hide: ( function( orig ) {
2776        return function( option ) {
2777            if ( standardAnimationOption( option ) ) {
2778                return orig.apply( this, arguments );
2779            } else {
2780                var args = _normalizeArguments.apply( this, arguments );
2781                args.mode = "hide";
2782                return this.effect.call( this, args );
2783            }
2784        };
2785    } )( $.fn.hide ),
2786
2787    toggle: ( function( orig ) {
2788        return function( option ) {
2789            if ( standardAnimationOption( option ) || typeof option === "boolean" ) {
2790                return orig.apply( this, arguments );
2791            } else {
2792                var args = _normalizeArguments.apply( this, arguments );
2793                args.mode = "toggle";
2794                return this.effect.call( this, args );
2795            }
2796        };
2797    } )( $.fn.toggle ),
2798
2799    cssUnit: function( key ) {
2800        var style = this.css( key ),
2801            val = [];
2802
2803        $.each( [ "em", "px", "%", "pt" ], function( i, unit ) {
2804            if ( style.indexOf( unit ) > 0 ) {
2805                val = [ parseFloat( style ), unit ];
2806            }
2807        } );
2808        return val;
2809    },
2810
2811    cssClip: function( clipObj ) {
2812        if ( clipObj ) {
2813            return this.css( "clip", "rect(" + clipObj.top + "px " + clipObj.right + "px " +
2814                clipObj.bottom + "px " + clipObj.left + "px)" );
2815        }
2816        return parseClip( this.css( "clip" ), this );
2817    },
2818
2819    transfer: function( options, done ) {
2820        var element = $( this ),
2821            target = $( options.to ),
2822            targetFixed = target.css( "position" ) === "fixed",
2823            body = $( "body" ),
2824            fixTop = targetFixed ? body.scrollTop() : 0,
2825            fixLeft = targetFixed ? body.scrollLeft() : 0,
2826            endPosition = target.offset(),
2827            animation = {
2828                top: endPosition.top - fixTop,
2829                left: endPosition.left - fixLeft,
2830                height: target.innerHeight(),
2831                width: target.innerWidth()
2832            },
2833            startPosition = element.offset(),
2834            transfer = $( "<div class='ui-effects-transfer'></div>" );
2835
2836        transfer
2837            .appendTo( "body" )
2838            .addClass( options.className )
2839            .css( {
2840                top: startPosition.top - fixTop,
2841                left: startPosition.left - fixLeft,
2842                height: element.innerHeight(),
2843                width: element.innerWidth(),
2844                position: targetFixed ? "fixed" : "absolute"
2845            } )
2846            .animate( animation, options.duration, options.easing, function() {
2847                transfer.remove();
2848                if ( typeof done === "function" ) {
2849                    done();
2850                }
2851            } );
2852    }
2853} );
2854
2855function parseClip( str, element ) {
2856        var outerWidth = element.outerWidth(),
2857            outerHeight = element.outerHeight(),
2858            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)\)$/,
2859            values = clipRegex.exec( str ) || [ "", 0, outerWidth, outerHeight, 0 ];
2860
2861        return {
2862            top: parseFloat( values[ 1 ] ) || 0,
2863            right: values[ 2 ] === "auto" ? outerWidth : parseFloat( values[ 2 ] ),
2864            bottom: values[ 3 ] === "auto" ? outerHeight : parseFloat( values[ 3 ] ),
2865            left: parseFloat( values[ 4 ] ) || 0
2866        };
2867}
2868
2869$.fx.step.clip = function( fx ) {
2870    if ( !fx.clipInit ) {
2871        fx.start = $( fx.elem ).cssClip();
2872        if ( typeof fx.end === "string" ) {
2873            fx.end = parseClip( fx.end, fx.elem );
2874        }
2875        fx.clipInit = true;
2876    }
2877
2878    $( fx.elem ).cssClip( {
2879        top: fx.pos * ( fx.end.top - fx.start.top ) + fx.start.top,
2880        right: fx.pos * ( fx.end.right - fx.start.right ) + fx.start.right,
2881        bottom: fx.pos * ( fx.end.bottom - fx.start.bottom ) + fx.start.bottom,
2882        left: fx.pos * ( fx.end.left - fx.start.left ) + fx.start.left
2883    } );
2884};
2885
2886} )();
2887
2888/******************************************************************************/
2889/*********************************** EASING ***********************************/
2890/******************************************************************************/
2891
2892( function() {
2893
2894// Based on easing equations from Robert Penner (http://robertpenner.com/easing)
2895
2896var baseEasings = {};
2897
2898$.each( [ "Quad", "Cubic", "Quart", "Quint", "Expo" ], function( i, name ) {
2899    baseEasings[ name ] = function( p ) {
2900        return Math.pow( p, i + 2 );
2901    };
2902} );
2903
2904$.extend( baseEasings, {
2905    Sine: function( p ) {
2906        return 1 - Math.cos( p * Math.PI / 2 );
2907    },
2908    Circ: function( p ) {
2909        return 1 - Math.sqrt( 1 - p * p );
2910    },
2911    Elastic: function( p ) {
2912        return p === 0 || p === 1 ? p :
2913            -Math.pow( 2, 8 * ( p - 1 ) ) * Math.sin( ( ( p - 1 ) * 80 - 7.5 ) * Math.PI / 15 );
2914    },
2915    Back: function( p ) {
2916        return p * p * ( 3 * p - 2 );
2917    },
2918    Bounce: function( p ) {
2919        var pow2,
2920            bounce = 4;
2921
2922        while ( p < ( ( pow2 = Math.pow( 2, --bounce ) ) - 1 ) / 11 ) {}
2923        return 1 / Math.pow( 4, 3 - bounce ) - 7.5625 * Math.pow( ( pow2 * 3 - 2 ) / 22 - p, 2 );
2924    }
2925} );
2926
2927$.each( baseEasings, function( name, easeIn ) {
2928    $.easing[ "easeIn" + name ] = easeIn;
2929    $.easing[ "easeOut" + name ] = function( p ) {
2930        return 1 - easeIn( 1 - p );
2931    };
2932    $.easing[ "easeInOut" + name ] = function( p ) {
2933        return p < 0.5 ?
2934            easeIn( p * 2 ) / 2 :
2935            1 - easeIn( p * -2 + 2 ) / 2;
2936    };
2937} );
2938
2939} )();
2940
2941var effect = $.effects;
2942
2943
2944/*!
2945 * jQuery UI Effects Blind 1.14.1
2946 * https://jqueryui.com
2947 *
2948 * Copyright OpenJS Foundation and other contributors
2949 * Released under the MIT license.
2950 * https://jquery.org/license
2951 */
2952
2953//>>label: Blind Effect
2954//>>group: Effects
2955//>>description: Blinds the element.
2956//>>docs: https://api.jqueryui.com/blind-effect/
2957//>>demos: https://jqueryui.com/effect/
2958
2959
2960var effectsEffectBlind = $.effects.define( "blind", "hide", function( options, done ) {
2961    var map = {
2962            up: [ "bottom", "top" ],
2963            vertical: [ "bottom", "top" ],
2964            down: [ "top", "bottom" ],
2965            left: [ "right", "left" ],
2966            horizontal: [ "right", "left" ],
2967            right: [ "left", "right" ]
2968        },
2969        element = $( this ),
2970        direction = options.direction || "up",
2971        start = element.cssClip(),
2972        animate = { clip: $.extend( {}, start ) },
2973        placeholder = $.effects.createPlaceholder( element );
2974
2975    animate.clip[ map[ direction ][ 0 ] ] = animate.clip[ map[ direction ][ 1 ] ];
2976
2977    if ( options.mode === "show" ) {
2978        element.cssClip( animate.clip );
2979        if ( placeholder ) {
2980            placeholder.css( $.effects.clipToBox( animate ) );
2981        }
2982
2983        animate.clip = start;
2984    }
2985
2986    if ( placeholder ) {
2987        placeholder.animate( $.effects.clipToBox( animate ), options.duration, options.easing );
2988    }
2989
2990    element.animate( animate, {
2991        queue: false,
2992        duration: options.duration,
2993        easing: options.easing,
2994        complete: done
2995    } );
2996} );
2997
2998
2999/*!
3000 * jQuery UI Effects Bounce 1.14.1
3001 * https://jqueryui.com
3002 *
3003 * Copyright OpenJS Foundation and other contributors
3004 * Released under the MIT license.
3005 * https://jquery.org/license
3006 */
3007
3008//>>label: Bounce Effect
3009//>>group: Effects
3010//>>description: Bounces an element horizontally or vertically n times.
3011//>>docs: https://api.jqueryui.com/bounce-effect/
3012//>>demos: https://jqueryui.com/effect/
3013
3014
3015var effectsEffectBounce = $.effects.define( "bounce", function( options, done ) {
3016    var upAnim, downAnim, refValue,
3017        element = $( this ),
3018
3019        // Defaults:
3020        mode = options.mode,
3021        hide = mode === "hide",
3022        show = mode === "show",
3023        direction = options.direction || "up",
3024        distance = options.distance,
3025        times = options.times || 5,
3026
3027        // Number of internal animations
3028        anims = times * 2 + ( show || hide ? 1 : 0 ),
3029        speed = options.duration / anims,
3030        easing = options.easing,
3031
3032        // Utility:
3033        ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3034        motion = ( direction === "up" || direction === "left" ),
3035        i = 0,
3036
3037        queuelen = element.queue().length;
3038
3039    $.effects.createPlaceholder( element );
3040
3041    refValue = element.css( ref );
3042
3043    // Default distance for the BIGGEST bounce is the outer Distance / 3
3044    if ( !distance ) {
3045        distance = element[ ref === "top" ? "outerHeight" : "outerWidth" ]() / 3;
3046    }
3047
3048    if ( show ) {
3049        downAnim = { opacity: 1 };
3050        downAnim[ ref ] = refValue;
3051
3052        // If we are showing, force opacity 0 and set the initial position
3053        // then do the "first" animation
3054        element
3055            .css( "opacity", 0 )
3056            .css( ref, motion ? -distance * 2 : distance * 2 )
3057            .animate( downAnim, speed, easing );
3058    }
3059
3060    // Start at the smallest distance if we are hiding
3061    if ( hide ) {
3062        distance = distance / Math.pow( 2, times - 1 );
3063    }
3064
3065    downAnim = {};
3066    downAnim[ ref ] = refValue;
3067
3068    // Bounces up/down/left/right then back to 0 -- times * 2 animations happen here
3069    for ( ; i < times; i++ ) {
3070        upAnim = {};
3071        upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3072
3073        element
3074            .animate( upAnim, speed, easing )
3075            .animate( downAnim, speed, easing );
3076
3077        distance = hide ? distance * 2 : distance / 2;
3078    }
3079
3080    // Last Bounce when Hiding
3081    if ( hide ) {
3082        upAnim = { opacity: 0 };
3083        upAnim[ ref ] = ( motion ? "-=" : "+=" ) + distance;
3084
3085        element.animate( upAnim, speed, easing );
3086    }
3087
3088    element.queue( done );
3089
3090    $.effects.unshift( element, queuelen, anims + 1 );
3091} );
3092
3093
3094/*!
3095 * jQuery UI Effects Clip 1.14.1
3096 * https://jqueryui.com
3097 *
3098 * Copyright OpenJS Foundation and other contributors
3099 * Released under the MIT license.
3100 * https://jquery.org/license
3101 */
3102
3103//>>label: Clip Effect
3104//>>group: Effects
3105//>>description: Clips the element on and off like an old TV.
3106//>>docs: https://api.jqueryui.com/clip-effect/
3107//>>demos: https://jqueryui.com/effect/
3108
3109
3110var effectsEffectClip = $.effects.define( "clip", "hide", function( options, done ) {
3111    var start,
3112        animate = {},
3113        element = $( this ),
3114        direction = options.direction || "vertical",
3115        both = direction === "both",
3116        horizontal = both || direction === "horizontal",
3117        vertical = both || direction === "vertical";
3118
3119    start = element.cssClip();
3120    animate.clip = {
3121        top: vertical ? ( start.bottom - start.top ) / 2 : start.top,
3122        right: horizontal ? ( start.right - start.left ) / 2 : start.right,
3123        bottom: vertical ? ( start.bottom - start.top ) / 2 : start.bottom,
3124        left: horizontal ? ( start.right - start.left ) / 2 : start.left
3125    };
3126
3127    $.effects.createPlaceholder( element );
3128
3129    if ( options.mode === "show" ) {
3130        element.cssClip( animate.clip );
3131        animate.clip = start;
3132    }
3133
3134    element.animate( animate, {
3135        queue: false,
3136        duration: options.duration,
3137        easing: options.easing,
3138        complete: done
3139    } );
3140
3141} );
3142
3143
3144/*!
3145 * jQuery UI Effects Drop 1.14.1
3146 * https://jqueryui.com
3147 *
3148 * Copyright OpenJS Foundation and other contributors
3149 * Released under the MIT license.
3150 * https://jquery.org/license
3151 */
3152
3153//>>label: Drop Effect
3154//>>group: Effects
3155//>>description: Moves an element in one direction and hides it at the same time.
3156//>>docs: https://api.jqueryui.com/drop-effect/
3157//>>demos: https://jqueryui.com/effect/
3158
3159
3160var effectsEffectDrop = $.effects.define( "drop", "hide", function( options, done ) {
3161
3162    var distance,
3163        element = $( this ),
3164        mode = options.mode,
3165        show = mode === "show",
3166        direction = options.direction || "left",
3167        ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3168        motion = ( direction === "up" || direction === "left" ) ? "-=" : "+=",
3169        oppositeMotion = ( motion === "+=" ) ? "-=" : "+=",
3170        animation = {
3171            opacity: 0
3172        };
3173
3174    $.effects.createPlaceholder( element );
3175
3176    distance = options.distance ||
3177        element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ) / 2;
3178
3179    animation[ ref ] = motion + distance;
3180
3181    if ( show ) {
3182        element.css( animation );
3183
3184        animation[ ref ] = oppositeMotion + distance;
3185        animation.opacity = 1;
3186    }
3187
3188    // Animate
3189    element.animate( animation, {
3190        queue: false,
3191        duration: options.duration,
3192        easing: options.easing,
3193        complete: done
3194    } );
3195} );
3196
3197
3198/*!
3199 * jQuery UI Effects Explode 1.14.1
3200 * https://jqueryui.com
3201 *
3202 * Copyright OpenJS Foundation and other contributors
3203 * Released under the MIT license.
3204 * https://jquery.org/license
3205 */
3206
3207//>>label: Explode Effect
3208//>>group: Effects
3209/* eslint-disable max-len */
3210//>>description: Explodes an element in all directions into n pieces. Implodes an element to its original wholeness.
3211/* eslint-enable max-len */
3212//>>docs: https://api.jqueryui.com/explode-effect/
3213//>>demos: https://jqueryui.com/effect/
3214
3215
3216var effectsEffectExplode = $.effects.define( "explode", "hide", function( options, done ) {
3217
3218    var i, j, left, top, mx, my,
3219        rows = options.pieces ? Math.round( Math.sqrt( options.pieces ) ) : 3,
3220        cells = rows,
3221        element = $( this ),
3222        mode = options.mode,
3223        show = mode === "show",
3224
3225        // Show and then visibility:hidden the element before calculating offset
3226        offset = element.show().css( "visibility", "hidden" ).offset(),
3227
3228        // Width and height of a piece
3229        width = Math.ceil( element.outerWidth() / cells ),
3230        height = Math.ceil( element.outerHeight() / rows ),
3231        pieces = [];
3232
3233    // Children animate complete:
3234    function childComplete() {
3235        pieces.push( this );
3236        if ( pieces.length === rows * cells ) {
3237            animComplete();
3238        }
3239    }
3240
3241    // Clone the element for each row and cell.
3242    for ( i = 0; i < rows; i++ ) { // ===>
3243        top = offset.top + i * height;
3244        my = i - ( rows - 1 ) / 2;
3245
3246        for ( j = 0; j < cells; j++ ) { // |||
3247            left = offset.left + j * width;
3248            mx = j - ( cells - 1 ) / 2;
3249
3250            // Create a clone of the now hidden main element that will be absolute positioned
3251            // within a wrapper div off the -left and -top equal to size of our pieces
3252            element
3253                .clone()
3254                .appendTo( "body" )
3255                .wrap( "<div></div>" )
3256                .css( {
3257                    position: "absolute",
3258                    visibility: "visible",
3259                    left: -j * width,
3260                    top: -i * height
3261                } )
3262
3263                // Select the wrapper - make it overflow: hidden and absolute positioned based on
3264                // where the original was located +left and +top equal to the size of pieces
3265                .parent()
3266                    .addClass( "ui-effects-explode" )
3267                    .css( {
3268                        position: "absolute",
3269                        overflow: "hidden",
3270                        width: width,
3271                        height: height,
3272                        left: left + ( show ? mx * width : 0 ),
3273                        top: top + ( show ? my * height : 0 ),
3274                        opacity: show ? 0 : 1
3275                    } )
3276                    .animate( {
3277                        left: left + ( show ? 0 : mx * width ),
3278                        top: top + ( show ? 0 : my * height ),
3279                        opacity: show ? 1 : 0
3280                    }, options.duration || 500, options.easing, childComplete );
3281        }
3282    }
3283
3284    function animComplete() {
3285        element.css( {
3286            visibility: "visible"
3287        } );
3288        $( pieces ).remove();
3289        done();
3290    }
3291} );
3292
3293
3294/*!
3295 * jQuery UI Effects Fade 1.14.1
3296 * https://jqueryui.com
3297 *
3298 * Copyright OpenJS Foundation and other contributors
3299 * Released under the MIT license.
3300 * https://jquery.org/license
3301 */
3302
3303//>>label: Fade Effect
3304//>>group: Effects
3305//>>description: Fades the element.
3306//>>docs: https://api.jqueryui.com/fade-effect/
3307//>>demos: https://jqueryui.com/effect/
3308
3309
3310var effectsEffectFade = $.effects.define( "fade", "toggle", function( options, done ) {
3311    var show = options.mode === "show";
3312
3313    $( this )
3314        .css( "opacity", show ? 0 : 1 )
3315        .animate( {
3316            opacity: show ? 1 : 0
3317        }, {
3318            queue: false,
3319            duration: options.duration,
3320            easing: options.easing,
3321            complete: done
3322        } );
3323} );
3324
3325
3326/*!
3327 * jQuery UI Effects Fold 1.14.1
3328 * https://jqueryui.com
3329 *
3330 * Copyright OpenJS Foundation and other contributors
3331 * Released under the MIT license.
3332 * https://jquery.org/license
3333 */
3334
3335//>>label: Fold Effect
3336//>>group: Effects
3337//>>description: Folds an element first horizontally and then vertically.
3338//>>docs: https://api.jqueryui.com/fold-effect/
3339//>>demos: https://jqueryui.com/effect/
3340
3341
3342var effectsEffectFold = $.effects.define( "fold", "hide", function( options, done ) {
3343
3344    // Create element
3345    var element = $( this ),
3346        mode = options.mode,
3347        show = mode === "show",
3348        hide = mode === "hide",
3349        size = options.size || 15,
3350        percent = /([0-9]+)%/.exec( size ),
3351        horizFirst = !!options.horizFirst,
3352        ref = horizFirst ? [ "right", "bottom" ] : [ "bottom", "right" ],
3353        duration = options.duration / 2,
3354
3355        placeholder = $.effects.createPlaceholder( element ),
3356
3357        start = element.cssClip(),
3358        animation1 = { clip: $.extend( {}, start ) },
3359        animation2 = { clip: $.extend( {}, start ) },
3360
3361        distance = [ start[ ref[ 0 ] ], start[ ref[ 1 ] ] ],
3362
3363        queuelen = element.queue().length;
3364
3365    if ( percent ) {
3366        size = parseInt( percent[ 1 ], 10 ) / 100 * distance[ hide ? 0 : 1 ];
3367    }
3368    animation1.clip[ ref[ 0 ] ] = size;
3369    animation2.clip[ ref[ 0 ] ] = size;
3370    animation2.clip[ ref[ 1 ] ] = 0;
3371
3372    if ( show ) {
3373        element.cssClip( animation2.clip );
3374        if ( placeholder ) {
3375            placeholder.css( $.effects.clipToBox( animation2 ) );
3376        }
3377
3378        animation2.clip = start;
3379    }
3380
3381    // Animate
3382    element
3383        .queue( function( next ) {
3384            if ( placeholder ) {
3385                placeholder
3386                    .animate( $.effects.clipToBox( animation1 ), duration, options.easing )
3387                    .animate( $.effects.clipToBox( animation2 ), duration, options.easing );
3388            }
3389
3390            next();
3391        } )
3392        .animate( animation1, duration, options.easing )
3393        .animate( animation2, duration, options.easing )
3394        .queue( done );
3395
3396    $.effects.unshift( element, queuelen, 4 );
3397} );
3398
3399
3400/*!
3401 * jQuery UI Effects Highlight 1.14.1
3402 * https://jqueryui.com
3403 *
3404 * Copyright OpenJS Foundation and other contributors
3405 * Released under the MIT license.
3406 * https://jquery.org/license
3407 */
3408
3409//>>label: Highlight Effect
3410//>>group: Effects
3411//>>description: Highlights the background of an element in a defined color for a custom duration.
3412//>>docs: https://api.jqueryui.com/highlight-effect/
3413//>>demos: https://jqueryui.com/effect/
3414
3415
3416var effectsEffectHighlight = $.effects.define( "highlight", "show", function( options, done ) {
3417    var element = $( this ),
3418        animation = {
3419            backgroundColor: element.css( "backgroundColor" )
3420        };
3421
3422    if ( options.mode === "hide" ) {
3423        animation.opacity = 0;
3424    }
3425
3426    $.effects.saveStyle( element );
3427
3428    element
3429        .css( {
3430            backgroundImage: "none",
3431            backgroundColor: options.color || "#ffff99"
3432        } )
3433        .animate( animation, {
3434            queue: false,
3435            duration: options.duration,
3436            easing: options.easing,
3437            complete: done
3438        } );
3439} );
3440
3441
3442/*!
3443 * jQuery UI Effects Size 1.14.1
3444 * https://jqueryui.com
3445 *
3446 * Copyright OpenJS Foundation and other contributors
3447 * Released under the MIT license.
3448 * https://jquery.org/license
3449 */
3450
3451//>>label: Size Effect
3452//>>group: Effects
3453//>>description: Resize an element to a specified width and height.
3454//>>docs: https://api.jqueryui.com/size-effect/
3455//>>demos: https://jqueryui.com/effect/
3456
3457
3458var effectsEffectSize = $.effects.define( "size", function( options, done ) {
3459
3460    // Create element
3461    var baseline, factor, temp,
3462        element = $( this ),
3463
3464        // Copy for children
3465        cProps = [ "fontSize" ],
3466        vProps = [ "borderTopWidth", "borderBottomWidth", "paddingTop", "paddingBottom" ],
3467        hProps = [ "borderLeftWidth", "borderRightWidth", "paddingLeft", "paddingRight" ],
3468
3469        // Set options
3470        mode = options.mode,
3471        restore = mode !== "effect",
3472        scale = options.scale || "both",
3473        origin = options.origin || [ "middle", "center" ],
3474        position = element.css( "position" ),
3475        pos = element.position(),
3476        original = $.effects.scaledDimensions( element ),
3477        from = options.from || original,
3478        to = options.to || $.effects.scaledDimensions( element, 0 );
3479
3480    $.effects.createPlaceholder( element );
3481
3482    if ( mode === "show" ) {
3483        temp = from;
3484        from = to;
3485        to = temp;
3486    }
3487
3488    // Set scaling factor
3489    factor = {
3490        from: {
3491            y: from.height / original.height,
3492            x: from.width / original.width
3493        },
3494        to: {
3495            y: to.height / original.height,
3496            x: to.width / original.width
3497        }
3498    };
3499
3500    // Scale the css box
3501    if ( scale === "box" || scale === "both" ) {
3502
3503        // Vertical props scaling
3504        if ( factor.from.y !== factor.to.y ) {
3505            from = $.effects.setTransition( element, vProps, factor.from.y, from );
3506            to = $.effects.setTransition( element, vProps, factor.to.y, to );
3507        }
3508
3509        // Horizontal props scaling
3510        if ( factor.from.x !== factor.to.x ) {
3511            from = $.effects.setTransition( element, hProps, factor.from.x, from );
3512            to = $.effects.setTransition( element, hProps, factor.to.x, to );
3513        }
3514    }
3515
3516    // Scale the content
3517    if ( scale === "content" || scale === "both" ) {
3518
3519        // Vertical props scaling
3520        if ( factor.from.y !== factor.to.y ) {
3521            from = $.effects.setTransition( element, cProps, factor.from.y, from );
3522            to = $.effects.setTransition( element, cProps, factor.to.y, to );
3523        }
3524    }
3525
3526    // Adjust the position properties based on the provided origin points
3527    if ( origin ) {
3528        baseline = $.effects.getBaseline( origin, original );
3529        from.top = ( original.outerHeight - from.outerHeight ) * baseline.y + pos.top;
3530        from.left = ( original.outerWidth - from.outerWidth ) * baseline.x + pos.left;
3531        to.top = ( original.outerHeight - to.outerHeight ) * baseline.y + pos.top;
3532        to.left = ( original.outerWidth - to.outerWidth ) * baseline.x + pos.left;
3533    }
3534    delete from.outerHeight;
3535    delete from.outerWidth;
3536    element.css( from );
3537
3538    // Animate the children if desired
3539    if ( scale === "content" || scale === "both" ) {
3540
3541        vProps = vProps.concat( [ "marginTop", "marginBottom" ] ).concat( cProps );
3542        hProps = hProps.concat( [ "marginLeft", "marginRight" ] );
3543
3544        // Only animate children with width attributes specified
3545        // TODO: is this right? should we include anything with css width specified as well
3546        element.find( "*[width]" ).each( function() {
3547            var child = $( this ),
3548                childOriginal = $.effects.scaledDimensions( child ),
3549                childFrom = {
3550                    height: childOriginal.height * factor.from.y,
3551                    width: childOriginal.width * factor.from.x,
3552                    outerHeight: childOriginal.outerHeight * factor.from.y,
3553                    outerWidth: childOriginal.outerWidth * factor.from.x
3554                },
3555                childTo = {
3556                    height: childOriginal.height * factor.to.y,
3557                    width: childOriginal.width * factor.to.x,
3558                    outerHeight: childOriginal.height * factor.to.y,
3559                    outerWidth: childOriginal.width * factor.to.x
3560                };
3561
3562            // Vertical props scaling
3563            if ( factor.from.y !== factor.to.y ) {
3564                childFrom = $.effects.setTransition( child, vProps, factor.from.y, childFrom );
3565                childTo = $.effects.setTransition( child, vProps, factor.to.y, childTo );
3566            }
3567
3568            // Horizontal props scaling
3569            if ( factor.from.x !== factor.to.x ) {
3570                childFrom = $.effects.setTransition( child, hProps, factor.from.x, childFrom );
3571                childTo = $.effects.setTransition( child, hProps, factor.to.x, childTo );
3572            }
3573
3574            if ( restore ) {
3575                $.effects.saveStyle( child );
3576            }
3577
3578            // Animate children
3579            child.css( childFrom );
3580            child.animate( childTo, options.duration, options.easing, function() {
3581
3582                // Restore children
3583                if ( restore ) {
3584                    $.effects.restoreStyle( child );
3585                }
3586            } );
3587        } );
3588    }
3589
3590    // Animate
3591    element.animate( to, {
3592        queue: false,
3593        duration: options.duration,
3594        easing: options.easing,
3595        complete: function() {
3596
3597            var offset = element.offset();
3598
3599            if ( to.opacity === 0 ) {
3600                element.css( "opacity", from.opacity );
3601            }
3602
3603            if ( !restore ) {
3604                element
3605                    .css( "position", position === "static" ? "relative" : position )
3606                    .offset( offset );
3607
3608                // Need to save style here so that automatic style restoration
3609                // doesn't restore to the original styles from before the animation.
3610                $.effects.saveStyle( element );
3611            }
3612
3613            done();
3614        }
3615    } );
3616
3617} );
3618
3619
3620/*!
3621 * jQuery UI Effects Scale 1.14.1
3622 * https://jqueryui.com
3623 *
3624 * Copyright OpenJS Foundation and other contributors
3625 * Released under the MIT license.
3626 * https://jquery.org/license
3627 */
3628
3629//>>label: Scale Effect
3630//>>group: Effects
3631//>>description: Grows or shrinks an element and its content.
3632//>>docs: https://api.jqueryui.com/scale-effect/
3633//>>demos: https://jqueryui.com/effect/
3634
3635
3636var effectsEffectScale = $.effects.define( "scale", function( options, done ) {
3637
3638    // Create element
3639    var el = $( this ),
3640        mode = options.mode,
3641        percent = parseInt( options.percent, 10 ) ||
3642            ( parseInt( options.percent, 10 ) === 0 ? 0 : ( mode !== "effect" ? 0 : 100 ) ),
3643
3644        newOptions = $.extend( true, {
3645            from: $.effects.scaledDimensions( el ),
3646            to: $.effects.scaledDimensions( el, percent, options.direction || "both" ),
3647            origin: options.origin || [ "middle", "center" ]
3648        }, options );
3649
3650    // Fade option to support puff
3651    if ( options.fade ) {
3652        newOptions.from.opacity = 1;
3653        newOptions.to.opacity = 0;
3654    }
3655
3656    $.effects.effect.size.call( this, newOptions, done );
3657} );
3658
3659
3660/*!
3661 * jQuery UI Effects Puff 1.14.1
3662 * https://jqueryui.com
3663 *
3664 * Copyright OpenJS Foundation and other contributors
3665 * Released under the MIT license.
3666 * https://jquery.org/license
3667 */
3668
3669//>>label: Puff Effect
3670//>>group: Effects
3671//>>description: Creates a puff effect by scaling the element up and hiding it at the same time.
3672//>>docs: https://api.jqueryui.com/puff-effect/
3673//>>demos: https://jqueryui.com/effect/
3674
3675
3676var effectsEffectPuff = $.effects.define( "puff", "hide", function( options, done ) {
3677    var newOptions = $.extend( true, {}, options, {
3678        fade: true,
3679        percent: parseInt( options.percent, 10 ) || 150
3680    } );
3681
3682    $.effects.effect.scale.call( this, newOptions, done );
3683} );
3684
3685
3686/*!
3687 * jQuery UI Effects Pulsate 1.14.1
3688 * https://jqueryui.com
3689 *
3690 * Copyright OpenJS Foundation and other contributors
3691 * Released under the MIT license.
3692 * https://jquery.org/license
3693 */
3694
3695//>>label: Pulsate Effect
3696//>>group: Effects
3697//>>description: Pulsates an element n times by changing the opacity to zero and back.
3698//>>docs: https://api.jqueryui.com/pulsate-effect/
3699//>>demos: https://jqueryui.com/effect/
3700
3701
3702var effectsEffectPulsate = $.effects.define( "pulsate", "show", function( options, done ) {
3703    var element = $( this ),
3704        mode = options.mode,
3705        show = mode === "show",
3706        hide = mode === "hide",
3707        showhide = show || hide,
3708
3709        // Showing or hiding leaves off the "last" animation
3710        anims = ( ( options.times || 5 ) * 2 ) + ( showhide ? 1 : 0 ),
3711        duration = options.duration / anims,
3712        animateTo = 0,
3713        i = 1,
3714        queuelen = element.queue().length;
3715
3716    if ( show || !element.is( ":visible" ) ) {
3717        element.css( "opacity", 0 ).show();
3718        animateTo = 1;
3719    }
3720
3721    // Anims - 1 opacity "toggles"
3722    for ( ; i < anims; i++ ) {
3723        element.animate( { opacity: animateTo }, duration, options.easing );
3724        animateTo = 1 - animateTo;
3725    }
3726
3727    element.animate( { opacity: animateTo }, duration, options.easing );
3728
3729    element.queue( done );
3730
3731    $.effects.unshift( element, queuelen, anims + 1 );
3732} );
3733
3734
3735/*!
3736 * jQuery UI Effects Shake 1.14.1
3737 * https://jqueryui.com
3738 *
3739 * Copyright OpenJS Foundation and other contributors
3740 * Released under the MIT license.
3741 * https://jquery.org/license
3742 */
3743
3744//>>label: Shake Effect
3745//>>group: Effects
3746//>>description: Shakes an element horizontally or vertically n times.
3747//>>docs: https://api.jqueryui.com/shake-effect/
3748//>>demos: https://jqueryui.com/effect/
3749
3750
3751var effectsEffectShake = $.effects.define( "shake", function( options, done ) {
3752
3753    var i = 1,
3754        element = $( this ),
3755        direction = options.direction || "left",
3756        distance = options.distance || 20,
3757        times = options.times || 3,
3758        anims = times * 2 + 1,
3759        speed = Math.round( options.duration / anims ),
3760        ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3761        positiveMotion = ( direction === "up" || direction === "left" ),
3762        animation = {},
3763        animation1 = {},
3764        animation2 = {},
3765
3766        queuelen = element.queue().length;
3767
3768    $.effects.createPlaceholder( element );
3769
3770    // Animation
3771    animation[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance;
3772    animation1[ ref ] = ( positiveMotion ? "+=" : "-=" ) + distance * 2;
3773    animation2[ ref ] = ( positiveMotion ? "-=" : "+=" ) + distance * 2;
3774
3775    // Animate
3776    element.animate( animation, speed, options.easing );
3777
3778    // Shakes
3779    for ( ; i < times; i++ ) {
3780        element
3781            .animate( animation1, speed, options.easing )
3782            .animate( animation2, speed, options.easing );
3783    }
3784
3785    element
3786        .animate( animation1, speed, options.easing )
3787        .animate( animation, speed / 2, options.easing )
3788        .queue( done );
3789
3790    $.effects.unshift( element, queuelen, anims + 1 );
3791} );
3792
3793
3794/*!
3795 * jQuery UI Effects Slide 1.14.1
3796 * https://jqueryui.com
3797 *
3798 * Copyright OpenJS Foundation and other contributors
3799 * Released under the MIT license.
3800 * https://jquery.org/license
3801 */
3802
3803//>>label: Slide Effect
3804//>>group: Effects
3805//>>description: Slides an element in and out of the viewport.
3806//>>docs: https://api.jqueryui.com/slide-effect/
3807//>>demos: https://jqueryui.com/effect/
3808
3809
3810var effectsEffectSlide = $.effects.define( "slide", "show", function( options, done ) {
3811    var startClip, startRef,
3812        element = $( this ),
3813        map = {
3814            up: [ "bottom", "top" ],
3815            down: [ "top", "bottom" ],
3816            left: [ "right", "left" ],
3817            right: [ "left", "right" ]
3818        },
3819        mode = options.mode,
3820        direction = options.direction || "left",
3821        ref = ( direction === "up" || direction === "down" ) ? "top" : "left",
3822        positiveMotion = ( direction === "up" || direction === "left" ),
3823        distance = options.distance ||
3824            element[ ref === "top" ? "outerHeight" : "outerWidth" ]( true ),
3825        animation = {};
3826
3827    $.effects.createPlaceholder( element );
3828
3829    startClip = element.cssClip();
3830    startRef = element.position()[ ref ];
3831
3832    // Define hide animation
3833    animation[ ref ] = ( positiveMotion ? -1 : 1 ) * distance + startRef;
3834    animation.clip = element.cssClip();
3835    animation.clip[ map[ direction ][ 1 ] ] = animation.clip[ map[ direction ][ 0 ] ];
3836
3837    // Reverse the animation if we're showing
3838    if ( mode === "show" ) {
3839        element.cssClip( animation.clip );
3840        element.css( ref, animation[ ref ] );
3841        animation.clip = startClip;
3842        animation[ ref ] = startRef;
3843    }
3844
3845    // Actually animate
3846    element.animate( animation, {
3847        queue: false,
3848        duration: options.duration,
3849        easing: options.easing,
3850        complete: done
3851    } );
3852} );
3853
3854
3855/*!
3856 * jQuery UI Effects Transfer 1.14.1
3857 * https://jqueryui.com
3858 *
3859 * Copyright OpenJS Foundation and other contributors
3860 * Released under the MIT license.
3861 * https://jquery.org/license
3862 */
3863
3864//>>label: Transfer Effect
3865//>>group: Effects
3866//>>description: Displays a transfer effect from one element to another.
3867//>>docs: https://api.jqueryui.com/transfer-effect/
3868//>>demos: https://jqueryui.com/effect/
3869
3870
3871var effect;
3872if ( $.uiBackCompat === true ) {
3873    effect = $.effects.define( "transfer", function( options, done ) {
3874        $( this ).transfer( options, done );
3875    } );
3876}
3877var effectsEffectTransfer = effect;
3878
3879
3880/*!
3881 * jQuery UI Focusable 1.14.1
3882 * https://jqueryui.com
3883 *
3884 * Copyright OpenJS Foundation and other contributors
3885 * Released under the MIT license.
3886 * https://jquery.org/license
3887 */
3888
3889//>>label: :focusable Selector
3890//>>group: Core
3891//>>description: Selects elements which can be focused.
3892//>>docs: https://api.jqueryui.com/focusable-selector/
3893
3894
3895// Selectors
3896$.ui.focusable = function( element, hasTabindex ) {
3897    var map, mapName, img, focusableIfVisible, fieldset,
3898        nodeName = element.nodeName.toLowerCase();
3899
3900    if ( "area" === nodeName ) {
3901        map = element.parentNode;
3902        mapName = map.name;
3903        if ( !element.href || !mapName || map.nodeName.toLowerCase() !== "map" ) {
3904            return false;
3905        }
3906        img = $( "img[usemap='#" + mapName + "']" );
3907        return img.length > 0 && img.is( ":visible" );
3908    }
3909
3910    if ( /^(input|select|textarea|button|object)$/.test( nodeName ) ) {
3911        focusableIfVisible = !element.disabled;
3912
3913        if ( focusableIfVisible ) {
3914
3915            // Form controls within a disabled fieldset are disabled.
3916            // However, controls within the fieldset's legend do not get disabled.
3917            // Since controls generally aren't placed inside legends, we skip
3918            // this portion of the check.
3919            fieldset = $( element ).closest( "fieldset" )[ 0 ];
3920            if ( fieldset ) {
3921                focusableIfVisible = !fieldset.disabled;
3922            }
3923        }
3924    } else if ( "a" === nodeName ) {
3925        focusableIfVisible = element.href || hasTabindex;
3926    } else {
3927        focusableIfVisible = hasTabindex;
3928    }
3929
3930    return focusableIfVisible && $( element ).is( ":visible" ) &&
3931        $( element ).css( "visibility" ) === "visible";
3932};
3933
3934$.extend( $.expr.pseudos, {
3935    focusable: function( element ) {
3936        return $.ui.focusable( element, $.attr( element, "tabindex" ) != null );
3937    }
3938} );
3939
3940var focusable = $.ui.focusable;
3941
3942
3943/*!
3944 * jQuery UI Form Reset Mixin 1.14.1
3945 * https://jqueryui.com
3946 *
3947 * Copyright OpenJS Foundation and other contributors
3948 * Released under the MIT license.
3949 * https://jquery.org/license
3950 */
3951
3952//>>label: Form Reset Mixin
3953//>>group: Core
3954//>>description: Refresh input widgets when their form is reset
3955//>>docs: https://api.jqueryui.com/form-reset-mixin/
3956
3957
3958var formResetMixin = $.ui.formResetMixin = {
3959    _formResetHandler: function() {
3960        var form = $( this );
3961
3962        // Wait for the form reset to actually happen before refreshing
3963        setTimeout( function() {
3964            var instances = form.data( "ui-form-reset-instances" );
3965            $.each( instances, function() {
3966                this.refresh();
3967            } );
3968        } );
3969    },
3970
3971    _bindFormResetHandler: function() {
3972        this.form = $( this.element.prop( "form" ) );
3973        if ( !this.form.length ) {
3974            return;
3975        }
3976
3977        var instances = this.form.data( "ui-form-reset-instances" ) || [];
3978        if ( !instances.length ) {
3979
3980            // We don't use _on() here because we use a single event handler per form
3981            this.form.on( "reset.ui-form-reset", this._formResetHandler );
3982        }
3983        instances.push( this );
3984        this.form.data( "ui-form-reset-instances", instances );
3985    },
3986
3987    _unbindFormResetHandler: function() {
3988        if ( !this.form.length ) {
3989            return;
3990        }
3991
3992        var instances = this.form.data( "ui-form-reset-instances" );
3993        instances.splice( $.inArray( this, instances ), 1 );
3994        if ( instances.length ) {
3995            this.form.data( "ui-form-reset-instances", instances );
3996        } else {
3997            this.form
3998                .removeData( "ui-form-reset-instances" )
3999                .off( "reset.ui-form-reset" );
4000        }
4001    }
4002};
4003
4004
4005/*!
4006 * jQuery UI Legacy jQuery Core patches 1.14.1
4007 * https://jqueryui.com
4008 *
4009 * Copyright OpenJS Foundation and other contributors
4010 * Released under the MIT license.
4011 * https://jquery.org/license
4012 *
4013 */
4014
4015//>>label: Legacy jQuery Core patches
4016//>>group: Core
4017//>>description: Backport `.even()`, `.odd()` and `$.escapeSelector` to older jQuery Core versions (deprecated)
4018
4019
4020// Support: jQuery 2.2.x or older.
4021// This method has been defined in jQuery 3.0.0.
4022// Code from https://github.com/jquery/jquery/blob/e539bac79e666bba95bba86d690b4e609dca2286/src/selector/escapeSelector.js
4023if ( !$.escapeSelector ) {
4024    $.escapeSelector = function( id ) {
4025        return CSS.escape( id + "" );
4026    };
4027}
4028
4029// Support: jQuery 3.4.x or older
4030// These methods have been defined in jQuery 3.5.0.
4031if ( !$.fn.even || !$.fn.odd ) {
4032    $.fn.extend( {
4033        even: function() {
4034            return this.filter( function( i ) {
4035                return i % 2 === 0;
4036            } );
4037        },
4038        odd: function() {
4039            return this.filter( function( i ) {
4040                return i % 2 === 1;
4041            } );
4042        }
4043    } );
4044}
4045
4046;
4047/*!
4048 * jQuery UI Keycode 1.14.1
4049 * https://jqueryui.com
4050 *
4051 * Copyright OpenJS Foundation and other contributors
4052 * Released under the MIT license.
4053 * https://jquery.org/license
4054 */
4055
4056//>>label: Keycode
4057//>>group: Core
4058//>>description: Provide keycodes as keynames
4059//>>docs: https://api.jqueryui.com/jQuery.ui.keyCode/
4060
4061
4062var keycode = $.ui.keyCode = {
4063    BACKSPACE: 8,
4064    COMMA: 188,
4065    DELETE: 46,
4066    DOWN: 40,
4067    END: 35,
4068    ENTER: 13,
4069    ESCAPE: 27,
4070    HOME: 36,
4071    LEFT: 37,
4072    PAGE_DOWN: 34,
4073    PAGE_UP: 33,
4074    PERIOD: 190,
4075    RIGHT: 39,
4076    SPACE: 32,
4077    TAB: 9,
4078    UP: 38
4079};
4080
4081
4082/*!
4083 * jQuery UI Labels 1.14.1
4084 * https://jqueryui.com
4085 *
4086 * Copyright OpenJS Foundation and other contributors
4087 * Released under the MIT license.
4088 * https://jquery.org/license
4089 */
4090
4091//>>label: labels
4092//>>group: Core
4093//>>description: Find all the labels associated with a given input
4094//>>docs: https://api.jqueryui.com/labels/
4095
4096
4097var labels = $.fn.labels = function() {
4098    var ancestor, selector, id, labels, ancestors;
4099
4100    if ( !this.length ) {
4101        return this.pushStack( [] );
4102    }
4103
4104    // Check control.labels first
4105    if ( this[ 0 ].labels && this[ 0 ].labels.length ) {
4106        return this.pushStack( this[ 0 ].labels );
4107    }
4108
4109    // If `control.labels` is empty - e.g. inside of document fragments - find
4110    // the labels manually
4111    labels = this.eq( 0 ).parents( "label" );
4112
4113    // Look for the label based on the id
4114    id = this.attr( "id" );
4115    if ( id ) {
4116
4117        // We don't search against the document in case the element
4118        // is disconnected from the DOM
4119        ancestor = this.eq( 0 ).parents().last();
4120
4121        // Get a full set of top level ancestors
4122        ancestors = ancestor.add( ancestor.length ? ancestor.siblings() : this.siblings() );
4123
4124        // Create a selector for the label based on the id
4125        selector = "label[for='" + CSS.escape( id ) + "']";
4126
4127        labels = labels.add( ancestors.find( selector ).addBack( selector ) );
4128
4129    }
4130
4131    // Return whatever we have found for labels
4132    return this.pushStack( labels );
4133};
4134
4135
4136/*!
4137 * jQuery UI Scroll Parent 1.14.1
4138 * https://jqueryui.com
4139 *
4140 * Copyright OpenJS Foundation and other contributors
4141 * Released under the MIT license.
4142 * https://jquery.org/license
4143 */
4144
4145//>>label: scrollParent
4146//>>group: Core
4147//>>description: Get the closest ancestor element that is scrollable.
4148//>>docs: https://api.jqueryui.com/scrollParent/
4149
4150
4151var scrollParent = $.fn.scrollParent = function( includeHidden ) {
4152    var position = this.css( "position" ),
4153        excludeStaticParent = position === "absolute",
4154        overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
4155        scrollParent = this.parents().filter( function() {
4156            var parent = $( this );
4157            if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
4158                return false;
4159            }
4160            return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
4161                parent.css( "overflow-x" ) );
4162        } ).eq( 0 );
4163
4164    return position === "fixed" || !scrollParent.length ?
4165        $( this[ 0 ].ownerDocument || document ) :
4166        scrollParent;
4167};
4168
4169
4170/*!
4171 * jQuery UI Tabbable 1.14.1
4172 * https://jqueryui.com
4173 *
4174 * Copyright OpenJS Foundation and other contributors
4175 * Released under the MIT license.
4176 * https://jquery.org/license
4177 */
4178
4179//>>label: :tabbable Selector
4180//>>group: Core
4181//>>description: Selects elements which can be tabbed to.
4182//>>docs: https://api.jqueryui.com/tabbable-selector/
4183
4184
4185var tabbable = $.extend( $.expr.pseudos, {
4186    tabbable: function( element ) {
4187        var tabIndex = $.attr( element, "tabindex" ),
4188            hasTabindex = tabIndex != null;
4189        return ( !hasTabindex || tabIndex >= 0 ) && $.ui.focusable( element, hasTabindex );
4190    }
4191} );
4192
4193
4194/*!
4195 * jQuery UI Unique ID 1.14.1
4196 * https://jqueryui.com
4197 *
4198 * Copyright OpenJS Foundation and other contributors
4199 * Released under the MIT license.
4200 * https://jquery.org/license
4201 */
4202
4203//>>label: uniqueId
4204//>>group: Core
4205//>>description: Functions to generate and remove uniqueId's
4206//>>docs: https://api.jqueryui.com/uniqueId/
4207
4208
4209var uniqueId = $.fn.extend( {
4210    uniqueId: ( function() {
4211        var uuid = 0;
4212
4213        return function() {
4214            return this.each( function() {
4215                if ( !this.id ) {
4216                    this.id = "ui-id-" + ( ++uuid );
4217                }
4218            } );
4219        };
4220    } )(),
4221
4222    removeUniqueId: function() {
4223        return this.each( function() {
4224            if ( /^ui-id-\d+$/.test( this.id ) ) {
4225                $( this ).removeAttr( "id" );
4226            }
4227        } );
4228    }
4229} );
4230
4231
4232/*!
4233 * jQuery UI Accordion 1.14.1
4234 * https://jqueryui.com
4235 *
4236 * Copyright OpenJS Foundation and other contributors
4237 * Released under the MIT license.
4238 * https://jquery.org/license
4239 */
4240
4241//>>label: Accordion
4242//>>group: Widgets
4243/* eslint-disable max-len */
4244//>>description: Displays collapsible content panels for presenting information in a limited amount of space.
4245/* eslint-enable max-len */
4246//>>docs: https://api.jqueryui.com/accordion/
4247//>>demos: https://jqueryui.com/accordion/
4248//>>css.structure: ../../themes/base/core.css
4249//>>css.structure: ../../themes/base/accordion.css
4250//>>css.theme: ../../themes/base/theme.css
4251
4252
4253var widgetsAccordion = $.widget( "ui.accordion", {
4254    version: "1.14.1",
4255    options: {
4256        active: 0,
4257        animate: {},
4258        classes: {
4259            "ui-accordion-header": "ui-corner-top",
4260            "ui-accordion-header-collapsed": "ui-corner-all",
4261            "ui-accordion-content": "ui-corner-bottom"
4262        },
4263        collapsible: false,
4264        event: "click",
4265        header: function( elem ) {
4266            return elem
4267                .find( "> li > :first-child" )
4268                .add(
4269                    elem.find( "> :not(li)" )
4270
4271                        // Support: jQuery <3.5 only
4272                        // We could use `.even()` but that's unavailable in older jQuery.
4273                        .filter( function( i ) {
4274                            return i % 2 === 0;
4275                        } )
4276                );
4277        },
4278        heightStyle: "auto",
4279        icons: {
4280            activeHeader: "ui-icon-triangle-1-s",
4281            header: "ui-icon-triangle-1-e"
4282        },
4283
4284        // Callbacks
4285        activate: null,
4286        beforeActivate: null
4287    },
4288
4289    hideProps: {
4290        borderTopWidth: "hide",
4291        borderBottomWidth: "hide",
4292        paddingTop: "hide",
4293        paddingBottom: "hide",
4294        height: "hide"
4295    },
4296
4297    showProps: {
4298        borderTopWidth: "show",
4299        borderBottomWidth: "show",
4300        paddingTop: "show",
4301        paddingBottom: "show",
4302        height: "show"
4303    },
4304
4305    _create: function() {
4306        var options = this.options;
4307
4308        this.prevShow = this.prevHide = $();
4309        this._addClass( "ui-accordion", "ui-widget ui-helper-reset" );
4310        this.element.attr( "role", "tablist" );
4311
4312        // Don't allow collapsible: false and active: false / null
4313        if ( !options.collapsible && ( options.active === false || options.active == null ) ) {
4314            options.active = 0;
4315        }
4316
4317        this._processPanels();
4318
4319        // handle negative values
4320        if ( options.active < 0 ) {
4321            options.active += this.headers.length;
4322        }
4323        this._refresh();
4324    },
4325
4326    _getCreateEventData: function() {
4327        return {
4328            header: this.active,
4329            panel: !this.active.length ? $() : this.active.next()
4330        };
4331    },
4332
4333    _createIcons: function() {
4334        var icon, children,
4335            icons = this.options.icons;
4336
4337        if ( icons ) {
4338            icon = $( "<span>" );
4339            this._addClass( icon, "ui-accordion-header-icon", "ui-icon " + icons.header );
4340            icon.prependTo( this.headers );
4341            children = this.active.children( ".ui-accordion-header-icon" );
4342            this._removeClass( children, icons.header )
4343                ._addClass( children, null, icons.activeHeader )
4344                ._addClass( this.headers, "ui-accordion-icons" );
4345        }
4346    },
4347
4348    _destroyIcons: function() {
4349        this._removeClass( this.headers, "ui-accordion-icons" );
4350        this.headers.children( ".ui-accordion-header-icon" ).remove();
4351    },
4352
4353    _destroy: function() {
4354        var contents;
4355
4356        // Clean up main element
4357        this.element.removeAttr( "role" );
4358
4359        // Clean up headers
4360        this.headers
4361            .removeAttr( "role aria-expanded aria-selected aria-controls tabIndex" )
4362            .removeUniqueId();
4363
4364        this._destroyIcons();
4365
4366        // Clean up content panels
4367        contents = this.headers.next()
4368            .css( "display", "" )
4369            .removeAttr( "role aria-hidden aria-labelledby" )
4370            .removeUniqueId();
4371
4372        if ( this.options.heightStyle !== "content" ) {
4373            contents.css( "height", "" );
4374        }
4375    },
4376
4377    _setOption: function( key, value ) {
4378        if ( key === "active" ) {
4379
4380            // _activate() will handle invalid values and update this.options
4381            this._activate( value );
4382            return;
4383        }
4384
4385        if ( key === "event" ) {
4386            if ( this.options.event ) {
4387                this._off( this.headers, this.options.event );
4388            }
4389            this._setupEvents( value );
4390        }
4391
4392        this._super( key, value );
4393
4394        // Setting collapsible: false while collapsed; open first panel
4395        if ( key === "collapsible" && !value && this.options.active === false ) {
4396            this._activate( 0 );
4397        }
4398
4399        if ( key === "icons" ) {
4400            this._destroyIcons();
4401            if ( value ) {
4402                this._createIcons();
4403            }
4404        }
4405    },
4406
4407    _setOptionDisabled: function( value ) {
4408        this._super( value );
4409
4410        this.element.attr( "aria-disabled", value );
4411        this._toggleClass( null, "ui-state-disabled", !!value );
4412    },
4413
4414    _keydown: function( event ) {
4415        if ( event.altKey || event.ctrlKey ) {
4416            return;
4417        }
4418
4419        var keyCode = $.ui.keyCode,
4420            length = this.headers.length,
4421            currentIndex = this.headers.index( event.target ),
4422            toFocus = false;
4423
4424        switch ( event.keyCode ) {
4425        case keyCode.RIGHT:
4426        case keyCode.DOWN:
4427            toFocus = this.headers[ ( currentIndex + 1 ) % length ];
4428            break;
4429        case keyCode.LEFT:
4430        case keyCode.UP:
4431            toFocus = this.headers[ ( currentIndex - 1 + length ) % length ];
4432            break;
4433        case keyCode.SPACE:
4434        case keyCode.ENTER:
4435            this._eventHandler( event );
4436            break;
4437        case keyCode.HOME:
4438            toFocus = this.headers[ 0 ];
4439            break;
4440        case keyCode.END:
4441            toFocus = this.headers[ length - 1 ];
4442            break;
4443        }
4444
4445        if ( toFocus ) {
4446            $( event.target ).attr( "tabIndex", -1 );
4447            $( toFocus ).attr( "tabIndex", 0 );
4448            $( toFocus ).trigger( "focus" );
4449            event.preventDefault();
4450        }
4451    },
4452
4453    _panelKeyDown: function( event ) {
4454        if ( event.keyCode === $.ui.keyCode.UP && event.ctrlKey ) {
4455            $( event.currentTarget ).prev().trigger( "focus" );
4456        }
4457    },
4458
4459    refresh: function() {
4460        var options = this.options;
4461        this._processPanels();
4462
4463        // Was collapsed or no panel
4464        if ( ( options.active === false && options.collapsible === true ) ||
4465                !this.headers.length ) {
4466            options.active = false;
4467            this.active = $();
4468
4469        // active false only when collapsible is true
4470        } else if ( options.active === false ) {
4471            this._activate( 0 );
4472
4473        // was active, but active panel is gone
4474        } else if ( this.active.length && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
4475
4476            // all remaining panel are disabled
4477            if ( this.headers.length === this.headers.find( ".ui-state-disabled" ).length ) {
4478                options.active = false;
4479                this.active = $();
4480
4481            // activate previous panel
4482            } else {
4483                this._activate( Math.max( 0, options.active - 1 ) );
4484            }
4485
4486        // was active, active panel still exists
4487        } else {
4488
4489            // make sure active index is correct
4490            options.active = this.headers.index( this.active );
4491        }
4492
4493        this._destroyIcons();
4494
4495        this._refresh();
4496    },
4497
4498    _processPanels: function() {
4499        var prevHeaders = this.headers,
4500            prevPanels = this.panels;
4501
4502        if ( typeof this.options.header === "function" ) {
4503            this.headers = this.options.header( this.element );
4504        } else {
4505            this.headers = this.element.find( this.options.header );
4506        }
4507        this._addClass( this.headers, "ui-accordion-header ui-accordion-header-collapsed",
4508            "ui-state-default" );
4509
4510        this.panels = this.headers.next().filter( ":not(.ui-accordion-content-active)" ).hide();
4511        this._addClass( this.panels, "ui-accordion-content", "ui-helper-reset ui-widget-content" );
4512
4513        // Avoid memory leaks (#10056)
4514        if ( prevPanels ) {
4515            this._off( prevHeaders.not( this.headers ) );
4516            this._off( prevPanels.not( this.panels ) );
4517        }
4518    },
4519
4520    _refresh: function() {
4521        var maxHeight,
4522            options = this.options,
4523            heightStyle = options.heightStyle,
4524            parent = this.element.parent();
4525
4526        this.active = this._findActive( options.active );
4527        this._addClass( this.active, "ui-accordion-header-active", "ui-state-active" )
4528            ._removeClass( this.active, "ui-accordion-header-collapsed" );
4529        this._addClass( this.active.next(), "ui-accordion-content-active" );
4530        this.active.next().show();
4531
4532        this.headers
4533            .attr( "role", "tab" )
4534            .each( function() {
4535                var header = $( this ),
4536                    headerId = header.uniqueId().attr( "id" ),
4537                    panel = header.next(),
4538                    panelId = panel.uniqueId().attr( "id" );
4539                header.attr( "aria-controls", panelId );
4540                panel.attr( "aria-labelledby", headerId );
4541            } )
4542            .next()
4543                .attr( "role", "tabpanel" );
4544
4545        this.headers
4546            .not( this.active )
4547                .attr( {
4548                    "aria-selected": "false",
4549                    "aria-expanded": "false",
4550                    tabIndex: -1
4551                } )
4552                .next()
4553                    .attr( {
4554                        "aria-hidden": "true"
4555                    } )
4556                    .hide();
4557
4558        // Make sure at least one header is in the tab order
4559        if ( !this.active.length ) {
4560            this.headers.eq( 0 ).attr( "tabIndex", 0 );
4561        } else {
4562            this.active.attr( {
4563                "aria-selected": "true",
4564                "aria-expanded": "true",
4565                tabIndex: 0
4566            } )
4567                .next()
4568                    .attr( {
4569                        "aria-hidden": "false"
4570                    } );
4571        }
4572
4573        this._createIcons();
4574
4575        this._setupEvents( options.event );
4576
4577        if ( heightStyle === "fill" ) {
4578            maxHeight = parent.height();
4579            this.element.siblings( ":visible" ).each( function() {
4580                var elem = $( this ),
4581                    position = elem.css( "position" );
4582
4583                if ( position === "absolute" || position === "fixed" ) {
4584                    return;
4585                }
4586                maxHeight -= elem.outerHeight( true );
4587            } );
4588
4589            this.headers.each( function() {
4590                maxHeight -= $( this ).outerHeight( true );
4591            } );
4592
4593            this.headers.next()
4594                .each( function() {
4595                    $( this ).height( Math.max( 0, maxHeight -
4596                        $( this ).innerHeight() + $( this ).height() ) );
4597                } )
4598                .css( "overflow", "auto" );
4599        } else if ( heightStyle === "auto" ) {
4600            maxHeight = 0;
4601            this.headers.next()
4602                .each( function() {
4603                    var isVisible = $( this ).is( ":visible" );
4604                    if ( !isVisible ) {
4605                        $( this ).show();
4606                    }
4607                    maxHeight = Math.max( maxHeight, $( this ).css( "height", "" ).height() );
4608                    if ( !isVisible ) {
4609                        $( this ).hide();
4610                    }
4611                } )
4612                .height( maxHeight );
4613        }
4614    },
4615
4616    _activate: function( index ) {
4617        var active = this._findActive( index )[ 0 ];
4618
4619        // Trying to activate the already active panel
4620        if ( active === this.active[ 0 ] ) {
4621            return;
4622        }
4623
4624        // Trying to collapse, simulate a click on the currently active header
4625        active = active || this.active[ 0 ];
4626
4627        this._eventHandler( {
4628            target: active,
4629            currentTarget: active,
4630            preventDefault: $.noop
4631        } );
4632    },
4633
4634    _findActive: function( selector ) {
4635        return typeof selector === "number" ? this.headers.eq( selector ) : $();
4636    },
4637
4638    _setupEvents: function( event ) {
4639        var events = {
4640            keydown: "_keydown"
4641        };
4642        if ( event ) {
4643            $.each( event.split( " " ), function( index, eventName ) {
4644                events[ eventName ] = "_eventHandler";
4645            } );
4646        }
4647
4648        this._off( this.headers.add( this.headers.next() ) );
4649        this._on( this.headers, events );
4650        this._on( this.headers.next(), { keydown: "_panelKeyDown" } );
4651        this._hoverable( this.headers );
4652        this._focusable( this.headers );
4653    },
4654
4655    _eventHandler: function( event ) {
4656        var activeChildren, clickedChildren,
4657            options = this.options,
4658            active = this.active,
4659            clicked = $( event.currentTarget ),
4660            clickedIsActive = clicked[ 0 ] === active[ 0 ],
4661            collapsing = clickedIsActive && options.collapsible,
4662            toShow = collapsing ? $() : clicked.next(),
4663            toHide = active.next(),
4664            eventData = {
4665                oldHeader: active,
4666                oldPanel: toHide,
4667                newHeader: collapsing ? $() : clicked,
4668                newPanel: toShow
4669            };
4670
4671        event.preventDefault();
4672
4673        if (
4674
4675                // click on active header, but not collapsible
4676                ( clickedIsActive && !options.collapsible ) ||
4677
4678                // allow canceling activation
4679                ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
4680            return;
4681        }
4682
4683        options.active = collapsing ? false : this.headers.index( clicked );
4684
4685        // When the call to ._toggle() comes after the class changes
4686        // it causes a very odd bug in IE 8 (see #6720)
4687        this.active = clickedIsActive ? $() : clicked;
4688        this._toggle( eventData );
4689
4690        // Switch classes
4691        // corner classes on the previously active header stay after the animation
4692        this._removeClass( active, "ui-accordion-header-active", "ui-state-active" );
4693        if ( options.icons ) {
4694            activeChildren = active.children( ".ui-accordion-header-icon" );
4695            this._removeClass( activeChildren, null, options.icons.activeHeader )
4696                ._addClass( activeChildren, null, options.icons.header );
4697        }
4698
4699        if ( !clickedIsActive ) {
4700            this._removeClass( clicked, "ui-accordion-header-collapsed" )
4701                ._addClass( clicked, "ui-accordion-header-active", "ui-state-active" );
4702            if ( options.icons ) {
4703                clickedChildren = clicked.children( ".ui-accordion-header-icon" );
4704                this._removeClass( clickedChildren, null, options.icons.header )
4705                    ._addClass( clickedChildren, null, options.icons.activeHeader );
4706            }
4707
4708            this._addClass( clicked.next(), "ui-accordion-content-active" );
4709        }
4710    },
4711
4712    _toggle: function( data ) {
4713        var toShow = data.newPanel,
4714            toHide = this.prevShow.length ? this.prevShow : data.oldPanel;
4715
4716        // Handle activating a panel during the animation for another activation
4717        this.prevShow.add( this.prevHide ).stop( true, true );
4718        this.prevShow = toShow;
4719        this.prevHide = toHide;
4720
4721        if ( this.options.animate ) {
4722            this._animate( toShow, toHide, data );
4723        } else {
4724            toHide.hide();
4725            toShow.show();
4726            this._toggleComplete( data );
4727        }
4728
4729        toHide.attr( {
4730            "aria-hidden": "true"
4731        } );
4732        toHide.prev().attr( {
4733            "aria-selected": "false",
4734            "aria-expanded": "false"
4735        } );
4736
4737        // if we're switching panels, remove the old header from the tab order
4738        // if we're opening from collapsed state, remove the previous header from the tab order
4739        // if we're collapsing, then keep the collapsing header in the tab order
4740        if ( toShow.length && toHide.length ) {
4741            toHide.prev().attr( {
4742                "tabIndex": -1,
4743                "aria-expanded": "false"
4744            } );
4745        } else if ( toShow.length ) {
4746            this.headers.filter( function() {
4747                return parseInt( $( this ).attr( "tabIndex" ), 10 ) === 0;
4748            } )
4749                .attr( "tabIndex", -1 );
4750        }
4751
4752        toShow
4753            .attr( "aria-hidden", "false" )
4754            .prev()
4755                .attr( {
4756                    "aria-selected": "true",
4757                    "aria-expanded": "true",
4758                    tabIndex: 0
4759                } );
4760    },
4761
4762    _animate: function( toShow, toHide, data ) {
4763        var total, easing, duration,
4764            that = this,
4765            adjust = 0,
4766            boxSizing = toShow.css( "box-sizing" ),
4767            down = toShow.length &&
4768                ( !toHide.length || ( toShow.index() < toHide.index() ) ),
4769            animate = this.options.animate || {},
4770            options = down && animate.down || animate,
4771            complete = function() {
4772                that._toggleComplete( data );
4773            };
4774
4775        if ( typeof options === "number" ) {
4776            duration = options;
4777        }
4778        if ( typeof options === "string" ) {
4779            easing = options;
4780        }
4781
4782        // fall back from options to animation in case of partial down settings
4783        easing = easing || options.easing || animate.easing;
4784        duration = duration || options.duration || animate.duration;
4785
4786        if ( !toHide.length ) {
4787            return toShow.animate( this.showProps, duration, easing, complete );
4788        }
4789        if ( !toShow.length ) {
4790            return toHide.animate( this.hideProps, duration, easing, complete );
4791        }
4792
4793        total = toShow.show().outerHeight();
4794        toHide.animate( this.hideProps, {
4795            duration: duration,
4796            easing: easing,
4797            step: function( now, fx ) {
4798                fx.now = Math.round( now );
4799            }
4800        } );
4801        toShow
4802            .hide()
4803            .animate( this.showProps, {
4804                duration: duration,
4805                easing: easing,
4806                complete: complete,
4807                step: function( now, fx ) {
4808                    fx.now = Math.round( now );
4809                    if ( fx.prop !== "height" ) {
4810                        if ( boxSizing === "content-box" ) {
4811                            adjust += fx.now;
4812                        }
4813                    } else if ( that.options.heightStyle !== "content" ) {
4814                        fx.now = Math.round( total - toHide.outerHeight() - adjust );
4815                        adjust = 0;
4816                    }
4817                }
4818            } );
4819    },
4820
4821    _toggleComplete: function( data ) {
4822        var toHide = data.oldPanel,
4823            prev = toHide.prev();
4824
4825        this._removeClass( toHide, "ui-accordion-content-active" );
4826        this._removeClass( prev, "ui-accordion-header-active" )
4827            ._addClass( prev, "ui-accordion-header-collapsed" );
4828
4829        this._trigger( "activate", null, data );
4830    }
4831} );
4832
4833
4834/*!
4835 * jQuery UI Menu 1.14.1
4836 * https://jqueryui.com
4837 *
4838 * Copyright OpenJS Foundation and other contributors
4839 * Released under the MIT license.
4840 * https://jquery.org/license
4841 */
4842
4843//>>label: Menu
4844//>>group: Widgets
4845//>>description: Creates nestable menus.
4846//>>docs: https://api.jqueryui.com/menu/
4847//>>demos: https://jqueryui.com/menu/
4848//>>css.structure: ../../themes/base/core.css
4849//>>css.structure: ../../themes/base/menu.css
4850//>>css.theme: ../../themes/base/theme.css
4851
4852
4853var widgetsMenu = $.widget( "ui.menu", {
4854    version: "1.14.1",
4855    defaultElement: "<ul>",
4856    delay: 300,
4857    options: {
4858        icons: {
4859            submenu: "ui-icon-caret-1-e"
4860        },
4861        items: "> *",
4862        menus: "ul",
4863        position: {
4864            my: "left top",
4865            at: "right top"
4866        },
4867        role: "menu",
4868
4869        // Callbacks
4870        blur: null,
4871        focus: null,
4872        select: null
4873    },
4874
4875    _create: function() {
4876        this.activeMenu = this.element;
4877
4878        // Flag used to prevent firing of the click handler
4879        // as the event bubbles up through nested menus
4880        this.mouseHandled = false;
4881        this.lastMousePosition = { x: null, y: null };
4882        this.element
4883            .uniqueId()
4884            .attr( {
4885                role: this.options.role,
4886                tabIndex: 0
4887            } );
4888
4889        this._addClass( "ui-menu", "ui-widget ui-widget-content" );
4890        this._on( {
4891
4892            // Prevent focus from sticking to links inside menu after clicking
4893            // them (focus should always stay on UL during navigation).
4894            "mousedown .ui-menu-item": function( event ) {
4895                event.preventDefault();
4896
4897                this._activateItem( event );
4898            },
4899            "click .ui-menu-item": function( event ) {
4900                var target = $( event.target );
4901                var active = $( this.document[ 0 ].activeElement );
4902                if ( !this.mouseHandled && target.not( ".ui-state-disabled" ).length ) {
4903                    this.select( event );
4904
4905                    // Only set the mouseHandled flag if the event will bubble, see #9469.
4906                    if ( !event.isPropagationStopped() ) {
4907                        this.mouseHandled = true;
4908                    }
4909
4910                    // Open submenu on click
4911                    if ( target.has( ".ui-menu" ).length ) {
4912                        this.expand( event );
4913                    } else if ( !this.element.is( ":focus" ) &&
4914                            active.closest( ".ui-menu" ).length ) {
4915
4916                        // Redirect focus to the menu
4917                        this.element.trigger( "focus", [ true ] );
4918
4919                        // If the active item is on the top level, let it stay active.
4920                        // Otherwise, blur the active item since it is no longer visible.
4921                        if ( this.active && this.active.parents( ".ui-menu" ).length === 1 ) {
4922                            clearTimeout( this.timer );
4923                        }
4924                    }
4925                }
4926            },
4927            "mouseenter .ui-menu-item": "_activateItem",
4928            "mousemove .ui-menu-item": "_activateItem",
4929            mouseleave: "collapseAll",
4930            "mouseleave .ui-menu": "collapseAll",
4931            focus: function( event, keepActiveItem ) {
4932
4933                // If there's already an active item, keep it active
4934                // If not, activate the first item
4935                var item = this.active || this._menuItems().first();
4936
4937                if ( !keepActiveItem ) {
4938                    this.focus( event, item );
4939                }
4940            },
4941            blur: function( event ) {
4942                this._delay( function() {
4943                    var notContained = !$.contains(
4944                        this.element[ 0 ],
4945                        this.document[ 0 ].activeElement
4946                    );
4947                    if ( notContained ) {
4948                        this.collapseAll( event );
4949                    }
4950                } );
4951            },
4952            keydown: "_keydown"
4953        } );
4954
4955        this.refresh();
4956
4957        // Clicks outside of a menu collapse any open menus
4958        this._on( this.document, {
4959            click: function( event ) {
4960                if ( this._closeOnDocumentClick( event ) ) {
4961                    this.collapseAll( event, true );
4962                }
4963
4964                // Reset the mouseHandled flag
4965                this.mouseHandled = false;
4966            }
4967        } );
4968    },
4969
4970    _activateItem: function( event ) {
4971
4972        // Ignore mouse events while typeahead is active, see #10458.
4973        // Prevents focusing the wrong item when typeahead causes a scroll while the mouse
4974        // is over an item in the menu
4975        if ( this.previousFilter ) {
4976            return;
4977        }
4978
4979        // If the mouse didn't actually move, but the page was scrolled, ignore the event (#9356)
4980        if ( event.clientX === this.lastMousePosition.x &&
4981                event.clientY === this.lastMousePosition.y ) {
4982            return;
4983        }
4984
4985        this.lastMousePosition = {
4986            x: event.clientX,
4987            y: event.clientY
4988        };
4989
4990        var actualTarget = $( event.target ).closest( ".ui-menu-item" ),
4991            target = $( event.currentTarget );
4992
4993        // Ignore bubbled events on parent items, see #11641
4994        if ( actualTarget[ 0 ] !== target[ 0 ] ) {
4995            return;
4996        }
4997
4998        // If the item is already active, there's nothing to do
4999        if ( target.is( ".ui-state-active" ) ) {
5000            return;
5001        }
5002
5003        // Remove ui-state-active class from siblings of the newly focused menu item
5004        // to avoid a jump caused by adjacent elements both having a class with a border
5005        this._removeClass( target.siblings().children( ".ui-state-active" ),
5006            null, "ui-state-active" );
5007        this.focus( event, target );
5008    },
5009
5010    _destroy: function() {
5011        var items = this.element.find( ".ui-menu-item" )
5012                .removeAttr( "role aria-disabled" ),
5013            submenus = items.children( ".ui-menu-item-wrapper" )
5014                .removeUniqueId()
5015                .removeAttr( "tabIndex role aria-haspopup" );
5016
5017        // Destroy (sub)menus
5018        this.element
5019            .removeAttr( "aria-activedescendant" )
5020            .find( ".ui-menu" ).addBack()
5021                .removeAttr( "role aria-labelledby aria-expanded aria-hidden aria-disabled " +
5022                    "tabIndex" )
5023                .removeUniqueId()
5024                .show();
5025
5026        submenus.children().each( function() {
5027            var elem = $( this );
5028            if ( elem.data( "ui-menu-submenu-caret" ) ) {
5029                elem.remove();
5030            }
5031        } );
5032    },
5033
5034    _keydown: function( event ) {
5035        var match, prev, character, skip,
5036            preventDefault = true;
5037
5038        switch ( event.keyCode ) {
5039        case $.ui.keyCode.PAGE_UP:
5040            this.previousPage( event );
5041            break;
5042        case $.ui.keyCode.PAGE_DOWN:
5043            this.nextPage( event );
5044            break;
5045        case $.ui.keyCode.HOME:
5046            this._move( "first", "first", event );
5047            break;
5048        case $.ui.keyCode.END:
5049            this._move( "last", "last", event );
5050            break;
5051        case $.ui.keyCode.UP:
5052            this.previous( event );
5053            break;
5054        case $.ui.keyCode.DOWN:
5055            this.next( event );
5056            break;
5057        case $.ui.keyCode.LEFT:
5058            this.collapse( event );
5059            break;
5060        case $.ui.keyCode.RIGHT:
5061            if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5062                this.expand( event );
5063            }
5064            break;
5065        case $.ui.keyCode.ENTER:
5066        case $.ui.keyCode.SPACE:
5067            this._activate( event );
5068            break;
5069        case $.ui.keyCode.ESCAPE:
5070            this.collapse( event );
5071            break;
5072        default:
5073            preventDefault = false;
5074            prev = this.previousFilter || "";
5075            skip = false;
5076
5077            // Support number pad values
5078            character = event.keyCode >= 96 && event.keyCode <= 105 ?
5079                ( event.keyCode - 96 ).toString() : String.fromCharCode( event.keyCode );
5080
5081            clearTimeout( this.filterTimer );
5082
5083            if ( character === prev ) {
5084                skip = true;
5085            } else {
5086                character = prev + character;
5087            }
5088
5089            match = this._filterMenuItems( character );
5090            match = skip && match.index( this.active.next() ) !== -1 ?
5091                this.active.nextAll( ".ui-menu-item" ) :
5092                match;
5093
5094            // If no matches on the current filter, reset to the last character pressed
5095            // to move down the menu to the first item that starts with that character
5096            if ( !match.length ) {
5097                character = String.fromCharCode( event.keyCode );
5098                match = this._filterMenuItems( character );
5099            }
5100
5101            if ( match.length ) {
5102                this.focus( event, match );
5103                this.previousFilter = character;
5104                this.filterTimer = this._delay( function() {
5105                    delete this.previousFilter;
5106                }, 1000 );
5107            } else {
5108                delete this.previousFilter;
5109            }
5110        }
5111
5112        if ( preventDefault ) {
5113            event.preventDefault();
5114        }
5115    },
5116
5117    _activate: function( event ) {
5118        if ( this.active && !this.active.is( ".ui-state-disabled" ) ) {
5119            if ( this.active.children( "[aria-haspopup='true']" ).length ) {
5120                this.expand( event );
5121            } else {
5122                this.select( event );
5123            }
5124        }
5125    },
5126
5127    refresh: function() {
5128        var menus, items, newSubmenus, newItems, newWrappers,
5129            that = this,
5130            icon = this.options.icons.submenu,
5131            submenus = this.element.find( this.options.menus );
5132
5133        this._toggleClass( "ui-menu-icons", null, !!this.element.find( ".ui-icon" ).length );
5134
5135        // Initialize nested menus
5136        newSubmenus = submenus.filter( ":not(.ui-menu)" )
5137            .hide()
5138            .attr( {
5139                role: this.options.role,
5140                "aria-hidden": "true",
5141                "aria-expanded": "false"
5142            } )
5143            .each( function() {
5144                var menu = $( this ),
5145                    item = menu.prev(),
5146                    submenuCaret = $( "<span>" ).data( "ui-menu-submenu-caret", true );
5147
5148                that._addClass( submenuCaret, "ui-menu-icon", "ui-icon " + icon );
5149                item
5150                    .attr( "aria-haspopup", "true" )
5151                    .prepend( submenuCaret );
5152                menu.attr( "aria-labelledby", item.attr( "id" ) );
5153            } );
5154
5155        this._addClass( newSubmenus, "ui-menu", "ui-widget ui-widget-content ui-front" );
5156
5157        menus = submenus.add( this.element );
5158        items = menus.find( this.options.items );
5159
5160        // Initialize menu-items containing spaces and/or dashes only as dividers
5161        items.not( ".ui-menu-item" ).each( function() {
5162            var item = $( this );
5163            if ( that._isDivider( item ) ) {
5164                that._addClass( item, "ui-menu-divider", "ui-widget-content" );
5165            }
5166        } );
5167
5168        // Don't refresh list items that are already adapted
5169        newItems = items.not( ".ui-menu-item, .ui-menu-divider" );
5170        newWrappers = newItems.children()
5171            .not( ".ui-menu" )
5172                .uniqueId()
5173                .attr( {
5174                    tabIndex: -1,
5175                    role: this._itemRole()
5176                } );
5177        this._addClass( newItems, "ui-menu-item" )
5178            ._addClass( newWrappers, "ui-menu-item-wrapper" );
5179
5180        // Add aria-disabled attribute to any disabled menu item
5181        items.filter( ".ui-state-disabled" ).attr( "aria-disabled", "true" );
5182
5183        // If the active item has been removed, blur the menu
5184        if ( this.active && !$.contains( this.element[ 0 ], this.active[ 0 ] ) ) {
5185            this.blur();
5186        }
5187    },
5188
5189    _itemRole: function() {
5190        return {
5191            menu: "menuitem",
5192            listbox: "option"
5193        }[ this.options.role ];
5194    },
5195
5196    _setOption: function( key, value ) {
5197        if ( key === "icons" ) {
5198            var icons = this.element.find( ".ui-menu-icon" );
5199            this._removeClass( icons, null, this.options.icons.submenu )
5200                ._addClass( icons, null, value.submenu );
5201        }
5202        this._super( key, value );
5203    },
5204
5205    _setOptionDisabled: function( value ) {
5206        this._super( value );
5207
5208        this.element.attr( "aria-disabled", String( value ) );
5209        this._toggleClass( null, "ui-state-disabled", !!value );
5210    },
5211
5212    focus: function( event, item ) {
5213        var nested, focused, activeParent;
5214        this.blur( event, event && event.type === "focus" );
5215
5216        this._scrollIntoView( item );
5217
5218        this.active = item.first();
5219
5220        focused = this.active.children( ".ui-menu-item-wrapper" );
5221        this._addClass( focused, null, "ui-state-active" );
5222
5223        // Only update aria-activedescendant if there's a role
5224        // otherwise we assume focus is managed elsewhere
5225        if ( this.options.role ) {
5226            this.element.attr( "aria-activedescendant", focused.attr( "id" ) );
5227        }
5228
5229        // Highlight active parent menu item, if any
5230        activeParent = this.active
5231            .parent()
5232                .closest( ".ui-menu-item" )
5233                    .children( ".ui-menu-item-wrapper" );
5234        this._addClass( activeParent, null, "ui-state-active" );
5235
5236        if ( event && event.type === "keydown" ) {
5237            this._close();
5238        } else {
5239            this.timer = this._delay( function() {
5240                this._close();
5241            }, this.delay );
5242        }
5243
5244        nested = item.children( ".ui-menu" );
5245        if ( nested.length && event && ( /^mouse/.test( event.type ) ) ) {
5246            this._startOpening( nested );
5247        }
5248        this.activeMenu = item.parent();
5249
5250        this._trigger( "focus", event, { item: item } );
5251    },
5252
5253    _scrollIntoView: function( item ) {
5254        var borderTop, paddingTop, offset, scroll, elementHeight, itemHeight;
5255        if ( this._hasScroll() ) {
5256            borderTop = parseFloat( $.css( this.activeMenu[ 0 ], "borderTopWidth" ) ) || 0;
5257            paddingTop = parseFloat( $.css( this.activeMenu[ 0 ], "paddingTop" ) ) || 0;
5258            offset = item.offset().top - this.activeMenu.offset().top - borderTop - paddingTop;
5259            scroll = this.activeMenu.scrollTop();
5260            elementHeight = this.activeMenu.height();
5261            itemHeight = item.outerHeight();
5262
5263            if ( offset < 0 ) {
5264                this.activeMenu.scrollTop( scroll + offset );
5265            } else if ( offset + itemHeight > elementHeight ) {
5266                this.activeMenu.scrollTop( scroll + offset - elementHeight + itemHeight );
5267            }
5268        }
5269    },
5270
5271    blur: function( event, fromFocus ) {
5272        if ( !fromFocus ) {
5273            clearTimeout( this.timer );
5274        }
5275
5276        if ( !this.active ) {
5277            return;
5278        }
5279
5280        this._removeClass( this.active.children( ".ui-menu-item-wrapper" ),
5281            null, "ui-state-active" );
5282
5283        this._trigger( "blur", event, { item: this.active } );
5284        this.active = null;
5285    },
5286
5287    _startOpening: function( submenu ) {
5288        clearTimeout( this.timer );
5289
5290        // Don't open if already open fixes a Firefox bug that caused a .5 pixel
5291        // shift in the submenu position when mousing over the caret icon
5292        if ( submenu.attr( "aria-hidden" ) !== "true" ) {
5293            return;
5294        }
5295
5296        this.timer = this._delay( function() {
5297            this._close();
5298            this._open( submenu );
5299        }, this.delay );
5300    },
5301
5302    _open: function( submenu ) {
5303        var position = $.extend( {
5304            of: this.active
5305        }, this.options.position );
5306
5307        clearTimeout( this.timer );
5308        this.element.find( ".ui-menu" ).not( submenu.parents( ".ui-menu" ) )
5309            .hide()
5310            .attr( "aria-hidden", "true" );
5311
5312        submenu
5313            .show()
5314            .removeAttr( "aria-hidden" )
5315            .attr( "aria-expanded", "true" )
5316            .position( position );
5317    },
5318
5319    collapseAll: function( event, all ) {
5320        clearTimeout( this.timer );
5321        this.timer = this._delay( function() {
5322
5323            // If we were passed an event, look for the submenu that contains the event
5324            var currentMenu = all ? this.element :
5325                $( event && event.target ).closest( this.element.find( ".ui-menu" ) );
5326
5327            // If we found no valid submenu ancestor, use the main menu to close all
5328            // sub menus anyway
5329            if ( !currentMenu.length ) {
5330                currentMenu = this.element;
5331            }
5332
5333            this._close( currentMenu );
5334
5335            this.blur( event );
5336
5337            // Work around active item staying active after menu is blurred
5338            this._removeClass( currentMenu.find( ".ui-state-active" ), null, "ui-state-active" );
5339
5340            this.activeMenu = currentMenu;
5341        }, all ? 0 : this.delay );
5342    },
5343
5344    // With no arguments, closes the currently active menu - if nothing is active
5345    // it closes all menus.  If passed an argument, it will search for menus BELOW
5346    _close: function( startMenu ) {
5347        if ( !startMenu ) {
5348            startMenu = this.active ? this.active.parent() : this.element;
5349        }
5350
5351        startMenu.find( ".ui-menu" )
5352            .hide()
5353            .attr( "aria-hidden", "true" )
5354            .attr( "aria-expanded", "false" );
5355    },
5356
5357    _closeOnDocumentClick: function( event ) {
5358        return !$( event.target ).closest( ".ui-menu" ).length;
5359    },
5360
5361    _isDivider: function( item ) {
5362
5363        // Match hyphen, em dash, en dash
5364        return !/[^\-\u2014\u2013\s]/.test( item.text() );
5365    },
5366
5367    collapse: function( event ) {
5368        var newItem = this.active &&
5369            this.active.parent().closest( ".ui-menu-item", this.element );
5370        if ( newItem && newItem.length ) {
5371            this._close();
5372            this.focus( event, newItem );
5373        }
5374    },
5375
5376    expand: function( event ) {
5377        var newItem = this.active && this._menuItems( this.active.children( ".ui-menu" ) ).first();
5378
5379        if ( newItem && newItem.length ) {
5380            this._open( newItem.parent() );
5381
5382            // Delay so Firefox will not hide activedescendant change in expanding submenu from AT
5383            this._delay( function() {
5384                this.focus( event, newItem );
5385            } );
5386        }
5387    },
5388
5389    next: function( event ) {
5390        this._move( "next", "first", event );
5391    },
5392
5393    previous: function( event ) {
5394        this._move( "prev", "last", event );
5395    },
5396
5397    isFirstItem: function() {
5398        return this.active && !this.active.prevAll( ".ui-menu-item" ).length;
5399    },
5400
5401    isLastItem: function() {
5402        return this.active && !this.active.nextAll( ".ui-menu-item" ).length;
5403    },
5404
5405    _menuItems: function( menu ) {
5406        return ( menu || this.element )
5407            .find( this.options.items )
5408            .filter( ".ui-menu-item" );
5409    },
5410
5411    _move: function( direction, filter, event ) {
5412        var next;
5413        if ( this.active ) {
5414            if ( direction === "first" || direction === "last" ) {
5415                next = this.active
5416                    [ direction === "first" ? "prevAll" : "nextAll" ]( ".ui-menu-item" )
5417                    .last();
5418            } else {
5419                next = this.active
5420                    [ direction + "All" ]( ".ui-menu-item" )
5421                    .first();
5422            }
5423        }
5424        if ( !next || !next.length || !this.active ) {
5425            next = this._menuItems( this.activeMenu )[ filter ]();
5426        }
5427
5428        this.focus( event, next );
5429    },
5430
5431    nextPage: function( event ) {
5432        var item, base, height;
5433
5434        if ( !this.active ) {
5435            this.next( event );
5436            return;
5437        }
5438        if ( this.isLastItem() ) {
5439            return;
5440        }
5441        if ( this._hasScroll() ) {
5442            base = this.active.offset().top;
5443            height = this.element.innerHeight();
5444
5445            // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5446            if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5447                height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5448            }
5449
5450            this.active.nextAll( ".ui-menu-item" ).each( function() {
5451                item = $( this );
5452                return item.offset().top - base - height < 0;
5453            } );
5454
5455            this.focus( event, item );
5456        } else {
5457            this.focus( event, this._menuItems( this.activeMenu )
5458                [ !this.active ? "first" : "last" ]() );
5459        }
5460    },
5461
5462    previousPage: function( event ) {
5463        var item, base, height;
5464        if ( !this.active ) {
5465            this.next( event );
5466            return;
5467        }
5468        if ( this.isFirstItem() ) {
5469            return;
5470        }
5471        if ( this._hasScroll() ) {
5472            base = this.active.offset().top;
5473            height = this.element.innerHeight();
5474
5475            // jQuery 3.2 doesn't include scrollbars in innerHeight, add it back.
5476            if ( $.fn.jquery.indexOf( "3.2." ) === 0 ) {
5477                height += this.element[ 0 ].offsetHeight - this.element.outerHeight();
5478            }
5479
5480            this.active.prevAll( ".ui-menu-item" ).each( function() {
5481                item = $( this );
5482                return item.offset().top - base + height > 0;
5483            } );
5484
5485            this.focus( event, item );
5486        } else {
5487            this.focus( event, this._menuItems( this.activeMenu ).first() );
5488        }
5489    },
5490
5491    _hasScroll: function() {
5492        return this.element.outerHeight() < this.element.prop( "scrollHeight" );
5493    },
5494
5495    select: function( event ) {
5496
5497        // TODO: It should never be possible to not have an active item at this
5498        // point, but the tests don't trigger mouseenter before click.
5499        this.active = this.active || $( event.target ).closest( ".ui-menu-item" );
5500        var ui = { item: this.active };
5501        if ( !this.active.has( ".ui-menu" ).length ) {
5502            this.collapseAll( event, true );
5503        }
5504        this._trigger( "select", event, ui );
5505    },
5506
5507    _filterMenuItems: function( character ) {
5508        var escapedCharacter = character.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" ),
5509            regex = new RegExp( "^" + escapedCharacter, "i" );
5510
5511        return this.activeMenu
5512            .find( this.options.items )
5513
5514                // Only match on items, not dividers or other content (#10571)
5515                .filter( ".ui-menu-item" )
5516                    .filter( function() {
5517                        return regex.test(
5518                            String.prototype.trim.call(
5519                                $( this ).children( ".ui-menu-item-wrapper" ).text() ) );
5520                    } );
5521    }
5522} );
5523
5524
5525/*!
5526 * jQuery UI Autocomplete 1.14.1
5527 * https://jqueryui.com
5528 *
5529 * Copyright OpenJS Foundation and other contributors
5530 * Released under the MIT license.
5531 * https://jquery.org/license
5532 */
5533
5534//>>label: Autocomplete
5535//>>group: Widgets
5536//>>description: Lists suggested words as the user is typing.
5537//>>docs: https://api.jqueryui.com/autocomplete/
5538//>>demos: https://jqueryui.com/autocomplete/
5539//>>css.structure: ../../themes/base/core.css
5540//>>css.structure: ../../themes/base/autocomplete.css
5541//>>css.theme: ../../themes/base/theme.css
5542
5543
5544$.widget( "ui.autocomplete", {
5545    version: "1.14.1",
5546    defaultElement: "<input>",
5547    options: {
5548        appendTo: null,
5549        autoFocus: false,
5550        delay: 300,
5551        minLength: 1,
5552        position: {
5553            my: "left top",
5554            at: "left bottom",
5555            collision: "none"
5556        },
5557        source: null,
5558
5559        // Callbacks
5560        change: null,
5561        close: null,
5562        focus: null,
5563        open: null,
5564        response: null,
5565        search: null,
5566        select: null
5567    },
5568
5569    requestIndex: 0,
5570    pending: 0,
5571    liveRegionTimer: null,
5572
5573    _create: function() {
5574
5575        // Some browsers only repeat keydown events, not keypress events,
5576        // so we use the suppressKeyPress flag to determine if we've already
5577        // handled the keydown event. #7269
5578        // Unfortunately the code for & in keypress is the same as the up arrow,
5579        // so we use the suppressKeyPressRepeat flag to avoid handling keypress
5580        // events when we know the keydown event was used to modify the
5581        // search term. #7799
5582        var suppressKeyPress, suppressKeyPressRepeat, suppressInput,
5583            nodeName = this.element[ 0 ].nodeName.toLowerCase(),
5584            isTextarea = nodeName === "textarea",
5585            isInput = nodeName === "input";
5586
5587        // Textareas are always multi-line
5588        // Inputs are always single-line, even if inside a contentEditable element
5589        // All other element types are determined by whether they're contentEditable
5590        this.isMultiLine = isTextarea ||
5591            !isInput && this.element.prop( "contentEditable" ) === "true";
5592
5593        this.valueMethod = this.element[ isTextarea || isInput ? "val" : "text" ];
5594        this.isNewMenu = true;
5595
5596        this._addClass( "ui-autocomplete-input" );
5597        this.element.attr( "autocomplete", "off" );
5598
5599        this._on( this.element, {
5600            keydown: function( event ) {
5601                if ( this.element.prop( "readOnly" ) ) {
5602                    suppressKeyPress = true;
5603                    suppressInput = true;
5604                    suppressKeyPressRepeat = true;
5605                    return;
5606                }
5607
5608                suppressKeyPress = false;
5609                suppressInput = false;
5610                suppressKeyPressRepeat = false;
5611                var keyCode = $.ui.keyCode;
5612                switch ( event.keyCode ) {
5613                case keyCode.PAGE_UP:
5614                    suppressKeyPress = true;
5615                    this._move( "previousPage", event );
5616                    break;
5617                case keyCode.PAGE_DOWN:
5618                    suppressKeyPress = true;
5619                    this._move( "nextPage", event );
5620                    break;
5621                case keyCode.UP:
5622                    suppressKeyPress = true;
5623                    this._keyEvent( "previous", event );
5624                    break;
5625                case keyCode.DOWN:
5626                    suppressKeyPress = true;
5627                    this._keyEvent( "next", event );
5628                    break;
5629                case keyCode.ENTER:
5630
5631                    // when menu is open and has focus
5632                    if ( this.menu.active ) {
5633
5634                        // #6055 - Opera still allows the keypress to occur
5635                        // which causes forms to submit
5636                        suppressKeyPress = true;
5637                        event.preventDefault();
5638                        this.menu.select( event );
5639                    }
5640                    break;
5641                case keyCode.TAB:
5642                    if ( this.menu.active ) {
5643                        this.menu.select( event );
5644                    }
5645                    break;
5646                case keyCode.ESCAPE:
5647                    if ( this.menu.element.is( ":visible" ) ) {
5648                        if ( !this.isMultiLine ) {
5649                            this._value( this.term );
5650                        }
5651                        this.close( event );
5652
5653                        // Different browsers have different default behavior for escape
5654                        // Single press can mean undo or clear
5655                        event.preventDefault();
5656                    }
5657                    break;
5658                default:
5659                    suppressKeyPressRepeat = true;
5660
5661                    // search timeout should be triggered before the input value is changed
5662                    this._searchTimeout( event );
5663                    break;
5664                }
5665            },
5666            keypress: function( event ) {
5667                if ( suppressKeyPress ) {
5668                    suppressKeyPress = false;
5669                    if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
5670                        event.preventDefault();
5671                    }
5672                    return;
5673                }
5674                if ( suppressKeyPressRepeat ) {
5675                    return;
5676                }
5677
5678                // Replicate some key handlers to allow them to repeat in Firefox and Opera
5679                var keyCode = $.ui.keyCode;
5680                switch ( event.keyCode ) {
5681                case keyCode.PAGE_UP:
5682                    this._move( "previousPage", event );
5683                    break;
5684                case keyCode.PAGE_DOWN:
5685                    this._move( "nextPage", event );
5686                    break;
5687                case keyCode.UP:
5688                    this._keyEvent( "previous", event );
5689                    break;
5690                case keyCode.DOWN:
5691                    this._keyEvent( "next", event );
5692                    break;
5693                }
5694            },
5695            input: function( event ) {
5696                if ( suppressInput ) {
5697                    suppressInput = false;
5698                    event.preventDefault();
5699                    return;
5700                }
5701                this._searchTimeout( event );
5702            },
5703            focus: function() {
5704                this.selectedItem = null;
5705                this.previous = this._value();
5706            },
5707            blur: function( event ) {
5708                clearTimeout( this.searching );
5709                this.close( event );
5710                this._change( event );
5711            }
5712        } );
5713
5714        this._initSource();
5715        this.menu = $( "<ul>" )
5716            .appendTo( this._appendTo() )
5717            .menu( {
5718
5719                // disable ARIA support, the live region takes care of that
5720                role: null
5721            } )
5722            .hide()
5723            .menu( "instance" );
5724
5725        this._addClass( this.menu.element, "ui-autocomplete", "ui-front" );
5726        this._on( this.menu.element, {
5727            mousedown: function( event ) {
5728
5729                // Prevent moving focus out of the text field
5730                event.preventDefault();
5731            },
5732            menufocus: function( event, ui ) {
5733                var label, item;
5734
5735                // Support: Firefox
5736                // Prevent accidental activation of menu items in Firefox (#7024 #9118)
5737                if ( this.isNewMenu ) {
5738                    this.isNewMenu = false;
5739                    if ( event.originalEvent && /^mouse/.test( event.originalEvent.type ) ) {
5740                        this.menu.blur();
5741
5742                        this.document.one( "mousemove", function() {
5743                            $( event.target ).trigger( event.originalEvent );
5744                        } );
5745
5746                        return;
5747                    }
5748                }
5749
5750                item = ui.item.data( "ui-autocomplete-item" );
5751                if ( false !== this._trigger( "focus", event, { item: item } ) ) {
5752
5753                    // use value to match what will end up in the input, if it was a key event
5754                    if ( event.originalEvent && /^key/.test( event.originalEvent.type ) ) {
5755                        this._value( item.value );
5756                    }
5757                }
5758
5759                // Announce the value in the liveRegion
5760                label = ui.item.attr( "aria-label" ) || item.value;
5761                if ( label && String.prototype.trim.call( label ).length ) {
5762                    clearTimeout( this.liveRegionTimer );
5763                    this.liveRegionTimer = this._delay( function() {
5764                        this.liveRegion.html( $( "<div>" ).text( label ) );
5765                    }, 100 );
5766                }
5767            },
5768            menuselect: function( event, ui ) {
5769                var item = ui.item.data( "ui-autocomplete-item" ),
5770                    previous = this.previous;
5771
5772                // Only trigger when focus was lost (click on menu)
5773                if ( this.element[ 0 ] !== this.document[ 0 ].activeElement ) {
5774                    this.element.trigger( "focus" );
5775                    this.previous = previous;
5776                }
5777
5778                if ( false !== this._trigger( "select", event, { item: item } ) ) {
5779                    this._value( item.value );
5780                }
5781
5782                // reset the term after the select event
5783                // this allows custom select handling to work properly
5784                this.term = this._value();
5785
5786                this.close( event );
5787                this.selectedItem = item;
5788            }
5789        } );
5790
5791        this.liveRegion = $( "<div>", {
5792            role: "status",
5793            "aria-live": "assertive",
5794            "aria-relevant": "additions"
5795        } )
5796            .appendTo( this.document[ 0 ].body );
5797
5798        this._addClass( this.liveRegion, null, "ui-helper-hidden-accessible" );
5799
5800        // Turning off autocomplete prevents the browser from remembering the
5801        // value when navigating through history, so we re-enable autocomplete
5802        // if the page is unloaded before the widget is destroyed. #7790
5803        this._on( this.window, {
5804            beforeunload: function() {
5805                this.element.removeAttr( "autocomplete" );
5806            }
5807        } );
5808    },
5809
5810    _destroy: function() {
5811        clearTimeout( this.searching );
5812        this.element.removeAttr( "autocomplete" );
5813        this.menu.element.remove();
5814        this.liveRegion.remove();
5815    },
5816
5817    _setOption: function( key, value ) {
5818        this._super( key, value );
5819        if ( key === "source" ) {
5820            this._initSource();
5821        }
5822        if ( key === "appendTo" ) {
5823            this.menu.element.appendTo( this._appendTo() );
5824        }
5825        if ( key === "disabled" && value && this.xhr ) {
5826            this.xhr.abort();
5827        }
5828    },
5829
5830    _isEventTargetInWidget: function( event ) {
5831        var menuElement = this.menu.element[ 0 ];
5832
5833        return event.target === this.element[ 0 ] ||
5834            event.target === menuElement ||
5835            $.contains( menuElement, event.target );
5836    },
5837
5838    _closeOnClickOutside: function( event ) {
5839        if ( !this._isEventTargetInWidget( event ) ) {
5840            this.close();
5841        }
5842    },
5843
5844    _appendTo: function() {
5845        var element = this.options.appendTo;
5846
5847        if ( element ) {
5848            element = element.jquery || element.nodeType ?
5849                $( element ) :
5850                this.document.find( element ).eq( 0 );
5851        }
5852
5853        if ( !element || !element[ 0 ] ) {
5854            element = this.element.closest( ".ui-front, dialog" );
5855        }
5856
5857        if ( !element.length ) {
5858            element = this.document[ 0 ].body;
5859        }
5860
5861        return element;
5862    },
5863
5864    _initSource: function() {
5865        var array, url,
5866            that = this;
5867        if ( Array.isArray( this.options.source ) ) {
5868            array = this.options.source;
5869            this.source = function( request, response ) {
5870                response( $.ui.autocomplete.filter( array, request.term ) );
5871            };
5872        } else if ( typeof this.options.source === "string" ) {
5873            url = this.options.source;
5874            this.source = function( request, response ) {
5875                if ( that.xhr ) {
5876                    that.xhr.abort();
5877                }
5878                that.xhr = $.ajax( {
5879                    url: url,
5880                    data: request,
5881                    dataType: "json",
5882                    success: function( data ) {
5883                        response( data );
5884                    },
5885                    error: function() {
5886                        response( [] );
5887                    }
5888                } );
5889            };
5890        } else {
5891            this.source = this.options.source;
5892        }
5893    },
5894
5895    _searchTimeout: function( event ) {
5896        clearTimeout( this.searching );
5897        this.searching = this._delay( function() {
5898
5899            // Search if the value has changed, or if the user retypes the same value (see #7434)
5900            var equalValues = this.term === this._value(),
5901                menuVisible = this.menu.element.is( ":visible" ),
5902                modifierKey = event.altKey || event.ctrlKey || event.metaKey || event.shiftKey;
5903
5904            if ( !equalValues || ( equalValues && !menuVisible && !modifierKey ) ) {
5905                this.selectedItem = null;
5906                this.search( null, event );
5907            }
5908        }, this.options.delay );
5909    },
5910
5911    search: function( value, event ) {
5912        value = value != null ? value : this._value();
5913
5914        // Always save the actual value, not the one passed as an argument
5915        this.term = this._value();
5916
5917        if ( value.length < this.options.minLength ) {
5918            return this.close( event );
5919        }
5920
5921        if ( this._trigger( "search", event ) === false ) {
5922            return;
5923        }
5924
5925        return this._search( value );
5926    },
5927
5928    _search: function( value ) {
5929        this.pending++;
5930        this._addClass( "ui-autocomplete-loading" );
5931        this.cancelSearch = false;
5932
5933        this.source( { term: value }, this._response() );
5934    },
5935
5936    _response: function() {
5937        var index = ++this.requestIndex;
5938
5939        return function( content ) {
5940            if ( index === this.requestIndex ) {
5941                this.__response( content );
5942            }
5943
5944            this.pending--;
5945            if ( !this.pending ) {
5946                this._removeClass( "ui-autocomplete-loading" );
5947            }
5948        }.bind( this );
5949    },
5950
5951    __response: function( content ) {
5952        if ( content ) {
5953            content = this._normalize( content );
5954        }
5955        this._trigger( "response", null, { content: content } );
5956        if ( !this.options.disabled && content && content.length && !this.cancelSearch ) {
5957            this._suggest( content );
5958            this._trigger( "open" );
5959        } else {
5960
5961            // use ._close() instead of .close() so we don't cancel future searches
5962            this._close();
5963        }
5964    },
5965
5966    close: function( event ) {
5967        this.cancelSearch = true;
5968        this._close( event );
5969    },
5970
5971    _close: function( event ) {
5972
5973        // Remove the handler that closes the menu on outside clicks
5974        this._off( this.document, "mousedown" );
5975
5976        if ( this.menu.element.is( ":visible" ) ) {
5977            this.menu.element.hide();
5978            this.menu.blur();
5979            this.isNewMenu = true;
5980            this._trigger( "close", event );
5981        }
5982    },
5983
5984    _change: function( event ) {
5985        if ( this.previous !== this._value() ) {
5986            this._trigger( "change", event, { item: this.selectedItem } );
5987        }
5988    },
5989
5990    _normalize: function( items ) {
5991
5992        // assume all items have the right format when the first item is complete
5993        if ( items.length && items[ 0 ].label && items[ 0 ].value ) {
5994            return items;
5995        }
5996        return $.map( items, function( item ) {
5997            if ( typeof item === "string" ) {
5998                return {
5999                    label: item,
6000                    value: item
6001                };
6002            }
6003            return $.extend( {}, item, {
6004                label: item.label || item.value,
6005                value: item.value || item.label
6006            } );
6007        } );
6008    },
6009
6010    _suggest: function( items ) {
6011        var ul = this.menu.element.empty();
6012        this._renderMenu( ul, items );
6013        this.isNewMenu = true;
6014        this.menu.refresh();
6015
6016        // Size and position menu
6017        ul.show();
6018        this._resizeMenu();
6019        ul.position( $.extend( {
6020            of: this.element
6021        }, this.options.position ) );
6022
6023        if ( this.options.autoFocus ) {
6024            this.menu.next();
6025        }
6026
6027        // Listen for interactions outside of the widget (#6642)
6028        this._on( this.document, {
6029            mousedown: "_closeOnClickOutside"
6030        } );
6031    },
6032
6033    _resizeMenu: function() {
6034        var ul = this.menu.element;
6035        ul.outerWidth( Math.max(
6036
6037            // Firefox wraps long text (possibly a rounding bug)
6038            // so we add 1px to avoid the wrapping (#7513)
6039            ul.width( "" ).outerWidth() + 1,
6040            this.element.outerWidth()
6041        ) );
6042    },
6043
6044    _renderMenu: function( ul, items ) {
6045        var that = this;
6046        $.each( items, function( index, item ) {
6047            that._renderItemData( ul, item );
6048        } );
6049    },
6050
6051    _renderItemData: function( ul, item ) {
6052        return this._renderItem( ul, item ).data( "ui-autocomplete-item", item );
6053    },
6054
6055    _renderItem: function( ul, item ) {
6056        return $( "<li>" )
6057            .append( $( "<div>" ).text( item.label ) )
6058            .appendTo( ul );
6059    },
6060
6061    _move: function( direction, event ) {
6062        if ( !this.menu.element.is( ":visible" ) ) {
6063            this.search( null, event );
6064            return;
6065        }
6066        if ( this.menu.isFirstItem() && /^previous/.test( direction ) ||
6067                this.menu.isLastItem() && /^next/.test( direction ) ) {
6068
6069            if ( !this.isMultiLine ) {
6070                this._value( this.term );
6071            }
6072
6073            this.menu.blur();
6074            return;
6075        }
6076        this.menu[ direction ]( event );
6077    },
6078
6079    widget: function() {
6080        return this.menu.element;
6081    },
6082
6083    _value: function() {
6084        return this.valueMethod.apply( this.element, arguments );
6085    },
6086
6087    _keyEvent: function( keyEvent, event ) {
6088        if ( !this.isMultiLine || this.menu.element.is( ":visible" ) ) {
6089            this._move( keyEvent, event );
6090
6091            // Prevents moving cursor to beginning/end of the text field in some browsers
6092            event.preventDefault();
6093        }
6094    }
6095} );
6096
6097$.extend( $.ui.autocomplete, {
6098    escapeRegex: function( value ) {
6099        return value.replace( /[\-\[\]{}()*+?.,\\\^$|#\s]/g, "\\$&" );
6100    },
6101    filter: function( array, term ) {
6102        var matcher = new RegExp( $.ui.autocomplete.escapeRegex( term ), "i" );
6103        return $.grep( array, function( value ) {
6104            return matcher.test( value.label || value.value || value );
6105        } );
6106    }
6107} );
6108
6109// Live region extension, adding a `messages` option
6110// NOTE: This is an experimental API. We are still investigating
6111// a full solution for string manipulation and internationalization.
6112$.widget( "ui.autocomplete", $.ui.autocomplete, {
6113    options: {
6114        messages: {
6115            noResults: "No search results.",
6116            results: function( amount ) {
6117                return amount + ( amount > 1 ? " results are" : " result is" ) +
6118                    " available, use up and down arrow keys to navigate.";
6119            }
6120        }
6121    },
6122
6123    __response: function( content ) {
6124        var message;
6125        this._superApply( arguments );
6126        if ( this.options.disabled || this.cancelSearch ) {
6127            return;
6128        }
6129        if ( content && content.length ) {
6130            message = this.options.messages.results( content.length );
6131        } else {
6132            message = this.options.messages.noResults;
6133        }
6134        clearTimeout( this.liveRegionTimer );
6135        this.liveRegionTimer = this._delay( function() {
6136            this.liveRegion.html( $( "<div>" ).text( message ) );
6137        }, 100 );
6138    }
6139} );
6140
6141var widgetsAutocomplete = $.ui.autocomplete;
6142
6143
6144/*!
6145 * jQuery UI Controlgroup 1.14.1
6146 * https://jqueryui.com
6147 *
6148 * Copyright OpenJS Foundation and other contributors
6149 * Released under the MIT license.
6150 * https://jquery.org/license
6151 */
6152
6153//>>label: Controlgroup
6154//>>group: Widgets
6155//>>description: Visually groups form control widgets
6156//>>docs: https://api.jqueryui.com/controlgroup/
6157//>>demos: https://jqueryui.com/controlgroup/
6158//>>css.structure: ../../themes/base/core.css
6159//>>css.structure: ../../themes/base/controlgroup.css
6160//>>css.theme: ../../themes/base/theme.css
6161
6162
6163var controlgroupCornerRegex = /ui-corner-([a-z]){2,6}/g;
6164
6165var widgetsControlgroup = $.widget( "ui.controlgroup", {
6166    version: "1.14.1",
6167    defaultElement: "<div>",
6168    options: {
6169        direction: "horizontal",
6170        disabled: null,
6171        onlyVisible: true,
6172        items: {
6173            "button": "input[type=button], input[type=submit], input[type=reset], button, a",
6174            "controlgroupLabel": ".ui-controlgroup-label",
6175            "checkboxradio": "input[type='checkbox'], input[type='radio']",
6176            "selectmenu": "select",
6177            "spinner": ".ui-spinner-input"
6178        }
6179    },
6180
6181    _create: function() {
6182        this._enhance();
6183    },
6184
6185    // To support the enhanced option in jQuery Mobile, we isolate DOM manipulation
6186    _enhance: function() {
6187        this.element.attr( "role", "toolbar" );
6188        this.refresh();
6189    },
6190
6191    _destroy: function() {
6192        this._callChildMethod( "destroy" );
6193        this.childWidgets.removeData( "ui-controlgroup-data" );
6194        this.element.removeAttr( "role" );
6195        if ( this.options.items.controlgroupLabel ) {
6196            this.element
6197                .find( this.options.items.controlgroupLabel )
6198                .find( ".ui-controlgroup-label-contents" )
6199                .contents().unwrap();
6200        }
6201    },
6202
6203    _initWidgets: function() {
6204        var that = this,
6205            childWidgets = [];
6206
6207        // First we iterate over each of the items options
6208        $.each( this.options.items, function( widget, selector ) {
6209            var labels;
6210            var options = {};
6211
6212            // Make sure the widget has a selector set
6213            if ( !selector ) {
6214                return;
6215            }
6216
6217            if ( widget === "controlgroupLabel" ) {
6218                labels = that.element.find( selector );
6219                labels.each( function() {
6220                    var element = $( this );
6221
6222                    if ( element.children( ".ui-controlgroup-label-contents" ).length ) {
6223                        return;
6224                    }
6225                    element.contents()
6226                        .wrapAll( "<span class='ui-controlgroup-label-contents'></span>" );
6227                } );
6228                that._addClass( labels, null, "ui-widget ui-widget-content ui-state-default" );
6229                childWidgets = childWidgets.concat( labels.get() );
6230                return;
6231            }
6232
6233            // Make sure the widget actually exists
6234            if ( !$.fn[ widget ] ) {
6235                return;
6236            }
6237
6238            // We assume everything is in the middle to start because we can't determine
6239            // first / last elements until all enhancments are done.
6240            if ( that[ "_" + widget + "Options" ] ) {
6241                options = that[ "_" + widget + "Options" ]( "middle" );
6242            } else {
6243                options = { classes: {} };
6244            }
6245
6246            // Find instances of this widget inside controlgroup and init them
6247            that.element
6248                .find( selector )
6249                .each( function() {
6250                    var element = $( this );
6251                    var instance = element[ widget ]( "instance" );
6252
6253                    // We need to clone the default options for this type of widget to avoid
6254                    // polluting the variable options which has a wider scope than a single widget.
6255                    var instanceOptions = $.widget.extend( {}, options );
6256
6257                    // If the button is the child of a spinner ignore it
6258                    // TODO: Find a more generic solution
6259                    if ( widget === "button" && element.parent( ".ui-spinner" ).length ) {
6260                        return;
6261                    }
6262
6263                    // Create the widget if it doesn't exist
6264                    if ( !instance ) {
6265                        instance = element[ widget ]()[ widget ]( "instance" );
6266                    }
6267                    if ( instance ) {
6268                        instanceOptions.classes =
6269                            that._resolveClassesValues( instanceOptions.classes, instance );
6270                    }
6271                    element[ widget ]( instanceOptions );
6272
6273                    // Store an instance of the controlgroup to be able to reference
6274                    // from the outermost element for changing options and refresh
6275                    var widgetElement = element[ widget ]( "widget" );
6276                    $.data( widgetElement[ 0 ], "ui-controlgroup-data",
6277                        instance ? instance : element[ widget ]( "instance" ) );
6278
6279                    childWidgets.push( widgetElement[ 0 ] );
6280                } );
6281        } );
6282
6283        this.childWidgets = $( $.uniqueSort( childWidgets ) );
6284        this._addClass( this.childWidgets, "ui-controlgroup-item" );
6285    },
6286
6287    _callChildMethod: function( method ) {
6288        this.childWidgets.each( function() {
6289            var element = $( this ),
6290                data = element.data( "ui-controlgroup-data" );
6291            if ( data && data[ method ] ) {
6292                data[ method ]();
6293            }
6294        } );
6295    },
6296
6297    _updateCornerClass: function( element, position ) {
6298        var remove = "ui-corner-top ui-corner-bottom ui-corner-left ui-corner-right ui-corner-all";
6299        var add = this._buildSimpleOptions( position, "label" ).classes.label;
6300
6301        this._removeClass( element, null, remove );
6302        this._addClass( element, null, add );
6303    },
6304
6305    _buildSimpleOptions: function( position, key ) {
6306        var direction = this.options.direction === "vertical";
6307        var result = {
6308            classes: {}
6309        };
6310        result.classes[ key ] = {
6311            "middle": "",
6312            "first": "ui-corner-" + ( direction ? "top" : "left" ),
6313            "last": "ui-corner-" + ( direction ? "bottom" : "right" ),
6314            "only": "ui-corner-all"
6315        }[ position ];
6316
6317        return result;
6318    },
6319
6320    _spinnerOptions: function( position ) {
6321        var options = this._buildSimpleOptions( position, "ui-spinner" );
6322
6323        options.classes[ "ui-spinner-up" ] = "";
6324        options.classes[ "ui-spinner-down" ] = "";
6325
6326        return options;
6327    },
6328
6329    _buttonOptions: function( position ) {
6330        return this._buildSimpleOptions( position, "ui-button" );
6331    },
6332
6333    _checkboxradioOptions: function( position ) {
6334        return this._buildSimpleOptions( position, "ui-checkboxradio-label" );
6335    },
6336
6337    _selectmenuOptions: function( position ) {
6338        var direction = this.options.direction === "vertical";
6339        return {
6340            width: direction ? "auto" : false,
6341            classes: {
6342                middle: {
6343                    "ui-selectmenu-button-open": "",
6344                    "ui-selectmenu-button-closed": ""
6345                },
6346                first: {
6347                    "ui-selectmenu-button-open": "ui-corner-" + ( direction ? "top" : "tl" ),
6348                    "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "top" : "left" )
6349                },
6350                last: {
6351                    "ui-selectmenu-button-open": direction ? "" : "ui-corner-tr",
6352                    "ui-selectmenu-button-closed": "ui-corner-" + ( direction ? "bottom" : "right" )
6353                },
6354                only: {
6355                    "ui-selectmenu-button-open": "ui-corner-top",
6356                    "ui-selectmenu-button-closed": "ui-corner-all"
6357                }
6358
6359            }[ position ]
6360        };
6361    },
6362
6363    _resolveClassesValues: function( classes, instance ) {
6364        var result = {};
6365        $.each( classes, function( key ) {
6366            var current = instance.options.classes[ key ] || "";
6367            current = String.prototype.trim.call( current.replace( controlgroupCornerRegex, "" ) );
6368            result[ key ] = ( current + " " + classes[ key ] ).replace( /\s+/g, " " );
6369        } );
6370        return result;
6371    },
6372
6373    _setOption: function( key, value ) {
6374        if ( key === "direction" ) {
6375            this._removeClass( "ui-controlgroup-" + this.options.direction );
6376        }
6377
6378        this._super( key, value );
6379        if ( key === "disabled" ) {
6380            this._callChildMethod( value ? "disable" : "enable" );
6381            return;
6382        }
6383
6384        this.refresh();
6385    },
6386
6387    refresh: function() {
6388        var children,
6389            that = this;
6390
6391        this._addClass( "ui-controlgroup ui-controlgroup-" + this.options.direction );
6392
6393        if ( this.options.direction === "horizontal" ) {
6394            this._addClass( null, "ui-helper-clearfix" );
6395        }
6396        this._initWidgets();
6397
6398        children = this.childWidgets;
6399
6400        // We filter here because we need to track all childWidgets not just the visible ones
6401        if ( this.options.onlyVisible ) {
6402            children = children.filter( ":visible" );
6403        }
6404
6405        if ( children.length ) {
6406
6407            // We do this last because we need to make sure all enhancment is done
6408            // before determining first and last
6409            $.each( [ "first", "last" ], function( index, value ) {
6410                var instance = children[ value ]().data( "ui-controlgroup-data" );
6411
6412                if ( instance && that[ "_" + instance.widgetName + "Options" ] ) {
6413                    var options = that[ "_" + instance.widgetName + "Options" ](
6414                        children.length === 1 ? "only" : value
6415                    );
6416                    options.classes = that._resolveClassesValues( options.classes, instance );
6417                    instance.element[ instance.widgetName ]( options );
6418                } else {
6419                    that._updateCornerClass( children[ value ](), value );
6420                }
6421            } );
6422
6423            // Finally call the refresh method on each of the child widgets.
6424            this._callChildMethod( "refresh" );
6425        }
6426    }
6427} );
6428
6429/*!
6430 * jQuery UI Checkboxradio 1.14.1
6431 * https://jqueryui.com
6432 *
6433 * Copyright OpenJS Foundation and other contributors
6434 * Released under the MIT license.
6435 * https://jquery.org/license
6436 */
6437
6438//>>label: Checkboxradio
6439//>>group: Widgets
6440//>>description: Enhances a form with multiple themeable checkboxes or radio buttons.
6441//>>docs: https://api.jqueryui.com/checkboxradio/
6442//>>demos: https://jqueryui.com/checkboxradio/
6443//>>css.structure: ../../themes/base/core.css
6444//>>css.structure: ../../themes/base/button.css
6445//>>css.structure: ../../themes/base/checkboxradio.css
6446//>>css.theme: ../../themes/base/theme.css
6447
6448
6449$.widget( "ui.checkboxradio", [ $.ui.formResetMixin, {
6450    version: "1.14.1",
6451    options: {
6452        disabled: null,
6453        label: null,
6454        icon: true,
6455        classes: {
6456            "ui-checkboxradio-label": "ui-corner-all",
6457            "ui-checkboxradio-icon": "ui-corner-all"
6458        }
6459    },
6460
6461    _getCreateOptions: function() {
6462        var disabled, labels, labelContents;
6463        var options = this._super() || {};
6464
6465        // We read the type here, because it makes more sense to throw a element type error first,
6466        // rather then the error for lack of a label. Often if its the wrong type, it
6467        // won't have a label (e.g. calling on a div, btn, etc)
6468        this._readType();
6469
6470        labels = this.element.labels();
6471
6472        // If there are multiple labels, use the last one
6473        this.label = $( labels[ labels.length - 1 ] );
6474        if ( !this.label.length ) {
6475            $.error( "No label found for checkboxradio widget" );
6476        }
6477
6478        this.originalLabel = "";
6479
6480        // We need to get the label text but this may also need to make sure it does not contain the
6481        // input itself.
6482        // The label contents could be text, html, or a mix. We wrap all elements
6483        // and read the wrapper's `innerHTML` to get a string representation of
6484        // the label, without the input as part of it.
6485        labelContents = this.label.contents().not( this.element[ 0 ] );
6486
6487        if ( labelContents.length ) {
6488            this.originalLabel += labelContents
6489                .clone()
6490                .wrapAll( "<div></div>" )
6491                .parent()
6492                .html();
6493        }
6494
6495        // Set the label option if we found label text
6496        if ( this.originalLabel ) {
6497            options.label = this.originalLabel;
6498        }
6499
6500        disabled = this.element[ 0 ].disabled;
6501        if ( disabled != null ) {
6502            options.disabled = disabled;
6503        }
6504        return options;
6505    },
6506
6507    _create: function() {
6508        var checked = this.element[ 0 ].checked;
6509
6510        this._bindFormResetHandler();
6511
6512        if ( this.options.disabled == null ) {
6513            this.options.disabled = this.element[ 0 ].disabled;
6514        }
6515
6516        this._setOption( "disabled", this.options.disabled );
6517        this._addClass( "ui-checkboxradio", "ui-helper-hidden-accessible" );
6518        this._addClass( this.label, "ui-checkboxradio-label", "ui-button ui-widget" );
6519
6520        if ( this.type === "radio" ) {
6521            this._addClass( this.label, "ui-checkboxradio-radio-label" );
6522        }
6523
6524        if ( this.options.label && this.options.label !== this.originalLabel ) {
6525            this._updateLabel();
6526        } else if ( this.originalLabel ) {
6527            this.options.label = this.originalLabel;
6528        }
6529
6530        this._enhance();
6531
6532        if ( checked ) {
6533            this._addClass( this.label, "ui-checkboxradio-checked", "ui-state-active" );
6534        }
6535
6536        this._on( {
6537            change: "_toggleClasses",
6538            focus: function() {
6539                this._addClass( this.label, null, "ui-state-focus ui-visual-focus" );
6540            },
6541            blur: function() {
6542                this._removeClass( this.label, null, "ui-state-focus ui-visual-focus" );
6543            }
6544        } );
6545    },
6546
6547    _readType: function() {
6548        var nodeName = this.element[ 0 ].nodeName.toLowerCase();
6549        this.type = this.element[ 0 ].type;
6550        if ( nodeName !== "input" || !/radio|checkbox/.test( this.type ) ) {
6551            $.error( "Can't create checkboxradio on element.nodeName=" + nodeName +
6552                " and element.type=" + this.type );
6553        }
6554    },
6555
6556    // Support jQuery Mobile enhanced option
6557    _enhance: function() {
6558        this._updateIcon( this.element[ 0 ].checked );
6559    },
6560
6561    widget: function() {
6562        return this.label;
6563    },
6564
6565    _getRadioGroup: function() {
6566        var group;
6567        var name = this.element[ 0 ].name;
6568        var nameSelector = "input[name='" + CSS.escape( name ) + "']";
6569
6570        if ( !name ) {
6571            return $( [] );
6572        }
6573
6574        if ( this.form.length ) {
6575            group = $( this.form[ 0 ].elements ).filter( nameSelector );
6576        } else {
6577
6578            // Not inside a form, check all inputs that also are not inside a form
6579            group = $( nameSelector ).filter( function() {
6580                return $( $( this ).prop( "form" ) ).length === 0;
6581            } );
6582        }
6583
6584        return group.not( this.element );
6585    },
6586
6587    _toggleClasses: function() {
6588        var checked = this.element[ 0 ].checked;
6589        this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6590
6591        if ( this.options.icon && this.type === "checkbox" ) {
6592            this._toggleClass( this.icon, null, "ui-icon-check ui-state-checked", checked )
6593                ._toggleClass( this.icon, null, "ui-icon-blank", !checked );
6594        }
6595
6596        if ( this.type === "radio" ) {
6597            this._getRadioGroup()
6598                .each( function() {
6599                    var instance = $( this ).checkboxradio( "instance" );
6600
6601                    if ( instance ) {
6602                        instance._removeClass( instance.label,
6603                            "ui-checkboxradio-checked", "ui-state-active" );
6604                    }
6605                } );
6606        }
6607    },
6608
6609    _destroy: function() {
6610        this._unbindFormResetHandler();
6611
6612        if ( this.icon ) {
6613            this.icon.remove();
6614            this.iconSpace.remove();
6615        }
6616    },
6617
6618    _setOption: function( key, value ) {
6619
6620        // We don't allow the value to be set to nothing
6621        if ( key === "label" && !value ) {
6622            return;
6623        }
6624
6625        this._super( key, value );
6626
6627        if ( key === "disabled" ) {
6628            this._toggleClass( this.label, null, "ui-state-disabled", value );
6629            this.element[ 0 ].disabled = value;
6630
6631            // Don't refresh when setting disabled
6632            return;
6633        }
6634        this.refresh();
6635    },
6636
6637    _updateIcon: function( checked ) {
6638        var toAdd = "ui-icon ui-icon-background ";
6639
6640        if ( this.options.icon ) {
6641            if ( !this.icon ) {
6642                this.icon = $( "<span>" );
6643                this.iconSpace = $( "<span> </span>" );
6644                this._addClass( this.iconSpace, "ui-checkboxradio-icon-space" );
6645            }
6646
6647            if ( this.type === "checkbox" ) {
6648                toAdd += checked ? "ui-icon-check ui-state-checked" : "ui-icon-blank";
6649                this._removeClass( this.icon, null, checked ? "ui-icon-blank" : "ui-icon-check" );
6650            } else {
6651                toAdd += "ui-icon-blank";
6652            }
6653            this._addClass( this.icon, "ui-checkboxradio-icon", toAdd );
6654            if ( !checked ) {
6655                this._removeClass( this.icon, null, "ui-icon-check ui-state-checked" );
6656            }
6657            this.icon.prependTo( this.label ).after( this.iconSpace );
6658        } else if ( this.icon !== undefined ) {
6659            this.icon.remove();
6660            this.iconSpace.remove();
6661            delete this.icon;
6662        }
6663    },
6664
6665    _updateLabel: function() {
6666
6667        // Remove the contents of the label ( minus the icon, icon space, and input )
6668        var contents = this.label.contents().not( this.element[ 0 ] );
6669        if ( this.icon ) {
6670            contents = contents.not( this.icon[ 0 ] );
6671        }
6672        if ( this.iconSpace ) {
6673            contents = contents.not( this.iconSpace[ 0 ] );
6674        }
6675        contents.remove();
6676
6677        this.label.append( this.options.label );
6678    },
6679
6680    refresh: function() {
6681        var checked = this.element[ 0 ].checked,
6682            isDisabled = this.element[ 0 ].disabled;
6683
6684        this._updateIcon( checked );
6685        this._toggleClass( this.label, "ui-checkboxradio-checked", "ui-state-active", checked );
6686        if ( this.options.label !== null ) {
6687            this._updateLabel();
6688        }
6689
6690        if ( isDisabled !== this.options.disabled ) {
6691            this._setOptions( { "disabled": isDisabled } );
6692        }
6693    }
6694
6695} ] );
6696
6697var widgetsCheckboxradio = $.ui.checkboxradio;
6698
6699
6700/*!
6701 * jQuery UI Button 1.14.1
6702 * https://jqueryui.com
6703 *
6704 * Copyright OpenJS Foundation and other contributors
6705 * Released under the MIT license.
6706 * https://jquery.org/license
6707 */
6708
6709//>>label: Button
6710//>>group: Widgets
6711//>>description: Enhances a form with themeable buttons.
6712//>>docs: https://api.jqueryui.com/button/
6713//>>demos: https://jqueryui.com/button/
6714//>>css.structure: ../../themes/base/core.css
6715//>>css.structure: ../../themes/base/button.css
6716//>>css.theme: ../../themes/base/theme.css
6717
6718
6719$.widget( "ui.button", {
6720    version: "1.14.1",
6721    defaultElement: "<button>",
6722    options: {
6723        classes: {
6724            "ui-button": "ui-corner-all"
6725        },
6726        disabled: null,
6727        icon: null,
6728        iconPosition: "beginning",
6729        label: null,
6730        showLabel: true
6731    },
6732
6733    _getCreateOptions: function() {
6734        var disabled,
6735
6736            // This is to support cases like in jQuery Mobile where the base widget does have
6737            // an implementation of _getCreateOptions
6738            options = this._super() || {};
6739
6740        this.isInput = this.element.is( "input" );
6741
6742        disabled = this.element[ 0 ].disabled;
6743        if ( disabled != null ) {
6744            options.disabled = disabled;
6745        }
6746
6747        this.originalLabel = this.isInput ? this.element.val() : this.element.html();
6748        if ( this.originalLabel ) {
6749            options.label = this.originalLabel;
6750        }
6751
6752        return options;
6753    },
6754
6755    _create: function() {
6756        if ( !this.option.showLabel & !this.options.icon ) {
6757            this.options.showLabel = true;
6758        }
6759
6760        // We have to check the option again here even though we did in _getCreateOptions,
6761        // because null may have been passed on init which would override what was set in
6762        // _getCreateOptions
6763        if ( this.options.disabled == null ) {
6764            this.options.disabled = this.element[ 0 ].disabled || false;
6765        }
6766
6767        this.hasTitle = !!this.element.attr( "title" );
6768
6769        // Check to see if the label needs to be set or if its already correct
6770        if ( this.options.label && this.options.label !== this.originalLabel ) {
6771            if ( this.isInput ) {
6772                this.element.val( this.options.label );
6773            } else {
6774                this.element.html( this.options.label );
6775            }
6776        }
6777        this._addClass( "ui-button", "ui-widget" );
6778        this._setOption( "disabled", this.options.disabled );
6779        this._enhance();
6780
6781        if ( this.element.is( "a" ) ) {
6782            this._on( {
6783                "keyup": function( event ) {
6784                    if ( event.keyCode === $.ui.keyCode.SPACE ) {
6785                        event.preventDefault();
6786
6787                        // If a native click is available use it, so we
6788                        // actually cause navigation. Otherwise, just trigger
6789                        // a click event.
6790                        if ( this.element[ 0 ].click ) {
6791                            this.element[ 0 ].click();
6792                        } else {
6793                            this.element.trigger( "click" );
6794                        }
6795                    }
6796                }
6797            } );
6798        }
6799    },
6800
6801    _enhance: function() {
6802        if ( !this.element.is( "button" ) ) {
6803            this.element.attr( "role", "button" );
6804        }
6805
6806        if ( this.options.icon ) {
6807            this._updateIcon( "icon", this.options.icon );
6808            this._updateTooltip();
6809        }
6810    },
6811
6812    _updateTooltip: function() {
6813        this.title = this.element.attr( "title" );
6814
6815        if ( !this.options.showLabel && !this.title ) {
6816            this.element.attr( "title", this.options.label );
6817        }
6818    },
6819
6820    _updateIcon: function( option, value ) {
6821        var icon = option !== "iconPosition",
6822            position = icon ? this.options.iconPosition : value,
6823            displayBlock = position === "top" || position === "bottom";
6824
6825        // Create icon
6826        if ( !this.icon ) {
6827            this.icon = $( "<span>" );
6828
6829            this._addClass( this.icon, "ui-button-icon", "ui-icon" );
6830
6831            if ( !this.options.showLabel ) {
6832                this._addClass( "ui-button-icon-only" );
6833            }
6834        } else if ( icon ) {
6835
6836            // If we are updating the icon remove the old icon class
6837            this._removeClass( this.icon, null, this.options.icon );
6838        }
6839
6840        // If we are updating the icon add the new icon class
6841        if ( icon ) {
6842            this._addClass( this.icon, null, value );
6843        }
6844
6845        this._attachIcon( position );
6846
6847        // If the icon is on top or bottom we need to add the ui-widget-icon-block class and remove
6848        // the iconSpace if there is one.
6849        if ( displayBlock ) {
6850            this._addClass( this.icon, null, "ui-widget-icon-block" );
6851            if ( this.iconSpace ) {
6852                this.iconSpace.remove();
6853            }
6854        } else {
6855
6856            // Position is beginning or end so remove the ui-widget-icon-block class and add the
6857            // space if it does not exist
6858            if ( !this.iconSpace ) {
6859                this.iconSpace = $( "<span> </span>" );
6860                this._addClass( this.iconSpace, "ui-button-icon-space" );
6861            }
6862            this._removeClass( this.icon, null, "ui-wiget-icon-block" );
6863            this._attachIconSpace( position );
6864        }
6865    },
6866
6867    _destroy: function() {
6868        this.element.removeAttr( "role" );
6869
6870        if ( this.icon ) {
6871            this.icon.remove();
6872        }
6873        if ( this.iconSpace ) {
6874            this.iconSpace.remove();
6875        }
6876        if ( !this.hasTitle ) {
6877            this.element.removeAttr( "title" );
6878        }
6879    },
6880
6881    _attachIconSpace: function( iconPosition ) {
6882        this.icon[ /^(?:end|bottom)/.test( iconPosition ) ? "before" : "after" ]( this.iconSpace );
6883    },
6884
6885    _attachIcon: function( iconPosition ) {
6886        this.element[ /^(?:end|bottom)/.test( iconPosition ) ? "append" : "prepend" ]( this.icon );
6887    },
6888
6889    _setOptions: function( options ) {
6890        var newShowLabel = options.showLabel === undefined ?
6891                this.options.showLabel :
6892                options.showLabel,
6893            newIcon = options.icon === undefined ? this.options.icon : options.icon;
6894
6895        if ( !newShowLabel && !newIcon ) {
6896            options.showLabel = true;
6897        }
6898        this._super( options );
6899    },
6900
6901    _setOption: function( key, value ) {
6902        if ( key === "icon" ) {
6903            if ( value ) {
6904                this._updateIcon( key, value );
6905            } else if ( this.icon ) {
6906                this.icon.remove();
6907                if ( this.iconSpace ) {
6908                    this.iconSpace.remove();
6909                }
6910            }
6911        }
6912
6913        if ( key === "iconPosition" ) {
6914            this._updateIcon( key, value );
6915        }
6916
6917        // Make sure we can't end up with a button that has neither text nor icon
6918        if ( key === "showLabel" ) {
6919                this._toggleClass( "ui-button-icon-only", null, !value );
6920                this._updateTooltip();
6921        }
6922
6923        if ( key === "label" ) {
6924            if ( this.isInput ) {
6925                this.element.val( value );
6926            } else {
6927
6928                // If there is an icon, append it, else nothing then append the value
6929                // this avoids removal of the icon when setting label text
6930                this.element.html( value );
6931                if ( this.icon ) {
6932                    this._attachIcon( this.options.iconPosition );
6933                    this._attachIconSpace( this.options.iconPosition );
6934                }
6935            }
6936        }
6937
6938        this._super( key, value );
6939
6940        if ( key === "disabled" ) {
6941            this._toggleClass( null, "ui-state-disabled", value );
6942            this.element[ 0 ].disabled = value;
6943            if ( value ) {
6944                this.element.trigger( "blur" );
6945            }
6946        }
6947    },
6948
6949    refresh: function() {
6950
6951        // Make sure to only check disabled if its an element that supports this otherwise
6952        // check for the disabled class to determine state
6953        var isDisabled = this.element.is( "input, button" ) ?
6954            this.element[ 0 ].disabled : this.element.hasClass( "ui-button-disabled" );
6955
6956        if ( isDisabled !== this.options.disabled ) {
6957            this._setOptions( { disabled: isDisabled } );
6958        }
6959
6960        this._updateTooltip();
6961    }
6962} );
6963
6964// DEPRECATED
6965if ( $.uiBackCompat === true ) {
6966
6967    // Text and Icons options
6968    $.widget( "ui.button", $.ui.button, {
6969        options: {
6970            text: true,
6971            icons: {
6972                primary: null,
6973                secondary: null
6974            }
6975        },
6976
6977        _create: function() {
6978            if ( this.options.showLabel && !this.options.text ) {
6979                this.options.showLabel = this.options.text;
6980            }
6981            if ( !this.options.showLabel && this.options.text ) {
6982                this.options.text = this.options.showLabel;
6983            }
6984            if ( !this.options.icon && ( this.options.icons.primary ||
6985                    this.options.icons.secondary ) ) {
6986                if ( this.options.icons.primary ) {
6987                    this.options.icon = this.options.icons.primary;
6988                } else {
6989                    this.options.icon = this.options.icons.secondary;
6990                    this.options.iconPosition = "end";
6991                }
6992            } else if ( this.options.icon ) {
6993                this.options.icons.primary = this.options.icon;
6994            }
6995            this._super();
6996        },
6997
6998        _setOption: function( key, value ) {
6999            if ( key === "text" ) {
7000                this._super( "showLabel", value );
7001                return;
7002            }
7003            if ( key === "showLabel" ) {
7004                this.options.text = value;
7005            }
7006            if ( key === "icon" ) {
7007                this.options.icons.primary = value;
7008            }
7009            if ( key === "icons" ) {
7010                if ( value.primary ) {
7011                    this._super( "icon", value.primary );
7012                    this._super( "iconPosition", "beginning" );
7013                } else if ( value.secondary ) {
7014                    this._super( "icon", value.secondary );
7015                    this._super( "iconPosition", "end" );
7016                }
7017            }
7018            this._superApply( arguments );
7019        }
7020    } );
7021
7022    $.fn.button = ( function( orig ) {
7023        return function( options ) {
7024            var isMethodCall = typeof options === "string";
7025            var args = Array.prototype.slice.call( arguments, 1 );
7026            var returnValue = this;
7027
7028            if ( isMethodCall ) {
7029
7030                // If this is an empty collection, we need to have the instance method
7031                // return undefined instead of the jQuery instance
7032                if ( !this.length && options === "instance" ) {
7033                    returnValue = undefined;
7034                } else {
7035                    this.each( function() {
7036                        var methodValue;
7037                        var type = $( this ).attr( "type" );
7038                        var name = type !== "checkbox" && type !== "radio" ?
7039                            "button" :
7040                            "checkboxradio";
7041                        var instance = $.data( this, "ui-" + name );
7042
7043                        if ( options === "instance" ) {
7044                            returnValue = instance;
7045                            return false;
7046                        }
7047
7048                        if ( !instance ) {
7049                            return $.error( "cannot call methods on button" +
7050                                " prior to initialization; " +
7051                                "attempted to call method '" + options + "'" );
7052                        }
7053
7054                        if ( typeof instance[ options ] !== "function" ||
7055                            options.charAt( 0 ) === "_" ) {
7056                            return $.error( "no such method '" + options + "' for button" +
7057                                " widget instance" );
7058                        }
7059
7060                        methodValue = instance[ options ].apply( instance, args );
7061
7062                        if ( methodValue !== instance && methodValue !== undefined ) {
7063                            returnValue = methodValue && methodValue.jquery ?
7064                                returnValue.pushStack( methodValue.get() ) :
7065                                methodValue;
7066                            return false;
7067                        }
7068                    } );
7069                }
7070            } else {
7071
7072                // Allow multiple hashes to be passed on init
7073                if ( args.length ) {
7074                    options = $.widget.extend.apply( null, [ options ].concat( args ) );
7075                }
7076
7077                this.each( function() {
7078                    var type = $( this ).attr( "type" );
7079                    var name = type !== "checkbox" && type !== "radio" ? "button" : "checkboxradio";
7080                    var instance = $.data( this, "ui-" + name );
7081
7082                    if ( instance ) {
7083                        instance.option( options || {} );
7084                        if ( instance._init ) {
7085                            instance._init();
7086                        }
7087                    } else {
7088                        if ( name === "button" ) {
7089                            orig.call( $( this ), options );
7090                            return;
7091                        }
7092
7093                        $( this ).checkboxradio( $.extend( { icon: false }, options ) );
7094                    }
7095                } );
7096            }
7097
7098            return returnValue;
7099        };
7100    } )( $.fn.button );
7101
7102    $.fn.buttonset = function() {
7103        if ( !$.ui.controlgroup ) {
7104            $.error( "Controlgroup widget missing" );
7105        }
7106        if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" && arguments[ 2 ] ) {
7107            return this.controlgroup.apply( this,
7108                [ arguments[ 0 ], "items.button", arguments[ 2 ] ] );
7109        }
7110        if ( arguments[ 0 ] === "option" && arguments[ 1 ] === "items" ) {
7111            return this.controlgroup.apply( this, [ arguments[ 0 ], "items.button" ] );
7112        }
7113        if ( typeof arguments[ 0 ] === "object" && arguments[ 0 ].items ) {
7114            arguments[ 0 ].items = {
7115                button: arguments[ 0 ].items
7116            };
7117        }
7118        return this.controlgroup.apply( this, arguments );
7119    };
7120}
7121
7122var widgetsButton = $.ui.button;
7123
7124
7125/* eslint-disable max-len, camelcase */
7126/*!
7127 * jQuery UI Datepicker 1.14.1
7128 * https://jqueryui.com
7129 *
7130 * Copyright OpenJS Foundation and other contributors
7131 * Released under the MIT license.
7132 * https://jquery.org/license
7133 */
7134
7135//>>label: Datepicker
7136//>>group: Widgets
7137//>>description: Displays a calendar from an input or inline for selecting dates.
7138//>>docs: https://api.jqueryui.com/datepicker/
7139//>>demos: https://jqueryui.com/datepicker/
7140//>>css.structure: ../../themes/base/core.css
7141//>>css.structure: ../../themes/base/datepicker.css
7142//>>css.theme: ../../themes/base/theme.css
7143
7144
7145$.extend( $.ui, { datepicker: { version: "1.14.1" } } );
7146
7147var datepicker_instActive;
7148
7149function datepicker_getZindex( elem ) {
7150    var position, value;
7151    while ( elem.length && elem[ 0 ] !== document ) {
7152
7153        // Ignore z-index if position is set to a value where z-index is ignored by the browser
7154        // This makes behavior of this function consistent across browsers
7155        // WebKit always returns auto if the element is positioned
7156        position = elem.css( "position" );
7157        if ( position === "absolute" || position === "relative" || position === "fixed" ) {
7158
7159            // IE returns 0 when zIndex is not specified
7160            // other browsers return a string
7161            // we ignore the case of nested elements with an explicit value of 0
7162            // <div style="z-index: -10;"><div style="z-index: 0;"></div></div>
7163            value = parseInt( elem.css( "zIndex" ), 10 );
7164            if ( !isNaN( value ) && value !== 0 ) {
7165                return value;
7166            }
7167        }
7168        elem = elem.parent();
7169    }
7170
7171    return 0;
7172}
7173
7174/* Date picker manager.
7175   Use the singleton instance of this class, $.datepicker, to interact with the date picker.
7176   Settings for (groups of) date pickers are maintained in an instance object,
7177   allowing multiple different settings on the same page. */
7178
7179function Datepicker() {
7180    this._curInst = null; // The current instance in use
7181    this._keyEvent = false; // If the last event was a key event
7182    this._disabledInputs = []; // List of date picker inputs that have been disabled
7183    this._datepickerShowing = false; // True if the popup picker is showing , false if not
7184    this._inDialog = false; // True if showing within a "dialog", false if not
7185    this._mainDivId = "ui-datepicker-div"; // The ID of the main datepicker division
7186    this._inlineClass = "ui-datepicker-inline"; // The name of the inline marker class
7187    this._appendClass = "ui-datepicker-append"; // The name of the append marker class
7188    this._triggerClass = "ui-datepicker-trigger"; // The name of the trigger marker class
7189    this._dialogClass = "ui-datepicker-dialog"; // The name of the dialog marker class
7190    this._disableClass = "ui-datepicker-disabled"; // The name of the disabled covering marker class
7191    this._unselectableClass = "ui-datepicker-unselectable"; // The name of the unselectable cell marker class
7192    this._currentClass = "ui-datepicker-current-day"; // The name of the current day marker class
7193    this._dayOverClass = "ui-datepicker-days-cell-over"; // The name of the day hover marker class
7194    this.regional = []; // Available regional settings, indexed by language code
7195    this.regional[ "" ] = { // Default regional settings
7196        closeText: "Done", // Display text for close link
7197        prevText: "Prev", // Display text for previous month link
7198        nextText: "Next", // Display text for next month link
7199        currentText: "Today", // Display text for current month link
7200        monthNames: [ "January", "February", "March", "April", "May", "June",
7201            "July", "August", "September", "October", "November", "December" ], // Names of months for drop-down and formatting
7202        monthNamesShort: [ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec" ], // For formatting
7203        dayNames: [ "Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" ], // For formatting
7204        dayNamesShort: [ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" ], // For formatting
7205        dayNamesMin: [ "Su", "Mo", "Tu", "We", "Th", "Fr", "Sa" ], // Column headings for days starting at Sunday
7206        weekHeader: "Wk", // Column header for week of the year
7207        dateFormat: "mm/dd/yy", // See format options on parseDate
7208        firstDay: 0, // The first day of the week, Sun = 0, Mon = 1, ...
7209        isRTL: false, // True if right-to-left language, false if left-to-right
7210        showMonthAfterYear: false, // True if the year select precedes month, false for month then year
7211        yearSuffix: "", // Additional text to append to the year in the month headers,
7212        selectMonthLabel: "Select month", // Invisible label for month selector
7213        selectYearLabel: "Select year" // Invisible label for year selector
7214    };
7215    this._defaults = { // Global defaults for all the date picker instances
7216        showOn: "focus", // "focus" for popup on focus,
7217            // "button" for trigger button, or "both" for either
7218        showAnim: "fadeIn", // Name of jQuery animation for popup
7219        showOptions: {}, // Options for enhanced animations
7220        defaultDate: null, // Used when field is blank: actual date,
7221            // +/-number for offset from today, null for today
7222        appendText: "", // Display text following the input box, e.g. showing the format
7223        buttonText: "...", // Text for trigger button
7224        buttonImage: "", // URL for trigger button image
7225        buttonImageOnly: false, // True if the image appears alone, false if it appears on a button
7226        hideIfNoPrevNext: false, // True to hide next/previous month links
7227            // if not applicable, false to just disable them
7228        navigationAsDateFormat: false, // True if date formatting applied to prev/today/next links
7229        gotoCurrent: false, // True if today link goes back to current selection instead
7230        changeMonth: false, // True if month can be selected directly, false if only prev/next
7231        changeYear: false, // True if year can be selected directly, false if only prev/next
7232        yearRange: "c-10:c+10", // Range of years to display in drop-down,
7233            // either relative to today's year (-nn:+nn), relative to currently displayed year
7234            // (c-nn:c+nn), absolute (nnnn:nnnn), or a combination of the above (nnnn:-n)
7235        showOtherMonths: false, // True to show dates in other months, false to leave blank
7236        selectOtherMonths: false, // True to allow selection of dates in other months, false for unselectable
7237        showWeek: false, // True to show week of the year, false to not show it
7238        calculateWeek: this.iso8601Week, // How to calculate the week of the year,
7239            // takes a Date and returns the number of the week for it
7240        shortYearCutoff: "+10", // Short year values < this are in the current century,
7241            // > this are in the previous century,
7242            // string value starting with "+" for current year + value
7243        minDate: null, // The earliest selectable date, or null for no limit
7244        maxDate: null, // The latest selectable date, or null for no limit
7245        duration: "fast", // Duration of display/closure
7246        beforeShowDay: null, // Function that takes a date and returns an array with
7247            // [0] = true if selectable, false if not, [1] = custom CSS class name(s) or "",
7248            // [2] = cell title (optional), e.g. $.datepicker.noWeekends
7249        beforeShow: null, // Function that takes an input field and
7250            // returns a set of custom settings for the date picker
7251        onSelect: null, // Define a callback function when a date is selected
7252        onChangeMonthYear: null, // Define a callback function when the month or year is changed
7253        onClose: null, // Define a callback function when the datepicker is closed
7254        onUpdateDatepicker: null, // Define a callback function when the datepicker is updated
7255        numberOfMonths: 1, // Number of months to show at a time
7256        showCurrentAtPos: 0, // The position in multipe months at which to show the current month (starting at 0)
7257        stepMonths: 1, // Number of months to step back/forward
7258        stepBigMonths: 12, // Number of months to step back/forward for the big links
7259        altField: "", // Selector for an alternate field to store selected dates into
7260        altFormat: "", // The date format to use for the alternate field
7261        constrainInput: true, // The input is constrained by the current date format
7262        showButtonPanel: false, // True to show button panel, false to not show it
7263        autoSize: false, // True to size the input for the date format, false to leave as is
7264        disabled: false // The initial disabled state
7265    };
7266    $.extend( this._defaults, this.regional[ "" ] );
7267    this.regional.en = $.extend( true, {}, this.regional[ "" ] );
7268    this.regional[ "en-US" ] = $.extend( true, {}, this.regional.en );
7269    this.dpDiv = datepicker_bindHover( $( "<div id='" + this._mainDivId + "' class='ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) );
7270}
7271
7272$.extend( Datepicker.prototype, {
7273
7274    /* Class name added to elements to indicate already configured with a date picker. */
7275    markerClassName: "hasDatepicker",
7276
7277    //Keep track of the maximum number of rows displayed (see #7043)
7278    maxRows: 4,
7279
7280    // TODO rename to "widget" when switching to widget factory
7281    _widgetDatepicker: function() {
7282        return this.dpDiv;
7283    },
7284
7285    /* Override the default settings for all instances of the date picker.
7286     * @param  settings  object - the new settings to use as defaults (anonymous object)
7287     * @return the manager object
7288     */
7289    setDefaults: function( settings ) {
7290        datepicker_extendRemove( this._defaults, settings || {} );
7291        return this;
7292    },
7293
7294    /* Attach the date picker to a jQuery selection.
7295     * @param  target   element - the target input field or division or span
7296     * @param  settings  object - the new settings to use for this date picker instance (anonymous)
7297     */
7298    _attachDatepicker: function( target, settings ) {
7299        var nodeName, inline, inst;
7300        nodeName = target.nodeName.toLowerCase();
7301        inline = ( nodeName === "div" || nodeName === "span" );
7302        if ( !target.id ) {
7303            this.uuid += 1;
7304            target.id = "dp" + this.uuid;
7305        }
7306        inst = this._newInst( $( target ), inline );
7307        inst.settings = $.extend( {}, settings || {} );
7308        if ( nodeName === "input" ) {
7309            this._connectDatepicker( target, inst );
7310        } else if ( inline ) {
7311            this._inlineDatepicker( target, inst );
7312        }
7313    },
7314
7315    /* Create a new instance object. */
7316    _newInst: function( target, inline ) {
7317        var id = target[ 0 ].id.replace( /([^A-Za-z0-9_\-])/g, "\\\\$1" ); // escape jQuery meta chars
7318        return { id: id, input: target, // associated target
7319            selectedDay: 0, selectedMonth: 0, selectedYear: 0, // current selection
7320            drawMonth: 0, drawYear: 0, // month being drawn
7321            inline: inline, // is datepicker inline or not
7322            dpDiv: ( !inline ? this.dpDiv : // presentation div
7323            datepicker_bindHover( $( "<div class='" + this._inlineClass + " ui-datepicker ui-widget ui-widget-content ui-helper-clearfix ui-corner-all'></div>" ) ) ) };
7324    },
7325
7326    /* Attach the date picker to an input field. */
7327    _connectDatepicker: function( target, inst ) {
7328        var input = $( target );
7329        inst.append = $( [] );
7330        inst.trigger = $( [] );
7331        if ( input.hasClass( this.markerClassName ) ) {
7332            return;
7333        }
7334        this._attachments( input, inst );
7335        input.addClass( this.markerClassName ).on( "keydown", this._doKeyDown ).
7336            on( "keypress", this._doKeyPress ).on( "keyup", this._doKeyUp );
7337        this._autoSize( inst );
7338        $.data( target, "datepicker", inst );
7339
7340        //If disabled option is true, disable the datepicker once it has been attached to the input (see ticket #5665)
7341        if ( inst.settings.disabled ) {
7342            this._disableDatepicker( target );
7343        }
7344    },
7345
7346    /* Make attachments based on settings. */
7347    _attachments: function( input, inst ) {
7348        var showOn, buttonText, buttonImage,
7349            appendText = this._get( inst, "appendText" ),
7350            isRTL = this._get( inst, "isRTL" );
7351
7352        if ( inst.append ) {
7353            inst.append.remove();
7354        }
7355        if ( appendText ) {
7356            inst.append = $( "<span>" )
7357                .addClass( this._appendClass )
7358                .text( appendText );
7359            input[ isRTL ? "before" : "after" ]( inst.append );
7360        }
7361
7362        input.off( "focus", this._showDatepicker );
7363
7364        if ( inst.trigger ) {
7365            inst.trigger.remove();
7366        }
7367
7368        showOn = this._get( inst, "showOn" );
7369        if ( showOn === "focus" || showOn === "both" ) { // pop-up date picker when in the marked field
7370            input.on( "focus", this._showDatepicker );
7371        }
7372        if ( showOn === "button" || showOn === "both" ) { // pop-up date picker when button clicked
7373            buttonText = this._get( inst, "buttonText" );
7374            buttonImage = this._get( inst, "buttonImage" );
7375
7376            if ( this._get( inst, "buttonImageOnly" ) ) {
7377                inst.trigger = $( "<img>" )
7378                    .addClass( this._triggerClass )
7379                    .attr( {
7380                        src: buttonImage,
7381                        alt: buttonText,
7382                        title: buttonText
7383                    } );
7384            } else {
7385                inst.trigger = $( "<button type='button'>" )
7386                    .addClass( this._triggerClass );
7387                if ( buttonImage ) {
7388                    inst.trigger.html(
7389                        $( "<img>" )
7390                            .attr( {
7391                                src: buttonImage,
7392                                alt: buttonText,
7393                                title: buttonText
7394                            } )
7395                    );
7396                } else {
7397                    inst.trigger.text( buttonText );
7398                }
7399            }
7400
7401            input[ isRTL ? "before" : "after" ]( inst.trigger );
7402            inst.trigger.on( "click", function() {
7403                if ( $.datepicker._datepickerShowing && $.datepicker._lastInput === input[ 0 ] ) {
7404                    $.datepicker._hideDatepicker();
7405                } else if ( $.datepicker._datepickerShowing && $.datepicker._lastInput !== input[ 0 ] ) {
7406                    $.datepicker._hideDatepicker();
7407                    $.datepicker._showDatepicker( input[ 0 ] );
7408                } else {
7409                    $.datepicker._showDatepicker( input[ 0 ] );
7410                }
7411                return false;
7412            } );
7413        }
7414    },
7415
7416    /* Apply the maximum length for the date format. */
7417    _autoSize: function( inst ) {
7418        if ( this._get( inst, "autoSize" ) && !inst.inline ) {
7419            var findMax, max, maxI, i,
7420                date = new Date( 2009, 12 - 1, 20 ), // Ensure double digits
7421                dateFormat = this._get( inst, "dateFormat" );
7422
7423            if ( dateFormat.match( /[DM]/ ) ) {
7424                findMax = function( names ) {
7425                    max = 0;
7426                    maxI = 0;
7427                    for ( i = 0; i < names.length; i++ ) {
7428                        if ( names[ i ].length > max ) {
7429                            max = names[ i ].length;
7430                            maxI = i;
7431                        }
7432                    }
7433                    return maxI;
7434                };
7435                date.setMonth( findMax( this._get( inst, ( dateFormat.match( /MM/ ) ?
7436                    "monthNames" : "monthNamesShort" ) ) ) );
7437                date.setDate( findMax( this._get( inst, ( dateFormat.match( /DD/ ) ?
7438                    "dayNames" : "dayNamesShort" ) ) ) + 20 - date.getDay() );
7439            }
7440            inst.input.attr( "size", this._formatDate( inst, date ).length );
7441        }
7442    },
7443
7444    /* Attach an inline date picker to a div. */
7445    _inlineDatepicker: function( target, inst ) {
7446        var divSpan = $( target );
7447        if ( divSpan.hasClass( this.markerClassName ) ) {
7448            return;
7449        }
7450        divSpan.addClass( this.markerClassName ).append( inst.dpDiv );
7451        $.data( target, "datepicker", inst );
7452        this._setDate( inst, this._getDefaultDate( inst ), true );
7453        this._updateDatepicker( inst );
7454        this._updateAlternate( inst );
7455
7456        //If disabled option is true, disable the datepicker before showing it (see ticket #5665)
7457        if ( inst.settings.disabled ) {
7458            this._disableDatepicker( target );
7459        }
7460
7461        // Set display:block in place of inst.dpDiv.show() which won't work on disconnected elements
7462        // https://bugs.jqueryui.com/ticket/7552 - A Datepicker created on a detached div has zero height
7463        inst.dpDiv.css( "display", "block" );
7464    },
7465
7466    /* Pop-up the date picker in a "dialog" box.
7467     * @param  input element - ignored
7468     * @param  date string or Date - the initial date to display
7469     * @param  onSelect  function - the function to call when a date is selected
7470     * @param  settings  object - update the dialog date picker instance's settings (anonymous object)
7471     * @param  pos int[2] - coordinates for the dialog's position within the screen or
7472     *                  event - with x/y coordinates or
7473     *                  leave empty for default (screen centre)
7474     * @return the manager object
7475     */
7476    _dialogDatepicker: function( input, date, onSelect, settings, pos ) {
7477        var id, browserWidth, browserHeight, scrollX, scrollY,
7478            inst = this._dialogInst; // internal instance
7479
7480        if ( !inst ) {
7481            this.uuid += 1;
7482            id = "dp" + this.uuid;
7483            this._dialogInput = $( "<input type='text' id='" + id +
7484                "' style='position: absolute; top: -100px; width: 0px;'/>" );
7485            this._dialogInput.on( "keydown", this._doKeyDown );
7486            $( "body" ).append( this._dialogInput );
7487            inst = this._dialogInst = this._newInst( this._dialogInput, false );
7488            inst.settings = {};
7489            $.data( this._dialogInput[ 0 ], "datepicker", inst );
7490        }
7491        datepicker_extendRemove( inst.settings, settings || {} );
7492        date = ( date && date.constructor === Date ? this._formatDate( inst, date ) : date );
7493        this._dialogInput.val( date );
7494
7495        this._pos = ( pos ? ( pos.length ? pos : [ pos.pageX, pos.pageY ] ) : null );
7496        if ( !this._pos ) {
7497            browserWidth = document.documentElement.clientWidth;
7498            browserHeight = document.documentElement.clientHeight;
7499            scrollX = document.documentElement.scrollLeft || document.body.scrollLeft;
7500            scrollY = document.documentElement.scrollTop || document.body.scrollTop;
7501            this._pos = // should use actual width/height below
7502                [ ( browserWidth / 2 ) - 100 + scrollX, ( browserHeight / 2 ) - 150 + scrollY ];
7503        }
7504
7505        // Move input on screen for focus, but hidden behind dialog
7506        this._dialogInput.css( "left", ( this._pos[ 0 ] + 20 ) + "px" ).css( "top", this._pos[ 1 ] + "px" );
7507        inst.settings.onSelect = onSelect;
7508        this._inDialog = true;
7509        this.dpDiv.addClass( this._dialogClass );
7510        this._showDatepicker( this._dialogInput[ 0 ] );
7511        if ( $.blockUI ) {
7512            $.blockUI( this.dpDiv );
7513        }
7514        $.data( this._dialogInput[ 0 ], "datepicker", inst );
7515        return this;
7516    },
7517
7518    /* Detach a datepicker from its control.
7519     * @param  target   element - the target input field or division or span
7520     */
7521    _destroyDatepicker: function( target ) {
7522        var nodeName,
7523            $target = $( target ),
7524            inst = $.data( target, "datepicker" );
7525
7526        if ( !$target.hasClass( this.markerClassName ) ) {
7527            return;
7528        }
7529
7530        nodeName = target.nodeName.toLowerCase();
7531        $.removeData( target, "datepicker" );
7532        if ( nodeName === "input" ) {
7533            inst.append.remove();
7534            inst.trigger.remove();
7535            $target.removeClass( this.markerClassName ).
7536                off( "focus", this._showDatepicker ).
7537                off( "keydown", this._doKeyDown ).
7538                off( "keypress", this._doKeyPress ).
7539                off( "keyup", this._doKeyUp );
7540        } else if ( nodeName === "div" || nodeName === "span" ) {
7541            $target.removeClass( this.markerClassName ).empty();
7542        }
7543
7544        $.datepicker._hideDatepicker();
7545        if ( datepicker_instActive === inst ) {
7546            datepicker_instActive = null;
7547            this._curInst = null;
7548        }
7549    },
7550
7551    /* Enable the date picker to a jQuery selection.
7552     * @param  target   element - the target input field or division or span
7553     */
7554    _enableDatepicker: function( target ) {
7555        var nodeName, inline,
7556            $target = $( target ),
7557            inst = $.data( target, "datepicker" );
7558
7559        if ( !$target.hasClass( this.markerClassName ) ) {
7560            return;
7561        }
7562
7563        nodeName = target.nodeName.toLowerCase();
7564        if ( nodeName === "input" ) {
7565            target.disabled = false;
7566            inst.trigger.filter( "button" ).
7567                each( function() {
7568                    this.disabled = false;
7569                } ).end().
7570                filter( "img" ).css( { opacity: "1.0", cursor: "" } );
7571        } else if ( nodeName === "div" || nodeName === "span" ) {
7572            inline = $target.children( "." + this._inlineClass );
7573            inline.children().removeClass( "ui-state-disabled" );
7574            inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7575                prop( "disabled", false );
7576        }
7577        this._disabledInputs = $.map( this._disabledInputs,
7578
7579            // Delete entry
7580            function( value ) {
7581                return ( value === target ? null : value );
7582            } );
7583    },
7584
7585    /* Disable the date picker to a jQuery selection.
7586     * @param  target   element - the target input field or division or span
7587     */
7588    _disableDatepicker: function( target ) {
7589        var nodeName, inline,
7590            $target = $( target ),
7591            inst = $.data( target, "datepicker" );
7592
7593        if ( !$target.hasClass( this.markerClassName ) ) {
7594            return;
7595        }
7596
7597        nodeName = target.nodeName.toLowerCase();
7598        if ( nodeName === "input" ) {
7599            target.disabled = true;
7600            inst.trigger.filter( "button" ).
7601                each( function() {
7602                    this.disabled = true;
7603                } ).end().
7604                filter( "img" ).css( { opacity: "0.5", cursor: "default" } );
7605        } else if ( nodeName === "div" || nodeName === "span" ) {
7606            inline = $target.children( "." + this._inlineClass );
7607            inline.children().addClass( "ui-state-disabled" );
7608            inline.find( "select.ui-datepicker-month, select.ui-datepicker-year" ).
7609                prop( "disabled", true );
7610        }
7611        this._disabledInputs = $.map( this._disabledInputs,
7612
7613            // Delete entry
7614            function( value ) {
7615                return ( value === target ? null : value );
7616            } );
7617        this._disabledInputs[ this._disabledInputs.length ] = target;
7618    },
7619
7620    /* Is the first field in a jQuery collection disabled as a datepicker?
7621     * @param  target   element - the target input field or division or span
7622     * @return boolean - true if disabled, false if enabled
7623     */
7624    _isDisabledDatepicker: function( target ) {
7625        if ( !target ) {
7626            return false;
7627        }
7628        for ( var i = 0; i < this._disabledInputs.length; i++ ) {
7629            if ( this._disabledInputs[ i ] === target ) {
7630                return true;
7631            }
7632        }
7633        return false;
7634    },
7635
7636    /* Retrieve the instance data for the target control.
7637     * @param  target  element - the target input field or division or span
7638     * @return  object - the associated instance data
7639     * @throws  error if a jQuery problem getting data
7640     */
7641    _getInst: function( target ) {
7642        try {
7643            return $.data( target, "datepicker" );
7644        } catch ( err ) {
7645            throw "Missing instance data for this datepicker";
7646        }
7647    },
7648
7649    /* Update or retrieve the settings for a date picker attached to an input field or division.
7650     * @param  target  element - the target input field or division or span
7651     * @param  name object - the new settings to update or
7652     *              string - the name of the setting to change or retrieve,
7653     *              when retrieving also "all" for all instance settings or
7654     *              "defaults" for all global defaults
7655     * @param  value   any - the new value for the setting
7656     *              (omit if above is an object or to retrieve a value)
7657     */
7658    _optionDatepicker: function( target, name, value ) {
7659        var settings, date, minDate, maxDate,
7660            inst = this._getInst( target );
7661
7662        if ( arguments.length === 2 && typeof name === "string" ) {
7663            return ( name === "defaults" ? $.extend( {}, $.datepicker._defaults ) :
7664                ( inst ? ( name === "all" ? $.extend( {}, inst.settings ) :
7665                this._get( inst, name ) ) : null ) );
7666        }
7667
7668        settings = name || {};
7669        if ( typeof name === "string" ) {
7670            settings = {};
7671            settings[ name ] = value;
7672        }
7673
7674        if ( inst ) {
7675            if ( this._curInst === inst ) {
7676                this._hideDatepicker();
7677            }
7678
7679            date = this._getDateDatepicker( target, true );
7680            minDate = this._getMinMaxDate( inst, "min" );
7681            maxDate = this._getMinMaxDate( inst, "max" );
7682            datepicker_extendRemove( inst.settings, settings );
7683
7684            // reformat the old minDate/maxDate values if dateFormat changes and a new minDate/maxDate isn't provided
7685            if ( minDate !== null && settings.dateFormat !== undefined && settings.minDate === undefined ) {
7686                inst.settings.minDate = this._formatDate( inst, minDate );
7687            }
7688            if ( maxDate !== null && settings.dateFormat !== undefined && settings.maxDate === undefined ) {
7689                inst.settings.maxDate = this._formatDate( inst, maxDate );
7690            }
7691            if ( "disabled" in settings ) {
7692                if ( settings.disabled ) {
7693                    this._disableDatepicker( target );
7694                } else {
7695                    this._enableDatepicker( target );
7696                }
7697            }
7698            this._attachments( $( target ), inst );
7699            this._autoSize( inst );
7700            this._setDate( inst, date );
7701            this._updateAlternate( inst );
7702            this._updateDatepicker( inst );
7703        }
7704    },
7705
7706    // Change method deprecated
7707    _changeDatepicker: function( target, name, value ) {
7708        this._optionDatepicker( target, name, value );
7709    },
7710
7711    /* Redraw the date picker attached to an input field or division.
7712     * @param  target  element - the target input field or division or span
7713     */
7714    _refreshDatepicker: function( target ) {
7715        var inst = this._getInst( target );
7716        if ( inst ) {
7717            this._updateDatepicker( inst );
7718        }
7719    },
7720
7721    /* Set the dates for a jQuery selection.
7722     * @param  target element - the target input field or division or span
7723     * @param  date Date - the new date
7724     */
7725    _setDateDatepicker: function( target, date ) {
7726        var inst = this._getInst( target );
7727        if ( inst ) {
7728            this._setDate( inst, date );
7729            this._updateDatepicker( inst );
7730            this._updateAlternate( inst );
7731        }
7732    },
7733
7734    /* Get the date(s) for the first entry in a jQuery selection.
7735     * @param  target element - the target input field or division or span
7736     * @param  noDefault boolean - true if no default date is to be used
7737     * @return Date - the current date
7738     */
7739    _getDateDatepicker: function( target, noDefault ) {
7740        var inst = this._getInst( target );
7741        if ( inst && !inst.inline ) {
7742            this._setDateFromField( inst, noDefault );
7743        }
7744        return ( inst ? this._getDate( inst ) : null );
7745    },
7746
7747    /* Handle keystrokes. */
7748    _doKeyDown: function( event ) {
7749        var onSelect, dateStr, sel,
7750            inst = $.datepicker._getInst( event.target ),
7751            handled = true,
7752            isRTL = inst.dpDiv.is( ".ui-datepicker-rtl" );
7753
7754        inst._keyEvent = true;
7755        if ( $.datepicker._datepickerShowing ) {
7756            switch ( event.keyCode ) {
7757                case 9: $.datepicker._hideDatepicker();
7758                        handled = false;
7759                        break; // hide on tab out
7760                case 13: sel = $( "td." + $.datepicker._dayOverClass + ":not(." +
7761                                    $.datepicker._currentClass + ")", inst.dpDiv );
7762                        if ( sel[ 0 ] ) {
7763                            $.datepicker._selectDay( event.target, inst.selectedMonth, inst.selectedYear, sel[ 0 ] );
7764                        }
7765
7766                        onSelect = $.datepicker._get( inst, "onSelect" );
7767                        if ( onSelect ) {
7768                            dateStr = $.datepicker._formatDate( inst );
7769
7770                            // Trigger custom callback
7771                            onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );
7772                        } else {
7773                            $.datepicker._hideDatepicker();
7774                        }
7775
7776                        return false; // don't submit the form
7777                case 27: $.datepicker._hideDatepicker();
7778                        break; // hide on escape
7779                case 33: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7780                            -$.datepicker._get( inst, "stepBigMonths" ) :
7781                            -$.datepicker._get( inst, "stepMonths" ) ), "M" );
7782                        break; // previous month/year on page up/+ ctrl
7783                case 34: $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7784                            +$.datepicker._get( inst, "stepBigMonths" ) :
7785                            +$.datepicker._get( inst, "stepMonths" ) ), "M" );
7786                        break; // next month/year on page down/+ ctrl
7787                case 35: if ( event.ctrlKey || event.metaKey ) {
7788                            $.datepicker._clearDate( event.target );
7789                        }
7790                        handled = event.ctrlKey || event.metaKey;
7791                        break; // clear on ctrl or command +end
7792                case 36: if ( event.ctrlKey || event.metaKey ) {
7793                            $.datepicker._gotoToday( event.target );
7794                        }
7795                        handled = event.ctrlKey || event.metaKey;
7796                        break; // current on ctrl or command +home
7797                case 37: if ( event.ctrlKey || event.metaKey ) {
7798                            $.datepicker._adjustDate( event.target, ( isRTL ? +1 : -1 ), "D" );
7799                        }
7800                        handled = event.ctrlKey || event.metaKey;
7801
7802                        // -1 day on ctrl or command +left
7803                        if ( event.originalEvent.altKey ) {
7804                            $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7805                                -$.datepicker._get( inst, "stepBigMonths" ) :
7806                                -$.datepicker._get( inst, "stepMonths" ) ), "M" );
7807                        }
7808
7809                        // next month/year on alt +left on Mac
7810                        break;
7811                case 38: if ( event.ctrlKey || event.metaKey ) {
7812                            $.datepicker._adjustDate( event.target, -7, "D" );
7813                        }
7814                        handled = event.ctrlKey || event.metaKey;
7815                        break; // -1 week on ctrl or command +up
7816                case 39: if ( event.ctrlKey || event.metaKey ) {
7817                            $.datepicker._adjustDate( event.target, ( isRTL ? -1 : +1 ), "D" );
7818                        }
7819                        handled = event.ctrlKey || event.metaKey;
7820
7821                        // +1 day on ctrl or command +right
7822                        if ( event.originalEvent.altKey ) {
7823                            $.datepicker._adjustDate( event.target, ( event.ctrlKey ?
7824                                +$.datepicker._get( inst, "stepBigMonths" ) :
7825                                +$.datepicker._get( inst, "stepMonths" ) ), "M" );
7826                        }
7827
7828                        // next month/year on alt +right
7829                        break;
7830                case 40: if ( event.ctrlKey || event.metaKey ) {
7831                            $.datepicker._adjustDate( event.target, +7, "D" );
7832                        }
7833                        handled = event.ctrlKey || event.metaKey;
7834                        break; // +1 week on ctrl or command +down
7835                default: handled = false;
7836            }
7837        } else if ( event.keyCode === 36 && event.ctrlKey ) { // display the date picker on ctrl+home
7838            $.datepicker._showDatepicker( this );
7839        } else {
7840            handled = false;
7841        }
7842
7843        if ( handled ) {
7844            event.preventDefault();
7845            event.stopPropagation();
7846        }
7847    },
7848
7849    /* Filter entered characters - based on date format. */
7850    _doKeyPress: function( event ) {
7851        var chars, chr,
7852            inst = $.datepicker._getInst( event.target );
7853
7854        if ( $.datepicker._get( inst, "constrainInput" ) ) {
7855            chars = $.datepicker._possibleChars( $.datepicker._get( inst, "dateFormat" ) );
7856            chr = String.fromCharCode( event.charCode == null ? event.keyCode : event.charCode );
7857            return event.ctrlKey || event.metaKey || ( chr < " " || !chars || chars.indexOf( chr ) > -1 );
7858        }
7859    },
7860
7861    /* Synchronise manual entry and field/alternate field. */
7862    _doKeyUp: function( event ) {
7863        var date,
7864            inst = $.datepicker._getInst( event.target );
7865
7866        if ( inst.input.val() !== inst.lastVal ) {
7867            try {
7868                date = $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
7869                    ( inst.input ? inst.input.val() : null ),
7870                    $.datepicker._getFormatConfig( inst ) );
7871
7872                if ( date ) { // only if valid
7873                    $.datepicker._setDateFromField( inst );
7874                    $.datepicker._updateAlternate( inst );
7875                    $.datepicker._updateDatepicker( inst );
7876                }
7877            } catch ( err ) {
7878            }
7879        }
7880        return true;
7881    },
7882
7883    /* Pop-up the date picker for a given input field.
7884     * If false returned from beforeShow event handler do not show.
7885     * @param  input  element - the input field attached to the date picker or
7886     *                  event - if triggered by focus
7887     */
7888    _showDatepicker: function( input ) {
7889        input = input.target || input;
7890        if ( input.nodeName.toLowerCase() !== "input" ) { // find from button/image trigger
7891            input = $( "input", input.parentNode )[ 0 ];
7892        }
7893
7894        if ( $.datepicker._isDisabledDatepicker( input ) || $.datepicker._lastInput === input ) { // already here
7895            return;
7896        }
7897
7898        var inst, beforeShow, beforeShowSettings, isFixed,
7899            offset, showAnim, duration;
7900
7901        inst = $.datepicker._getInst( input );
7902        if ( $.datepicker._curInst && $.datepicker._curInst !== inst ) {
7903            $.datepicker._curInst.dpDiv.stop( true, true );
7904            if ( inst && $.datepicker._datepickerShowing ) {
7905                $.datepicker._hideDatepicker( $.datepicker._curInst.input[ 0 ] );
7906            }
7907        }
7908
7909        beforeShow = $.datepicker._get( inst, "beforeShow" );
7910        beforeShowSettings = beforeShow ? beforeShow.apply( input, [ input, inst ] ) : {};
7911        if ( beforeShowSettings === false ) {
7912            return;
7913        }
7914        datepicker_extendRemove( inst.settings, beforeShowSettings );
7915
7916        inst.lastVal = null;
7917        $.datepicker._lastInput = input;
7918        $.datepicker._setDateFromField( inst );
7919
7920        if ( $.datepicker._inDialog ) { // hide cursor
7921            input.value = "";
7922        }
7923        if ( !$.datepicker._pos ) { // position below input
7924            $.datepicker._pos = $.datepicker._findPos( input );
7925            $.datepicker._pos[ 1 ] += input.offsetHeight; // add the height
7926        }
7927
7928        isFixed = false;
7929        $( input ).parents().each( function() {
7930            isFixed |= $( this ).css( "position" ) === "fixed";
7931            return !isFixed;
7932        } );
7933
7934        offset = { left: $.datepicker._pos[ 0 ], top: $.datepicker._pos[ 1 ] };
7935        $.datepicker._pos = null;
7936
7937        //to avoid flashes on Firefox
7938        inst.dpDiv.empty();
7939
7940        // determine sizing offscreen
7941        inst.dpDiv.css( { position: "absolute", display: "block", top: "-1000px" } );
7942        $.datepicker._updateDatepicker( inst );
7943
7944        // fix width for dynamic number of date pickers
7945        // and adjust position before showing
7946        offset = $.datepicker._checkOffset( inst, offset, isFixed );
7947        inst.dpDiv.css( { position: ( $.datepicker._inDialog && $.blockUI ?
7948            "static" : ( isFixed ? "fixed" : "absolute" ) ), display: "none",
7949            left: offset.left + "px", top: offset.top + "px" } );
7950
7951        if ( !inst.inline ) {
7952            showAnim = $.datepicker._get( inst, "showAnim" );
7953            duration = $.datepicker._get( inst, "duration" );
7954            inst.dpDiv.css( "z-index", datepicker_getZindex( $( input ) ) + 1 );
7955            $.datepicker._datepickerShowing = true;
7956
7957            if ( $.effects && $.effects.effect[ showAnim ] ) {
7958                inst.dpDiv.show( showAnim, $.datepicker._get( inst, "showOptions" ), duration );
7959            } else {
7960                inst.dpDiv[ showAnim || "show" ]( showAnim ? duration : null );
7961            }
7962
7963            if ( $.datepicker._shouldFocusInput( inst ) ) {
7964                inst.input.trigger( "focus" );
7965            }
7966
7967            $.datepicker._curInst = inst;
7968        }
7969    },
7970
7971    /* Generate the date picker content. */
7972    _updateDatepicker: function( inst ) {
7973        this.maxRows = 4; //Reset the max number of rows being displayed (see #7043)
7974        datepicker_instActive = inst; // for delegate hover events
7975        inst.dpDiv.empty().append( this._generateHTML( inst ) );
7976        this._attachHandlers( inst );
7977
7978        var origyearshtml,
7979            numMonths = this._getNumberOfMonths( inst ),
7980            cols = numMonths[ 1 ],
7981            width = 17,
7982            activeCell = inst.dpDiv.find( "." + this._dayOverClass + " a" ),
7983            onUpdateDatepicker = $.datepicker._get( inst, "onUpdateDatepicker" );
7984
7985        if ( activeCell.length > 0 ) {
7986            datepicker_handleMouseover.apply( activeCell.get( 0 ) );
7987        }
7988
7989        inst.dpDiv.removeClass( "ui-datepicker-multi-2 ui-datepicker-multi-3 ui-datepicker-multi-4" ).width( "" );
7990        if ( cols > 1 ) {
7991            inst.dpDiv.addClass( "ui-datepicker-multi-" + cols ).css( "width", ( width * cols ) + "em" );
7992        }
7993        inst.dpDiv[ ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ? "add" : "remove" ) +
7994            "Class" ]( "ui-datepicker-multi" );
7995        inst.dpDiv[ ( this._get( inst, "isRTL" ) ? "add" : "remove" ) +
7996            "Class" ]( "ui-datepicker-rtl" );
7997
7998        if ( inst === $.datepicker._curInst && $.datepicker._datepickerShowing && $.datepicker._shouldFocusInput( inst ) ) {
7999            inst.input.trigger( "focus" );
8000        }
8001
8002        // Deffered render of the years select (to avoid flashes on Firefox)
8003        if ( inst.yearshtml ) {
8004            origyearshtml = inst.yearshtml;
8005            setTimeout( function() {
8006
8007                //assure that inst.yearshtml didn't change.
8008                if ( origyearshtml === inst.yearshtml && inst.yearshtml ) {
8009                    inst.dpDiv.find( "select.ui-datepicker-year" ).first().replaceWith( inst.yearshtml );
8010                }
8011                origyearshtml = inst.yearshtml = null;
8012            }, 0 );
8013        }
8014
8015        if ( onUpdateDatepicker ) {
8016            onUpdateDatepicker.apply( ( inst.input ? inst.input[ 0 ] : null ), [ inst ] );
8017        }
8018    },
8019
8020    _shouldFocusInput: function( inst ) {
8021        return inst.input && inst.input.is( ":visible" ) && !inst.input.is( ":disabled" );
8022    },
8023
8024    /* Check positioning to remain on screen. */
8025    _checkOffset: function( inst, offset, isFixed ) {
8026        var dpWidth = inst.dpDiv.outerWidth(),
8027            dpHeight = inst.dpDiv.outerHeight(),
8028            inputWidth = inst.input ? inst.input.outerWidth() : 0,
8029            inputHeight = inst.input ? inst.input.outerHeight() : 0,
8030            viewWidth = document.documentElement.clientWidth + ( isFixed ? 0 : $( document ).scrollLeft() ),
8031            viewHeight = document.documentElement.clientHeight + ( isFixed ? 0 : $( document ).scrollTop() );
8032
8033        offset.left -= ( this._get( inst, "isRTL" ) ? ( dpWidth - inputWidth ) : 0 );
8034        offset.left -= ( isFixed && offset.left === inst.input.offset().left ) ? $( document ).scrollLeft() : 0;
8035        offset.top -= ( isFixed && offset.top === ( inst.input.offset().top + inputHeight ) ) ? $( document ).scrollTop() : 0;
8036
8037        // Now check if datepicker is showing outside window viewport - move to a better place if so.
8038        offset.left -= Math.min( offset.left, ( offset.left + dpWidth > viewWidth && viewWidth > dpWidth ) ?
8039            Math.abs( offset.left + dpWidth - viewWidth ) : 0 );
8040        offset.top -= Math.min( offset.top, ( offset.top + dpHeight > viewHeight && viewHeight > dpHeight ) ?
8041            Math.abs( dpHeight + inputHeight ) : 0 );
8042
8043        return offset;
8044    },
8045
8046    /* Find an object's position on the screen. */
8047    _findPos: function( obj ) {
8048        var position,
8049            inst = this._getInst( obj ),
8050            isRTL = this._get( inst, "isRTL" );
8051
8052        while ( obj && ( obj.type === "hidden" || obj.nodeType !== 1 || $.expr.pseudos.hidden( obj ) ) ) {
8053            obj = obj[ isRTL ? "previousSibling" : "nextSibling" ];
8054        }
8055
8056        position = $( obj ).offset();
8057        return [ position.left, position.top ];
8058    },
8059
8060    /* Hide the date picker from view.
8061     * @param  input  element - the input field attached to the date picker
8062     */
8063    _hideDatepicker: function( input ) {
8064        var showAnim, duration, postProcess, onClose,
8065            inst = this._curInst;
8066
8067        if ( !inst || ( input && inst !== $.data( input, "datepicker" ) ) ) {
8068            return;
8069        }
8070
8071        if ( this._datepickerShowing ) {
8072            showAnim = this._get( inst, "showAnim" );
8073            duration = this._get( inst, "duration" );
8074            postProcess = function() {
8075                $.datepicker._tidyDialog( inst );
8076            };
8077
8078            if ( $.effects && ( $.effects.effect[ showAnim ] ) ) {
8079                inst.dpDiv.hide( showAnim, $.datepicker._get( inst, "showOptions" ), duration, postProcess );
8080            } else {
8081                inst.dpDiv[ ( showAnim === "slideDown" ? "slideUp" :
8082                    ( showAnim === "fadeIn" ? "fadeOut" : "hide" ) ) ]( ( showAnim ? duration : null ), postProcess );
8083            }
8084
8085            if ( !showAnim ) {
8086                postProcess();
8087            }
8088            this._datepickerShowing = false;
8089
8090            onClose = this._get( inst, "onClose" );
8091            if ( onClose ) {
8092                onClose.apply( ( inst.input ? inst.input[ 0 ] : null ), [ ( inst.input ? inst.input.val() : "" ), inst ] );
8093            }
8094
8095            this._lastInput = null;
8096            if ( this._inDialog ) {
8097                this._dialogInput.css( { position: "absolute", left: "0", top: "-100px" } );
8098                if ( $.blockUI ) {
8099                    $.unblockUI();
8100                    $( "body" ).append( this.dpDiv );
8101                }
8102            }
8103            this._inDialog = false;
8104        }
8105    },
8106
8107    /* Tidy up after a dialog display. */
8108    _tidyDialog: function( inst ) {
8109        inst.dpDiv.removeClass( this._dialogClass ).off( ".ui-datepicker-calendar" );
8110    },
8111
8112    /* Close date picker if clicked elsewhere. */
8113    _checkExternalClick: function( event ) {
8114        if ( !$.datepicker._curInst ) {
8115            return;
8116        }
8117
8118        var $target = $( event.target ),
8119            inst = $.datepicker._getInst( $target[ 0 ] );
8120
8121        if ( ( ( $target[ 0 ].id !== $.datepicker._mainDivId &&
8122                $target.parents( "#" + $.datepicker._mainDivId ).length === 0 &&
8123                !$target.hasClass( $.datepicker.markerClassName ) &&
8124                !$target.closest( "." + $.datepicker._triggerClass ).length &&
8125                $.datepicker._datepickerShowing && !( $.datepicker._inDialog && $.blockUI ) ) ) ||
8126            ( $target.hasClass( $.datepicker.markerClassName ) && $.datepicker._curInst !== inst ) ) {
8127                $.datepicker._hideDatepicker();
8128        }
8129    },
8130
8131    /* Adjust one of the date sub-fields. */
8132    _adjustDate: function( id, offset, period ) {
8133        var target = $( id ),
8134            inst = this._getInst( target[ 0 ] );
8135
8136        if ( this._isDisabledDatepicker( target[ 0 ] ) ) {
8137            return;
8138        }
8139        this._adjustInstDate( inst, offset, period );
8140        this._updateDatepicker( inst );
8141    },
8142
8143    /* Action for current link. */
8144    _gotoToday: function( id ) {
8145        var date,
8146            target = $( id ),
8147            inst = this._getInst( target[ 0 ] );
8148
8149        if ( this._get( inst, "gotoCurrent" ) && inst.currentDay ) {
8150            inst.selectedDay = inst.currentDay;
8151            inst.drawMonth = inst.selectedMonth = inst.currentMonth;
8152            inst.drawYear = inst.selectedYear = inst.currentYear;
8153        } else {
8154            date = new Date();
8155            inst.selectedDay = date.getDate();
8156            inst.drawMonth = inst.selectedMonth = date.getMonth();
8157            inst.drawYear = inst.selectedYear = date.getFullYear();
8158        }
8159        this._notifyChange( inst );
8160        this._adjustDate( target );
8161    },
8162
8163    /* Action for selecting a new month/year. */
8164    _selectMonthYear: function( id, select, period ) {
8165        var target = $( id ),
8166            inst = this._getInst( target[ 0 ] );
8167
8168        inst[ "selected" + ( period === "M" ? "Month" : "Year" ) ] =
8169        inst[ "draw" + ( period === "M" ? "Month" : "Year" ) ] =
8170            parseInt( select.options[ select.selectedIndex ].value, 10 );
8171
8172        this._notifyChange( inst );
8173        this._adjustDate( target );
8174    },
8175
8176    /* Action for selecting a day. */
8177    _selectDay: function( id, month, year, td ) {
8178        var inst,
8179            target = $( id );
8180
8181        if ( $( td ).hasClass( this._unselectableClass ) || this._isDisabledDatepicker( target[ 0 ] ) ) {
8182            return;
8183        }
8184
8185        inst = this._getInst( target[ 0 ] );
8186        inst.selectedDay = inst.currentDay = parseInt( $( "a", td ).attr( "data-date" ) );
8187        inst.selectedMonth = inst.currentMonth = month;
8188        inst.selectedYear = inst.currentYear = year;
8189        this._selectDate( id, this._formatDate( inst,
8190            inst.currentDay, inst.currentMonth, inst.currentYear ) );
8191    },
8192
8193    /* Erase the input field and hide the date picker. */
8194    _clearDate: function( id ) {
8195        var target = $( id );
8196        this._selectDate( target, "" );
8197    },
8198
8199    /* Update the input field with the selected date. */
8200    _selectDate: function( id, dateStr ) {
8201        var onSelect,
8202            target = $( id ),
8203            inst = this._getInst( target[ 0 ] );
8204
8205        dateStr = ( dateStr != null ? dateStr : this._formatDate( inst ) );
8206        if ( inst.input ) {
8207            inst.input.val( dateStr );
8208        }
8209        this._updateAlternate( inst );
8210
8211        onSelect = this._get( inst, "onSelect" );
8212        if ( onSelect ) {
8213            onSelect.apply( ( inst.input ? inst.input[ 0 ] : null ), [ dateStr, inst ] );  // trigger custom callback
8214        } else if ( inst.input ) {
8215            inst.input.trigger( "change" ); // fire the change event
8216        }
8217
8218        if ( inst.inline ) {
8219            this._updateDatepicker( inst );
8220        } else {
8221            this._hideDatepicker();
8222            this._lastInput = inst.input[ 0 ];
8223            if ( typeof( inst.input[ 0 ] ) !== "object" ) {
8224                inst.input.trigger( "focus" ); // restore focus
8225            }
8226            this._lastInput = null;
8227        }
8228    },
8229
8230    /* Update any alternate field to synchronise with the main field. */
8231    _updateAlternate: function( inst ) {
8232        var altFormat, date, dateStr,
8233            altField = this._get( inst, "altField" );
8234
8235        if ( altField ) { // update alternate field too
8236            altFormat = this._get( inst, "altFormat" ) || this._get( inst, "dateFormat" );
8237            date = this._getDate( inst );
8238            dateStr = this.formatDate( altFormat, date, this._getFormatConfig( inst ) );
8239            $( document ).find( altField ).val( dateStr );
8240        }
8241    },
8242
8243    /* Set as beforeShowDay function to prevent selection of weekends.
8244     * @param  date  Date - the date to customise
8245     * @return [boolean, string] - is this date selectable?, what is its CSS class?
8246     */
8247    noWeekends: function( date ) {
8248        var day = date.getDay();
8249        return [ ( day > 0 && day < 6 ), "" ];
8250    },
8251
8252    /* Set as calculateWeek to determine the week of the year based on the ISO 8601 definition.
8253     * @param  date  Date - the date to get the week for
8254     * @return  number - the number of the week within the year that contains this date
8255     */
8256    iso8601Week: function( date ) {
8257        var time,
8258            checkDate = new Date( date.getTime() );
8259
8260        // Find Thursday of this week starting on Monday
8261        checkDate.setDate( checkDate.getDate() + 4 - ( checkDate.getDay() || 7 ) );
8262
8263        time = checkDate.getTime();
8264        checkDate.setMonth( 0 ); // Compare with Jan 1
8265        checkDate.setDate( 1 );
8266        return Math.floor( Math.round( ( time - checkDate ) / 86400000 ) / 7 ) + 1;
8267    },
8268
8269    /* Parse a string value into a date object.
8270     * See formatDate below for the possible formats.
8271     *
8272     * @param  format string - the expected format of the date
8273     * @param  value string - the date in the above format
8274     * @param  settings Object - attributes include:
8275     *                  shortYearCutoff  number - the cutoff year for determining the century (optional)
8276     *                  dayNamesShort   string[7] - abbreviated names of the days from Sunday (optional)
8277     *                  dayNames        string[7] - names of the days from Sunday (optional)
8278     *                  monthNamesShort string[12] - abbreviated names of the months (optional)
8279     *                  monthNames      string[12] - names of the months (optional)
8280     * @return  Date - the extracted date value or null if value is blank
8281     */
8282    parseDate: function( format, value, settings ) {
8283        if ( format == null || value == null ) {
8284            throw "Invalid arguments";
8285        }
8286
8287        value = ( typeof value === "object" ? value.toString() : value + "" );
8288        if ( value === "" ) {
8289            return null;
8290        }
8291
8292        var iFormat, dim, extra,
8293            iValue = 0,
8294            shortYearCutoffTemp = ( settings ? settings.shortYearCutoff : null ) || this._defaults.shortYearCutoff,
8295            shortYearCutoff = ( typeof shortYearCutoffTemp !== "string" ? shortYearCutoffTemp :
8296                new Date().getFullYear() % 100 + parseInt( shortYearCutoffTemp, 10 ) ),
8297            dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8298            dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8299            monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8300            monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8301            year = -1,
8302            month = -1,
8303            day = -1,
8304            doy = -1,
8305            literal = false,
8306            date,
8307
8308            // Check whether a format character is doubled
8309            lookAhead = function( match ) {
8310                var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8311                if ( matches ) {
8312                    iFormat++;
8313                }
8314                return matches;
8315            },
8316
8317            // Extract a number from the string value
8318            getNumber = function( match ) {
8319                var isDoubled = lookAhead( match ),
8320                    size = ( match === "@" ? 14 : ( match === "!" ? 20 :
8321                    ( match === "y" && isDoubled ? 4 : ( match === "o" ? 3 : 2 ) ) ) ),
8322                    minSize = ( match === "y" ? size : 1 ),
8323                    digits = new RegExp( "^\\d{" + minSize + "," + size + "}" ),
8324                    num = value.substring( iValue ).match( digits );
8325                if ( !num ) {
8326                    throw "Missing number at position " + iValue;
8327                }
8328                iValue += num[ 0 ].length;
8329                return parseInt( num[ 0 ], 10 );
8330            },
8331
8332            // Extract a name from the string value and convert to an index
8333            getName = function( match, shortNames, longNames ) {
8334                var index = -1,
8335                    names = $.map( lookAhead( match ) ? longNames : shortNames, function( v, k ) {
8336                        return [ [ k, v ] ];
8337                    } ).sort( function( a, b ) {
8338                        return -( a[ 1 ].length - b[ 1 ].length );
8339                    } );
8340
8341                $.each( names, function( i, pair ) {
8342                    var name = pair[ 1 ];
8343                    if ( value.substr( iValue, name.length ).toLowerCase() === name.toLowerCase() ) {
8344                        index = pair[ 0 ];
8345                        iValue += name.length;
8346                        return false;
8347                    }
8348                } );
8349                if ( index !== -1 ) {
8350                    return index + 1;
8351                } else {
8352                    throw "Unknown name at position " + iValue;
8353                }
8354            },
8355
8356            // Confirm that a literal character matches the string value
8357            checkLiteral = function() {
8358                if ( value.charAt( iValue ) !== format.charAt( iFormat ) ) {
8359                    throw "Unexpected literal at position " + iValue;
8360                }
8361                iValue++;
8362            };
8363
8364        for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8365            if ( literal ) {
8366                if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8367                    literal = false;
8368                } else {
8369                    checkLiteral();
8370                }
8371            } else {
8372                switch ( format.charAt( iFormat ) ) {
8373                    case "d":
8374                        day = getNumber( "d" );
8375                        break;
8376                    case "D":
8377                        getName( "D", dayNamesShort, dayNames );
8378                        break;
8379                    case "o":
8380                        doy = getNumber( "o" );
8381                        break;
8382                    case "m":
8383                        month = getNumber( "m" );
8384                        break;
8385                    case "M":
8386                        month = getName( "M", monthNamesShort, monthNames );
8387                        break;
8388                    case "y":
8389                        year = getNumber( "y" );
8390                        break;
8391                    case "@":
8392                        date = new Date( getNumber( "@" ) );
8393                        year = date.getFullYear();
8394                        month = date.getMonth() + 1;
8395                        day = date.getDate();
8396                        break;
8397                    case "!":
8398                        date = new Date( ( getNumber( "!" ) - this._ticksTo1970 ) / 10000 );
8399                        year = date.getFullYear();
8400                        month = date.getMonth() + 1;
8401                        day = date.getDate();
8402                        break;
8403                    case "'":
8404                        if ( lookAhead( "'" ) ) {
8405                            checkLiteral();
8406                        } else {
8407                            literal = true;
8408                        }
8409                        break;
8410                    default:
8411                        checkLiteral();
8412                }
8413            }
8414        }
8415
8416        if ( iValue < value.length ) {
8417            extra = value.substr( iValue );
8418            if ( !/^\s+/.test( extra ) ) {
8419                throw "Extra/unparsed characters found in date: " + extra;
8420            }
8421        }
8422
8423        if ( year === -1 ) {
8424            year = new Date().getFullYear();
8425        } else if ( year < 100 ) {
8426            year += new Date().getFullYear() - new Date().getFullYear() % 100 +
8427                ( year <= shortYearCutoff ? 0 : -100 );
8428        }
8429
8430        if ( doy > -1 ) {
8431            month = 1;
8432            day = doy;
8433            do {
8434                dim = this._getDaysInMonth( year, month - 1 );
8435                if ( day <= dim ) {
8436                    break;
8437                }
8438                month++;
8439                day -= dim;
8440            } while ( true );
8441        }
8442
8443        date = this._daylightSavingAdjust( new Date( year, month - 1, day ) );
8444        if ( date.getFullYear() !== year || date.getMonth() + 1 !== month || date.getDate() !== day ) {
8445            throw "Invalid date"; // E.g. 31/02/00
8446        }
8447        return date;
8448    },
8449
8450    /* Standard date formats. */
8451    ATOM: "yy-mm-dd", // RFC 3339 (ISO 8601)
8452    COOKIE: "D, dd M yy",
8453    ISO_8601: "yy-mm-dd",
8454    RFC_822: "D, d M y",
8455    RFC_850: "DD, dd-M-y",
8456    RFC_1036: "D, d M y",
8457    RFC_1123: "D, d M yy",
8458    RFC_2822: "D, d M yy",
8459    RSS: "D, d M y", // RFC 822
8460    TICKS: "!",
8461    TIMESTAMP: "@",
8462    W3C: "yy-mm-dd", // ISO 8601
8463
8464    _ticksTo1970: ( ( ( 1970 - 1 ) * 365 + Math.floor( 1970 / 4 ) - Math.floor( 1970 / 100 ) +
8465        Math.floor( 1970 / 400 ) ) * 24 * 60 * 60 * 10000000 ),
8466
8467    /* Format a date object into a string value.
8468     * The format can be combinations of the following:
8469     * d  - day of month (no leading zero)
8470     * dd - day of month (two digit)
8471     * o  - day of year (no leading zeros)
8472     * oo - day of year (three digit)
8473     * D  - day name short
8474     * DD - day name long
8475     * m  - month of year (no leading zero)
8476     * mm - month of year (two digit)
8477     * M  - month name short
8478     * MM - month name long
8479     * y  - year (two digit)
8480     * yy - year (four digit)
8481     * @ - Unix timestamp (ms since 01/01/1970)
8482     * ! - Windows ticks (100ns since 01/01/0001)
8483     * "..." - literal text
8484     * '' - single quote
8485     *
8486     * @param  format string - the desired format of the date
8487     * @param  date Date - the date value to format
8488     * @param  settings Object - attributes include:
8489     *                  dayNamesShort   string[7] - abbreviated names of the days from Sunday (optional)
8490     *                  dayNames        string[7] - names of the days from Sunday (optional)
8491     *                  monthNamesShort string[12] - abbreviated names of the months (optional)
8492     *                  monthNames      string[12] - names of the months (optional)
8493     * @return  string - the date in the above format
8494     */
8495    formatDate: function( format, date, settings ) {
8496        if ( !date ) {
8497            return "";
8498        }
8499
8500        var iFormat,
8501            dayNamesShort = ( settings ? settings.dayNamesShort : null ) || this._defaults.dayNamesShort,
8502            dayNames = ( settings ? settings.dayNames : null ) || this._defaults.dayNames,
8503            monthNamesShort = ( settings ? settings.monthNamesShort : null ) || this._defaults.monthNamesShort,
8504            monthNames = ( settings ? settings.monthNames : null ) || this._defaults.monthNames,
8505
8506            // Check whether a format character is doubled
8507            lookAhead = function( match ) {
8508                var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8509                if ( matches ) {
8510                    iFormat++;
8511                }
8512                return matches;
8513            },
8514
8515            // Format a number, with leading zero if necessary
8516            formatNumber = function( match, value, len ) {
8517                var num = "" + value;
8518                if ( lookAhead( match ) ) {
8519                    while ( num.length < len ) {
8520                        num = "0" + num;
8521                    }
8522                }
8523                return num;
8524            },
8525
8526            // Format a name, short or long as requested
8527            formatName = function( match, value, shortNames, longNames ) {
8528                return ( lookAhead( match ) ? longNames[ value ] : shortNames[ value ] );
8529            },
8530            output = "",
8531            literal = false;
8532
8533        if ( date ) {
8534            for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8535                if ( literal ) {
8536                    if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8537                        literal = false;
8538                    } else {
8539                        output += format.charAt( iFormat );
8540                    }
8541                } else {
8542                    switch ( format.charAt( iFormat ) ) {
8543                        case "d":
8544                            output += formatNumber( "d", date.getDate(), 2 );
8545                            break;
8546                        case "D":
8547                            output += formatName( "D", date.getDay(), dayNamesShort, dayNames );
8548                            break;
8549                        case "o":
8550                            output += formatNumber( "o",
8551                                Math.round( ( new Date( date.getFullYear(), date.getMonth(), date.getDate() ).getTime() - new Date( date.getFullYear(), 0, 0 ).getTime() ) / 86400000 ), 3 );
8552                            break;
8553                        case "m":
8554                            output += formatNumber( "m", date.getMonth() + 1, 2 );
8555                            break;
8556                        case "M":
8557                            output += formatName( "M", date.getMonth(), monthNamesShort, monthNames );
8558                            break;
8559                        case "y":
8560                            output += ( lookAhead( "y" ) ? date.getFullYear() :
8561                                ( date.getFullYear() % 100 < 10 ? "0" : "" ) + date.getFullYear() % 100 );
8562                            break;
8563                        case "@":
8564                            output += date.getTime();
8565                            break;
8566                        case "!":
8567                            output += date.getTime() * 10000 + this._ticksTo1970;
8568                            break;
8569                        case "'":
8570                            if ( lookAhead( "'" ) ) {
8571                                output += "'";
8572                            } else {
8573                                literal = true;
8574                            }
8575                            break;
8576                        default:
8577                            output += format.charAt( iFormat );
8578                    }
8579                }
8580            }
8581        }
8582        return output;
8583    },
8584
8585    /* Extract all possible characters from the date format. */
8586    _possibleChars: function( format ) {
8587        var iFormat,
8588            chars = "",
8589            literal = false,
8590
8591            // Check whether a format character is doubled
8592            lookAhead = function( match ) {
8593                var matches = ( iFormat + 1 < format.length && format.charAt( iFormat + 1 ) === match );
8594                if ( matches ) {
8595                    iFormat++;
8596                }
8597                return matches;
8598            };
8599
8600        for ( iFormat = 0; iFormat < format.length; iFormat++ ) {
8601            if ( literal ) {
8602                if ( format.charAt( iFormat ) === "'" && !lookAhead( "'" ) ) {
8603                    literal = false;
8604                } else {
8605                    chars += format.charAt( iFormat );
8606                }
8607            } else {
8608                switch ( format.charAt( iFormat ) ) {
8609                    case "d": case "m": case "y": case "@":
8610                        chars += "0123456789";
8611                        break;
8612                    case "D": case "M":
8613                        return null; // Accept anything
8614                    case "'":
8615                        if ( lookAhead( "'" ) ) {
8616                            chars += "'";
8617                        } else {
8618                            literal = true;
8619                        }
8620                        break;
8621                    default:
8622                        chars += format.charAt( iFormat );
8623                }
8624            }
8625        }
8626        return chars;
8627    },
8628
8629    /* Get a setting value, defaulting if necessary. */
8630    _get: function( inst, name ) {
8631        return inst.settings[ name ] !== undefined ?
8632            inst.settings[ name ] : this._defaults[ name ];
8633    },
8634
8635    /* Parse existing date and initialise date picker. */
8636    _setDateFromField: function( inst, noDefault ) {
8637        if ( inst.input.val() === inst.lastVal ) {
8638            return;
8639        }
8640
8641        var dateFormat = this._get( inst, "dateFormat" ),
8642            dates = inst.lastVal = inst.input ? inst.input.val() : null,
8643            defaultDate = this._getDefaultDate( inst ),
8644            date = defaultDate,
8645            settings = this._getFormatConfig( inst );
8646
8647        try {
8648            date = this.parseDate( dateFormat, dates, settings ) || defaultDate;
8649        } catch ( event ) {
8650            dates = ( noDefault ? "" : dates );
8651        }
8652        inst.selectedDay = date.getDate();
8653        inst.drawMonth = inst.selectedMonth = date.getMonth();
8654        inst.drawYear = inst.selectedYear = date.getFullYear();
8655        inst.currentDay = ( dates ? date.getDate() : 0 );
8656        inst.currentMonth = ( dates ? date.getMonth() : 0 );
8657        inst.currentYear = ( dates ? date.getFullYear() : 0 );
8658        this._adjustInstDate( inst );
8659    },
8660
8661    /* Retrieve the default date shown on opening. */
8662    _getDefaultDate: function( inst ) {
8663        return this._restrictMinMax( inst,
8664            this._determineDate( inst, this._get( inst, "defaultDate" ), new Date() ) );
8665    },
8666
8667    /* A date may be specified as an exact value or a relative one. */
8668    _determineDate: function( inst, date, defaultDate ) {
8669        var offsetNumeric = function( offset ) {
8670                var date = new Date();
8671                date.setDate( date.getDate() + offset );
8672                return date;
8673            },
8674            offsetString = function( offset ) {
8675                try {
8676                    return $.datepicker.parseDate( $.datepicker._get( inst, "dateFormat" ),
8677                        offset, $.datepicker._getFormatConfig( inst ) );
8678                } catch ( e ) {
8679
8680                    // Ignore
8681                }
8682
8683                var date = ( offset.toLowerCase().match( /^c/ ) ?
8684                    $.datepicker._getDate( inst ) : null ) || new Date(),
8685                    year = date.getFullYear(),
8686                    month = date.getMonth(),
8687                    day = date.getDate(),
8688                    pattern = /([+\-]?[0-9]+)\s*(d|D|w|W|m|M|y|Y)?/g,
8689                    matches = pattern.exec( offset );
8690
8691                while ( matches ) {
8692                    switch ( matches[ 2 ] || "d" ) {
8693                        case "d" : case "D" :
8694                            day += parseInt( matches[ 1 ], 10 ); break;
8695                        case "w" : case "W" :
8696                            day += parseInt( matches[ 1 ], 10 ) * 7; break;
8697                        case "m" : case "M" :
8698                            month += parseInt( matches[ 1 ], 10 );
8699                            day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8700                            break;
8701                        case "y": case "Y" :
8702                            year += parseInt( matches[ 1 ], 10 );
8703                            day = Math.min( day, $.datepicker._getDaysInMonth( year, month ) );
8704                            break;
8705                    }
8706                    matches = pattern.exec( offset );
8707                }
8708                return new Date( year, month, day );
8709            },
8710            newDate = ( date == null || date === "" ? defaultDate : ( typeof date === "string" ? offsetString( date ) :
8711                ( typeof date === "number" ? ( isNaN( date ) ? defaultDate : offsetNumeric( date ) ) : new Date( date.getTime() ) ) ) );
8712
8713        newDate = ( newDate && newDate.toString() === "Invalid Date" ? defaultDate : newDate );
8714        if ( newDate ) {
8715            newDate.setHours( 0 );
8716            newDate.setMinutes( 0 );
8717            newDate.setSeconds( 0 );
8718            newDate.setMilliseconds( 0 );
8719        }
8720        return this._daylightSavingAdjust( newDate );
8721    },
8722
8723    /* Handle switch to/from daylight saving.
8724     * Hours may be non-zero on daylight saving cut-over:
8725     * > 12 when midnight changeover, but then cannot generate
8726     * midnight datetime, so jump to 1AM, otherwise reset.
8727     * @param  date  (Date) the date to check
8728     * @return  (Date) the corrected date
8729     */
8730    _daylightSavingAdjust: function( date ) {
8731        if ( !date ) {
8732            return null;
8733        }
8734        date.setHours( date.getHours() > 12 ? date.getHours() + 2 : 0 );
8735        return date;
8736    },
8737
8738    /* Set the date(s) directly. */
8739    _setDate: function( inst, date, noChange ) {
8740        var clear = !date,
8741            origMonth = inst.selectedMonth,
8742            origYear = inst.selectedYear,
8743            newDate = this._restrictMinMax( inst, this._determineDate( inst, date, new Date() ) );
8744
8745        inst.selectedDay = inst.currentDay = newDate.getDate();
8746        inst.drawMonth = inst.selectedMonth = inst.currentMonth = newDate.getMonth();
8747        inst.drawYear = inst.selectedYear = inst.currentYear = newDate.getFullYear();
8748        if ( ( origMonth !== inst.selectedMonth || origYear !== inst.selectedYear ) && !noChange ) {
8749            this._notifyChange( inst );
8750        }
8751        this._adjustInstDate( inst );
8752        if ( inst.input ) {
8753            inst.input.val( clear ? "" : this._formatDate( inst ) );
8754        }
8755    },
8756
8757    /* Retrieve the date(s) directly. */
8758    _getDate: function( inst ) {
8759        var startDate = ( !inst.currentYear || ( inst.input && inst.input.val() === "" ) ? null :
8760            this._daylightSavingAdjust( new Date(
8761            inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
8762            return startDate;
8763    },
8764
8765    /* Attach the onxxx handlers.  These are declared statically so
8766     * they work with static code transformers like Caja.
8767     */
8768    _attachHandlers: function( inst ) {
8769        var stepMonths = this._get( inst, "stepMonths" ),
8770            id = "#" + inst.id.replace( /\\\\/g, "\\" );
8771        inst.dpDiv.find( "[data-handler]" ).map( function() {
8772            var handler = {
8773                prev: function() {
8774                    $.datepicker._adjustDate( id, -stepMonths, "M" );
8775                },
8776                next: function() {
8777                    $.datepicker._adjustDate( id, +stepMonths, "M" );
8778                },
8779                hide: function() {
8780                    $.datepicker._hideDatepicker();
8781                },
8782                today: function() {
8783                    $.datepicker._gotoToday( id );
8784                },
8785                selectDay: function() {
8786                    $.datepicker._selectDay( id, +this.getAttribute( "data-month" ), +this.getAttribute( "data-year" ), this );
8787                    return false;
8788                },
8789                selectMonth: function() {
8790                    $.datepicker._selectMonthYear( id, this, "M" );
8791                    return false;
8792                },
8793                selectYear: function() {
8794                    $.datepicker._selectMonthYear( id, this, "Y" );
8795                    return false;
8796                }
8797            };
8798            $( this ).on( this.getAttribute( "data-event" ), handler[ this.getAttribute( "data-handler" ) ] );
8799        } );
8800    },
8801
8802    /* Generate the HTML for the current state of the date picker. */
8803    _generateHTML: function( inst ) {
8804        var maxDraw, prevText, prev, nextText, next, currentText, gotoDate,
8805            controls, buttonPanel, firstDay, showWeek, dayNames, dayNamesMin,
8806            monthNames, monthNamesShort, beforeShowDay, showOtherMonths,
8807            selectOtherMonths, defaultDate, html, dow, row, group, col, selectedDate,
8808            cornerClass, calender, thead, day, daysInMonth, leadDays, curRows, numRows,
8809            printDate, dRow, tbody, daySettings, otherMonth, unselectable,
8810            tempDate = new Date(),
8811            today = this._daylightSavingAdjust(
8812                new Date( tempDate.getFullYear(), tempDate.getMonth(), tempDate.getDate() ) ), // clear time
8813            isRTL = this._get( inst, "isRTL" ),
8814            showButtonPanel = this._get( inst, "showButtonPanel" ),
8815            hideIfNoPrevNext = this._get( inst, "hideIfNoPrevNext" ),
8816            navigationAsDateFormat = this._get( inst, "navigationAsDateFormat" ),
8817            numMonths = this._getNumberOfMonths( inst ),
8818            showCurrentAtPos = this._get( inst, "showCurrentAtPos" ),
8819            stepMonths = this._get( inst, "stepMonths" ),
8820            isMultiMonth = ( numMonths[ 0 ] !== 1 || numMonths[ 1 ] !== 1 ),
8821            currentDate = this._daylightSavingAdjust( ( !inst.currentDay ? new Date( 9999, 9, 9 ) :
8822                new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) ),
8823            minDate = this._getMinMaxDate( inst, "min" ),
8824            maxDate = this._getMinMaxDate( inst, "max" ),
8825            drawMonth = inst.drawMonth - showCurrentAtPos,
8826            drawYear = inst.drawYear;
8827
8828        if ( drawMonth < 0 ) {
8829            drawMonth += 12;
8830            drawYear--;
8831        }
8832        if ( maxDate ) {
8833            maxDraw = this._daylightSavingAdjust( new Date( maxDate.getFullYear(),
8834                maxDate.getMonth() - ( numMonths[ 0 ] * numMonths[ 1 ] ) + 1, maxDate.getDate() ) );
8835            maxDraw = ( minDate && maxDraw < minDate ? minDate : maxDraw );
8836            while ( this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 ) ) > maxDraw ) {
8837                drawMonth--;
8838                if ( drawMonth < 0 ) {
8839                    drawMonth = 11;
8840                    drawYear--;
8841                }
8842            }
8843        }
8844        inst.drawMonth = drawMonth;
8845        inst.drawYear = drawYear;
8846
8847        prevText = this._get( inst, "prevText" );
8848        prevText = ( !navigationAsDateFormat ? prevText : this.formatDate( prevText,
8849            this._daylightSavingAdjust( new Date( drawYear, drawMonth - stepMonths, 1 ) ),
8850            this._getFormatConfig( inst ) ) );
8851
8852        if ( this._canAdjustMonth( inst, -1, drawYear, drawMonth ) ) {
8853            prev = $( "<a>" )
8854                .attr( {
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                    "class": "ui-datepicker-next ui-corner-all",
8891                    "data-handler": "next",
8892                    "data-event": "click",
8893                    title: nextText
8894                } )
8895                .append(
8896                    $( "<span>" )
8897                        .addClass( "ui-icon ui-icon-circle-triangle-" +
8898                            ( isRTL ? "w" : "e" ) )
8899                        .text( nextText )
8900                )[ 0 ].outerHTML;
8901        } else if ( hideIfNoPrevNext ) {
8902            next = "";
8903        } else {
8904            next = $( "<a>" )
8905                .attr( {
8906                    "class": "ui-datepicker-next ui-corner-all ui-state-disabled",
8907                    title: nextText
8908                } )
8909                .append(
8910                    $( "<span>" )
8911                        .attr( "class", "ui-icon ui-icon-circle-triangle-" +
8912                            ( isRTL ? "w" : "e" ) )
8913                        .text( nextText )
8914                )[ 0 ].outerHTML;
8915        }
8916
8917        currentText = this._get( inst, "currentText" );
8918        gotoDate = ( this._get( inst, "gotoCurrent" ) && inst.currentDay ? currentDate : today );
8919        currentText = ( !navigationAsDateFormat ? currentText :
8920            this.formatDate( currentText, gotoDate, this._getFormatConfig( inst ) ) );
8921
8922        controls = "";
8923        if ( !inst.inline ) {
8924            controls = $( "<button>" )
8925                .attr( {
8926                    type: "button",
8927                    "class": "ui-datepicker-close ui-state-default ui-priority-primary ui-corner-all",
8928                    "data-handler": "hide",
8929                    "data-event": "click"
8930                } )
8931                .text( this._get( inst, "closeText" ) )[ 0 ].outerHTML;
8932        }
8933
8934        buttonPanel = "";
8935        if ( showButtonPanel ) {
8936            buttonPanel = $( "<div class='ui-datepicker-buttonpane ui-widget-content'>" )
8937                .append( isRTL ? controls : "" )
8938                .append( this._isInRange( inst, gotoDate ) ?
8939                    $( "<button>" )
8940                        .attr( {
8941                            type: "button",
8942                            "class": "ui-datepicker-current ui-state-default ui-priority-secondary ui-corner-all",
8943                            "data-handler": "today",
8944                            "data-event": "click"
8945                        } )
8946                        .text( currentText ) :
8947                    "" )
8948                .append( isRTL ? "" : controls )[ 0 ].outerHTML;
8949        }
8950
8951        firstDay = parseInt( this._get( inst, "firstDay" ), 10 );
8952        firstDay = ( isNaN( firstDay ) ? 0 : firstDay );
8953
8954        showWeek = this._get( inst, "showWeek" );
8955        dayNames = this._get( inst, "dayNames" );
8956        dayNamesMin = this._get( inst, "dayNamesMin" );
8957        monthNames = this._get( inst, "monthNames" );
8958        monthNamesShort = this._get( inst, "monthNamesShort" );
8959        beforeShowDay = this._get( inst, "beforeShowDay" );
8960        showOtherMonths = this._get( inst, "showOtherMonths" );
8961        selectOtherMonths = this._get( inst, "selectOtherMonths" );
8962        defaultDate = this._getDefaultDate( inst );
8963        html = "";
8964
8965        for ( row = 0; row < numMonths[ 0 ]; row++ ) {
8966            group = "";
8967            this.maxRows = 4;
8968            for ( col = 0; col < numMonths[ 1 ]; col++ ) {
8969                selectedDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, inst.selectedDay ) );
8970                cornerClass = " ui-corner-all";
8971                calender = "";
8972                if ( isMultiMonth ) {
8973                    calender += "<div class='ui-datepicker-group";
8974                    if ( numMonths[ 1 ] > 1 ) {
8975                        switch ( col ) {
8976                            case 0: calender += " ui-datepicker-group-first";
8977                                cornerClass = " ui-corner-" + ( isRTL ? "right" : "left" ); break;
8978                            case numMonths[ 1 ] - 1: calender += " ui-datepicker-group-last";
8979                                cornerClass = " ui-corner-" + ( isRTL ? "left" : "right" ); break;
8980                            default: calender += " ui-datepicker-group-middle"; cornerClass = ""; break;
8981                        }
8982                    }
8983                    calender += "'>";
8984                }
8985                calender += "<div class='ui-datepicker-header ui-widget-header ui-helper-clearfix" + cornerClass + "'>" +
8986                    ( /all|left/.test( cornerClass ) && row === 0 ? ( isRTL ? next : prev ) : "" ) +
8987                    ( /all|right/.test( cornerClass ) && row === 0 ? ( isRTL ? prev : next ) : "" ) +
8988                    this._generateMonthYearHeader( inst, drawMonth, drawYear, minDate, maxDate,
8989                    row > 0 || col > 0, monthNames, monthNamesShort ) + // draw month headers
8990                    "</div><table class='ui-datepicker-calendar'><thead>" +
8991                    "<tr>";
8992                thead = ( showWeek ? "<th class='ui-datepicker-week-col'>" + this._get( inst, "weekHeader" ) + "</th>" : "" );
8993                for ( dow = 0; dow < 7; dow++ ) { // days of the week
8994                    day = ( dow + firstDay ) % 7;
8995                    thead += "<th scope='col'" + ( ( dow + firstDay + 6 ) % 7 >= 5 ? " class='ui-datepicker-week-end'" : "" ) + ">" +
8996                        "<span title='" + dayNames[ day ] + "'>" + dayNamesMin[ day ] + "</span></th>";
8997                }
8998                calender += thead + "</tr></thead><tbody>";
8999                daysInMonth = this._getDaysInMonth( drawYear, drawMonth );
9000                if ( drawYear === inst.selectedYear && drawMonth === inst.selectedMonth ) {
9001                    inst.selectedDay = Math.min( inst.selectedDay, daysInMonth );
9002                }
9003                leadDays = ( this._getFirstDayOfMonth( drawYear, drawMonth ) - firstDay + 7 ) % 7;
9004                curRows = Math.ceil( ( leadDays + daysInMonth ) / 7 ); // calculate the number of rows to generate
9005                numRows = ( isMultiMonth ? this.maxRows > curRows ? this.maxRows : curRows : curRows ); //If multiple months, use the higher number of rows (see #7043)
9006                this.maxRows = numRows;
9007                printDate = this._daylightSavingAdjust( new Date( drawYear, drawMonth, 1 - leadDays ) );
9008                for ( dRow = 0; dRow < numRows; dRow++ ) { // create date picker rows
9009                    calender += "<tr>";
9010                    tbody = ( !showWeek ? "" : "<td class='ui-datepicker-week-col'>" +
9011                        this._get( inst, "calculateWeek" )( printDate ) + "</td>" );
9012                    for ( dow = 0; dow < 7; dow++ ) { // create date picker days
9013                        daySettings = ( beforeShowDay ?
9014                            beforeShowDay.apply( ( inst.input ? inst.input[ 0 ] : null ), [ printDate ] ) : [ true, "" ] );
9015                        otherMonth = ( printDate.getMonth() !== drawMonth );
9016                        unselectable = ( otherMonth && !selectOtherMonths ) || !daySettings[ 0 ] ||
9017                            ( minDate && printDate < minDate ) || ( maxDate && printDate > maxDate );
9018                        tbody += "<td class='" +
9019                            ( ( dow + firstDay + 6 ) % 7 >= 5 ? " ui-datepicker-week-end" : "" ) + // highlight weekends
9020                            ( otherMonth ? " ui-datepicker-other-month" : "" ) + // highlight days from other months
9021                            ( ( printDate.getTime() === selectedDate.getTime() && drawMonth === inst.selectedMonth && inst._keyEvent ) || // user pressed key
9022                            ( defaultDate.getTime() === printDate.getTime() && defaultDate.getTime() === selectedDate.getTime() ) ?
9023
9024                            // or defaultDate is current printedDate and defaultDate is selectedDate
9025                            " " + this._dayOverClass : "" ) + // highlight selected day
9026                            ( unselectable ? " " + this._unselectableClass + " ui-state-disabled" : "" ) +  // highlight unselectable days
9027                            ( otherMonth && !showOtherMonths ? "" : " " + daySettings[ 1 ] + // highlight custom dates
9028                            ( printDate.getTime() === currentDate.getTime() ? " " + this._currentClass : "" ) + // highlight selected day
9029                            ( printDate.getTime() === today.getTime() ? " ui-datepicker-today" : "" ) ) + "'" + // highlight today (if different)
9030                            ( ( !otherMonth || showOtherMonths ) && daySettings[ 2 ] ? " title='" + daySettings[ 2 ].replace( /'/g, "&#39;" ) + "'" : "" ) + // cell title
9031                            ( unselectable ? "" : " data-handler='selectDay' data-event='click' data-month='" + printDate.getMonth() + "' data-year='" + printDate.getFullYear() + "'" ) + ">" + // actions
9032                            ( otherMonth && !showOtherMonths ? "&#xa0;" : // display for other months
9033                            ( unselectable ? "<span class='ui-state-default'>" + printDate.getDate() + "</span>" : "<a class='ui-state-default" +
9034                            ( printDate.getTime() === today.getTime() ? " ui-state-highlight" : "" ) +
9035                            ( printDate.getTime() === currentDate.getTime() ? " ui-state-active" : "" ) + // highlight selected day
9036                            ( otherMonth ? " ui-priority-secondary" : "" ) + // distinguish dates from other months
9037                            "' href='#' aria-current='" + ( printDate.getTime() === currentDate.getTime() ? "true" : "false" ) + // mark date as selected for screen reader
9038                            "' data-date='" + printDate.getDate() + // store date as data
9039                            "'>" + printDate.getDate() + "</a>" ) ) + "</td>"; // display selectable date
9040                        printDate.setDate( printDate.getDate() + 1 );
9041                        printDate = this._daylightSavingAdjust( printDate );
9042                    }
9043                    calender += tbody + "</tr>";
9044                }
9045                drawMonth++;
9046                if ( drawMonth > 11 ) {
9047                    drawMonth = 0;
9048                    drawYear++;
9049                }
9050                calender += "</tbody></table>" + ( isMultiMonth ? "</div>" +
9051                            ( ( numMonths[ 0 ] > 0 && col === numMonths[ 1 ] - 1 ) ? "<div class='ui-datepicker-row-break'></div>" : "" ) : "" );
9052                group += calender;
9053            }
9054            html += group;
9055        }
9056        html += buttonPanel;
9057        inst._keyEvent = false;
9058        return html;
9059    },
9060
9061    /* Generate the month and year header. */
9062    _generateMonthYearHeader: function( inst, drawMonth, drawYear, minDate, maxDate,
9063            secondary, monthNames, monthNamesShort ) {
9064
9065        var inMinYear, inMaxYear, month, years, thisYear, determineYear, year, endYear,
9066            changeMonth = this._get( inst, "changeMonth" ),
9067            changeYear = this._get( inst, "changeYear" ),
9068            showMonthAfterYear = this._get( inst, "showMonthAfterYear" ),
9069            selectMonthLabel = this._get( inst, "selectMonthLabel" ),
9070            selectYearLabel = this._get( inst, "selectYearLabel" ),
9071            html = "<div class='ui-datepicker-title'>",
9072            monthHtml = "";
9073
9074        // Month selection
9075        if ( secondary || !changeMonth ) {
9076            monthHtml += "<span class='ui-datepicker-month'>" + monthNames[ drawMonth ] + "</span>";
9077        } else {
9078            inMinYear = ( minDate && minDate.getFullYear() === drawYear );
9079            inMaxYear = ( maxDate && maxDate.getFullYear() === drawYear );
9080            monthHtml += "<select class='ui-datepicker-month' aria-label='" + selectMonthLabel + "' data-handler='selectMonth' data-event='change'>";
9081            for ( month = 0; month < 12; month++ ) {
9082                if ( ( !inMinYear || month >= minDate.getMonth() ) && ( !inMaxYear || month <= maxDate.getMonth() ) ) {
9083                    monthHtml += "<option value='" + month + "'" +
9084                        ( month === drawMonth ? " selected='selected'" : "" ) +
9085                        ">" + monthNamesShort[ month ] + "</option>";
9086                }
9087            }
9088            monthHtml += "</select>";
9089        }
9090
9091        if ( !showMonthAfterYear ) {
9092            html += monthHtml + ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" );
9093        }
9094
9095        // Year selection
9096        if ( !inst.yearshtml ) {
9097            inst.yearshtml = "";
9098            if ( secondary || !changeYear ) {
9099                html += "<span class='ui-datepicker-year'>" + drawYear + "</span>";
9100            } else {
9101
9102                // determine range of years to display
9103                years = this._get( inst, "yearRange" ).split( ":" );
9104                thisYear = new Date().getFullYear();
9105                determineYear = function( value ) {
9106                    var year = ( value.match( /c[+\-].*/ ) ? drawYear + parseInt( value.substring( 1 ), 10 ) :
9107                        ( value.match( /[+\-].*/ ) ? thisYear + parseInt( value, 10 ) :
9108                        parseInt( value, 10 ) ) );
9109                    return ( isNaN( year ) ? thisYear : year );
9110                };
9111                year = determineYear( years[ 0 ] );
9112                endYear = Math.max( year, determineYear( years[ 1 ] || "" ) );
9113                year = ( minDate ? Math.max( year, minDate.getFullYear() ) : year );
9114                endYear = ( maxDate ? Math.min( endYear, maxDate.getFullYear() ) : endYear );
9115                inst.yearshtml += "<select class='ui-datepicker-year' aria-label='" + selectYearLabel + "' data-handler='selectYear' data-event='change'>";
9116                for ( ; year <= endYear; year++ ) {
9117                    inst.yearshtml += "<option value='" + year + "'" +
9118                        ( year === drawYear ? " selected='selected'" : "" ) +
9119                        ">" + year + "</option>";
9120                }
9121                inst.yearshtml += "</select>";
9122
9123                html += inst.yearshtml;
9124                inst.yearshtml = null;
9125            }
9126        }
9127
9128        html += this._get( inst, "yearSuffix" );
9129        if ( showMonthAfterYear ) {
9130            html += ( secondary || !( changeMonth && changeYear ) ? "&#xa0;" : "" ) + monthHtml;
9131        }
9132        html += "</div>"; // Close datepicker_header
9133        return html;
9134    },
9135
9136    /* Adjust one of the date sub-fields. */
9137    _adjustInstDate: function( inst, offset, period ) {
9138        var year = inst.selectedYear + ( period === "Y" ? offset : 0 ),
9139            month = inst.selectedMonth + ( period === "M" ? offset : 0 ),
9140            day = Math.min( inst.selectedDay, this._getDaysInMonth( year, month ) ) + ( period === "D" ? offset : 0 ),
9141            date = this._restrictMinMax( inst, this._daylightSavingAdjust( new Date( year, month, day ) ) );
9142
9143        inst.selectedDay = date.getDate();
9144        inst.drawMonth = inst.selectedMonth = date.getMonth();
9145        inst.drawYear = inst.selectedYear = date.getFullYear();
9146        if ( period === "M" || period === "Y" ) {
9147            this._notifyChange( inst );
9148        }
9149    },
9150
9151    /* Ensure a date is within any min/max bounds. */
9152    _restrictMinMax: function( inst, date ) {
9153        var minDate = this._getMinMaxDate( inst, "min" ),
9154            maxDate = this._getMinMaxDate( inst, "max" ),
9155            newDate = ( minDate && date < minDate ? minDate : date );
9156        return ( maxDate && newDate > maxDate ? maxDate : newDate );
9157    },
9158
9159    /* Notify change of month/year. */
9160    _notifyChange: function( inst ) {
9161        var onChange = this._get( inst, "onChangeMonthYear" );
9162        if ( onChange ) {
9163            onChange.apply( ( inst.input ? inst.input[ 0 ] : null ),
9164                [ inst.selectedYear, inst.selectedMonth + 1, inst ] );
9165        }
9166    },
9167
9168    /* Determine the number of months to show. */
9169    _getNumberOfMonths: function( inst ) {
9170        var numMonths = this._get( inst, "numberOfMonths" );
9171        return ( numMonths == null ? [ 1, 1 ] : ( typeof numMonths === "number" ? [ 1, numMonths ] : numMonths ) );
9172    },
9173
9174    /* Determine the current maximum date - ensure no time components are set. */
9175    _getMinMaxDate: function( inst, minMax ) {
9176        return this._determineDate( inst, this._get( inst, minMax + "Date" ), null );
9177    },
9178
9179    /* Find the number of days in a given month. */
9180    _getDaysInMonth: function( year, month ) {
9181        return 32 - this._daylightSavingAdjust( new Date( year, month, 32 ) ).getDate();
9182    },
9183
9184    /* Find the day of the week of the first of a month. */
9185    _getFirstDayOfMonth: function( year, month ) {
9186        return new Date( year, month, 1 ).getDay();
9187    },
9188
9189    /* Determines if we should allow a "next/prev" month display change. */
9190    _canAdjustMonth: function( inst, offset, curYear, curMonth ) {
9191        var numMonths = this._getNumberOfMonths( inst ),
9192            date = this._daylightSavingAdjust( new Date( curYear,
9193            curMonth + ( offset < 0 ? offset : numMonths[ 0 ] * numMonths[ 1 ] ), 1 ) );
9194
9195        if ( offset < 0 ) {
9196            date.setDate( this._getDaysInMonth( date.getFullYear(), date.getMonth() ) );
9197        }
9198        return this._isInRange( inst, date );
9199    },
9200
9201    /* Is the given date in the accepted range? */
9202    _isInRange: function( inst, date ) {
9203        var yearSplit, currentYear,
9204            minDate = this._getMinMaxDate( inst, "min" ),
9205            maxDate = this._getMinMaxDate( inst, "max" ),
9206            minYear = null,
9207            maxYear = null,
9208            years = this._get( inst, "yearRange" );
9209            if ( years ) {
9210                yearSplit = years.split( ":" );
9211                currentYear = new Date().getFullYear();
9212                minYear = parseInt( yearSplit[ 0 ], 10 );
9213                maxYear = parseInt( yearSplit[ 1 ], 10 );
9214                if ( yearSplit[ 0 ].match( /[+\-].*/ ) ) {
9215                    minYear += currentYear;
9216                }
9217                if ( yearSplit[ 1 ].match( /[+\-].*/ ) ) {
9218                    maxYear += currentYear;
9219                }
9220            }
9221
9222        return ( ( !minDate || date.getTime() >= minDate.getTime() ) &&
9223            ( !maxDate || date.getTime() <= maxDate.getTime() ) &&
9224            ( !minYear || date.getFullYear() >= minYear ) &&
9225            ( !maxYear || date.getFullYear() <= maxYear ) );
9226    },
9227
9228    /* Provide the configuration settings for formatting/parsing. */
9229    _getFormatConfig: function( inst ) {
9230        var shortYearCutoff = this._get( inst, "shortYearCutoff" );
9231        shortYearCutoff = ( typeof shortYearCutoff !== "string" ? shortYearCutoff :
9232            new Date().getFullYear() % 100 + parseInt( shortYearCutoff, 10 ) );
9233        return { shortYearCutoff: shortYearCutoff,
9234            dayNamesShort: this._get( inst, "dayNamesShort" ), dayNames: this._get( inst, "dayNames" ),
9235            monthNamesShort: this._get( inst, "monthNamesShort" ), monthNames: this._get( inst, "monthNames" ) };
9236    },
9237
9238    /* Format the given date for display. */
9239    _formatDate: function( inst, day, month, year ) {
9240        if ( !day ) {
9241            inst.currentDay = inst.selectedDay;
9242            inst.currentMonth = inst.selectedMonth;
9243            inst.currentYear = inst.selectedYear;
9244        }
9245        var date = ( day ? ( typeof day === "object" ? day :
9246            this._daylightSavingAdjust( new Date( year, month, day ) ) ) :
9247            this._daylightSavingAdjust( new Date( inst.currentYear, inst.currentMonth, inst.currentDay ) ) );
9248        return this.formatDate( this._get( inst, "dateFormat" ), date, this._getFormatConfig( inst ) );
9249    }
9250} );
9251
9252/*
9253 * Bind hover events for datepicker elements.
9254 * Done via delegate so the binding only occurs once in the lifetime of the parent div.
9255 * Global datepicker_instActive, set by _updateDatepicker allows the handlers to find their way back to the active picker.
9256 */
9257function datepicker_bindHover( dpDiv ) {
9258    var selector = "button, .ui-datepicker-prev, .ui-datepicker-next, .ui-datepicker-calendar td a";
9259    return dpDiv.on( "mouseout", selector, function() {
9260            $( this ).removeClass( "ui-state-hover" );
9261            if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9262                $( this ).removeClass( "ui-datepicker-prev-hover" );
9263            }
9264            if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9265                $( this ).removeClass( "ui-datepicker-next-hover" );
9266            }
9267        } )
9268        .on( "mouseover", selector, datepicker_handleMouseover );
9269}
9270
9271function datepicker_handleMouseover() {
9272    if ( !$.datepicker._isDisabledDatepicker( datepicker_instActive.inline ? datepicker_instActive.dpDiv.parent()[ 0 ] : datepicker_instActive.input[ 0 ] ) ) {
9273        $( this ).parents( ".ui-datepicker-calendar" ).find( "a" ).removeClass( "ui-state-hover" );
9274        $( this ).addClass( "ui-state-hover" );
9275        if ( this.className.indexOf( "ui-datepicker-prev" ) !== -1 ) {
9276            $( this ).addClass( "ui-datepicker-prev-hover" );
9277        }
9278        if ( this.className.indexOf( "ui-datepicker-next" ) !== -1 ) {
9279            $( this ).addClass( "ui-datepicker-next-hover" );
9280        }
9281    }
9282}
9283
9284/* jQuery extend now ignores nulls! */
9285function datepicker_extendRemove( target, props ) {
9286    $.extend( target, props );
9287    for ( var name in props ) {
9288        if ( props[ name ] == null ) {
9289            target[ name ] = props[ name ];
9290        }
9291    }
9292    return target;
9293}
9294
9295/* Invoke the datepicker functionality.
9296   @param  options  string - a command, optionally followed by additional parameters or
9297                    Object - settings for attaching new datepicker functionality
9298   @return  jQuery object */
9299$.fn.datepicker = function( options ) {
9300
9301    /* Verify an empty collection wasn't passed - Fixes #6976 */
9302    if ( !this.length ) {
9303        return this;
9304    }
9305
9306    /* Initialise the date picker. */
9307    if ( !$.datepicker.initialized ) {
9308        $( document ).on( "mousedown", $.datepicker._checkExternalClick );
9309        $.datepicker.initialized = true;
9310    }
9311
9312    /* Append datepicker main container to body if not exist. */
9313    if ( $( "#" + $.datepicker._mainDivId ).length === 0 ) {
9314        $( "body" ).append( $.datepicker.dpDiv );
9315    }
9316
9317    var otherArgs = Array.prototype.slice.call( arguments, 1 );
9318    if ( typeof options === "string" && ( options === "isDisabled" || options === "getDate" || options === "widget" ) ) {
9319        return $.datepicker[ "_" + options + "Datepicker" ].
9320            apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9321    }
9322    if ( options === "option" && arguments.length === 2 && typeof arguments[ 1 ] === "string" ) {
9323        return $.datepicker[ "_" + options + "Datepicker" ].
9324            apply( $.datepicker, [ this[ 0 ] ].concat( otherArgs ) );
9325    }
9326    return this.each( function() {
9327        if ( typeof options === "string" ) {
9328            $.datepicker[ "_" + options + "Datepicker" ]
9329                .apply( $.datepicker, [ this ].concat( otherArgs ) );
9330        } else {
9331            $.datepicker._attachDatepicker( this, options );
9332        }
9333    } );
9334};
9335
9336$.datepicker = new Datepicker(); // singleton instance
9337$.datepicker.initialized = false;
9338$.datepicker.uuid = new Date().getTime();
9339$.datepicker.version = "1.14.1";
9340
9341var widgetsDatepicker = $.datepicker;
9342
9343
9344/*!
9345 * jQuery UI Mouse 1.14.1
9346 * https://jqueryui.com
9347 *
9348 * Copyright OpenJS Foundation and other contributors
9349 * Released under the MIT license.
9350 * https://jquery.org/license
9351 */
9352
9353//>>label: Mouse
9354//>>group: Widgets
9355//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
9356//>>docs: https://api.jqueryui.com/mouse/
9357
9358
9359var mouseHandled = false;
9360$( document ).on( "mouseup", function() {
9361    mouseHandled = false;
9362} );
9363
9364var widgetsMouse = $.widget( "ui.mouse", {
9365    version: "1.14.1",
9366    options: {
9367        cancel: "input, textarea, button, select, option",
9368        distance: 1,
9369        delay: 0
9370    },
9371    _mouseInit: function() {
9372        var that = this;
9373
9374        this.element
9375            .on( "mousedown." + this.widgetName, function( event ) {
9376                return that._mouseDown( event );
9377            } )
9378            .on( "click." + this.widgetName, function( event ) {
9379                if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
9380                    $.removeData( event.target, that.widgetName + ".preventClickEvent" );
9381                    event.stopImmediatePropagation();
9382                    return false;
9383                }
9384            } );
9385
9386        this.started = false;
9387    },
9388
9389    // TODO: make sure destroying one instance of mouse doesn't mess with
9390    // other instances of mouse
9391    _mouseDestroy: function() {
9392        this.element.off( "." + this.widgetName );
9393        if ( this._mouseMoveDelegate ) {
9394            this.document
9395                .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9396                .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9397        }
9398    },
9399
9400    _mouseDown: function( event ) {
9401
9402        // don't let more than one widget handle mouseStart
9403        if ( mouseHandled ) {
9404            return;
9405        }
9406
9407        this._mouseMoved = false;
9408
9409        // We may have missed mouseup (out of window)
9410        if ( this._mouseStarted ) {
9411            this._mouseUp( event );
9412        }
9413
9414        this._mouseDownEvent = event;
9415
9416        var that = this,
9417            btnIsLeft = event.which === 1,
9418            elIsCancel = typeof this.options.cancel === "string" ?
9419                $( event.target ).closest( this.options.cancel ).length :
9420                false;
9421        if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
9422            return true;
9423        }
9424
9425        this.mouseDelayMet = !this.options.delay;
9426        if ( !this.mouseDelayMet ) {
9427            this._mouseDelayTimer = setTimeout( function() {
9428                that.mouseDelayMet = true;
9429            }, this.options.delay );
9430        }
9431
9432        if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9433            this._mouseStarted = ( this._mouseStart( event ) !== false );
9434            if ( !this._mouseStarted ) {
9435                event.preventDefault();
9436                return true;
9437            }
9438        }
9439
9440        // Click event may never have fired (Gecko & Opera)
9441        if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
9442            $.removeData( event.target, this.widgetName + ".preventClickEvent" );
9443        }
9444
9445        // These delegates are required to keep context
9446        this._mouseMoveDelegate = function( event ) {
9447            return that._mouseMove( event );
9448        };
9449        this._mouseUpDelegate = function( event ) {
9450            return that._mouseUp( event );
9451        };
9452
9453        this.document
9454            .on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9455            .on( "mouseup." + this.widgetName, this._mouseUpDelegate );
9456
9457        event.preventDefault();
9458
9459        mouseHandled = true;
9460        return true;
9461    },
9462
9463    _mouseMove: function( event ) {
9464
9465        // Only check for mouseups outside the document if you've moved inside the document
9466        // at least once.
9467        if ( this._mouseMoved && !event.which ) {
9468
9469            // Support: Safari <=8 - 9
9470            // Safari sets which to 0 if you press any of the following keys
9471            // during a drag (#14461)
9472            if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
9473                    event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
9474                this.ignoreMissingWhich = true;
9475            } else if ( !this.ignoreMissingWhich ) {
9476                return this._mouseUp( event );
9477            }
9478        }
9479
9480        if ( event.which || event.button ) {
9481            this._mouseMoved = true;
9482        }
9483
9484        if ( this._mouseStarted ) {
9485            this._mouseDrag( event );
9486            return event.preventDefault();
9487        }
9488
9489        if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
9490            this._mouseStarted =
9491                ( this._mouseStart( this._mouseDownEvent, event ) !== false );
9492            if ( this._mouseStarted ) {
9493                this._mouseDrag( event );
9494            } else {
9495                this._mouseUp( event );
9496            }
9497        }
9498
9499        return !this._mouseStarted;
9500    },
9501
9502    _mouseUp: function( event ) {
9503        this.document
9504            .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
9505            .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
9506
9507        if ( this._mouseStarted ) {
9508            this._mouseStarted = false;
9509
9510            if ( event.target === this._mouseDownEvent.target ) {
9511                $.data( event.target, this.widgetName + ".preventClickEvent", true );
9512            }
9513
9514            this._mouseStop( event );
9515        }
9516
9517        if ( this._mouseDelayTimer ) {
9518            clearTimeout( this._mouseDelayTimer );
9519            delete this._mouseDelayTimer;
9520        }
9521
9522        this.ignoreMissingWhich = false;
9523        mouseHandled = false;
9524        event.preventDefault();
9525    },
9526
9527    _mouseDistanceMet: function( event ) {
9528        return ( Math.max(
9529                Math.abs( this._mouseDownEvent.pageX - event.pageX ),
9530                Math.abs( this._mouseDownEvent.pageY - event.pageY )
9531            ) >= this.options.distance
9532        );
9533    },
9534
9535    _mouseDelayMet: function( /* event */ ) {
9536        return this.mouseDelayMet;
9537    },
9538
9539    // These are placeholder methods, to be overriden by extending plugin
9540    _mouseStart: function( /* event */ ) {},
9541    _mouseDrag: function( /* event */ ) {},
9542    _mouseStop: function( /* event */ ) {},
9543    _mouseCapture: function( /* event */ ) {
9544        return true;
9545    }
9546} );
9547
9548
9549
9550// $.ui.plugin is deprecated. Use $.widget() extensions instead.
9551var plugin = $.ui.plugin = {
9552    add: function( module, option, set ) {
9553        var i,
9554            proto = $.ui[ module ].prototype;
9555        for ( i in set ) {
9556            proto.plugins[ i ] = proto.plugins[ i ] || [];
9557            proto.plugins[ i ].push( [ option, set[ i ] ] );
9558        }
9559    },
9560    call: function( instance, name, args, allowDisconnected ) {
9561        var i,
9562            set = instance.plugins[ name ];
9563
9564        if ( !set ) {
9565            return;
9566        }
9567
9568        if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
9569                instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
9570            return;
9571        }
9572
9573        for ( i = 0; i < set.length; i++ ) {
9574            if ( instance.options[ set[ i ][ 0 ] ] ) {
9575                set[ i ][ 1 ].apply( instance.element, args );
9576            }
9577        }
9578    }
9579};
9580
9581
9582/*!
9583 * jQuery UI Draggable 1.14.1
9584 * https://jqueryui.com
9585 *
9586 * Copyright OpenJS Foundation and other contributors
9587 * Released under the MIT license.
9588 * https://jquery.org/license
9589 */
9590
9591//>>label: Draggable
9592//>>group: Interactions
9593//>>description: Enables dragging functionality for any element.
9594//>>docs: https://api.jqueryui.com/draggable/
9595//>>demos: https://jqueryui.com/draggable/
9596//>>css.structure: ../../themes/base/draggable.css
9597
9598
9599$.widget( "ui.draggable", $.ui.mouse, {
9600    version: "1.14.1",
9601    widgetEventPrefix: "drag",
9602    options: {
9603        addClasses: true,
9604        appendTo: "parent",
9605        axis: false,
9606        connectToSortable: false,
9607        containment: false,
9608        cursor: "auto",
9609        cursorAt: false,
9610        grid: false,
9611        handle: false,
9612        helper: "original",
9613        iframeFix: false,
9614        opacity: false,
9615        refreshPositions: false,
9616        revert: false,
9617        revertDuration: 500,
9618        scope: "default",
9619        scroll: true,
9620        scrollSensitivity: 20,
9621        scrollSpeed: 20,
9622        snap: false,
9623        snapMode: "both",
9624        snapTolerance: 20,
9625        stack: false,
9626        zIndex: false,
9627
9628        // Callbacks
9629        drag: null,
9630        start: null,
9631        stop: null
9632    },
9633    _create: function() {
9634
9635        if ( this.options.helper === "original" ) {
9636            this._setPositionRelative();
9637        }
9638        if ( this.options.addClasses ) {
9639            this._addClass( "ui-draggable" );
9640        }
9641        this._setHandleClassName();
9642
9643        this._mouseInit();
9644    },
9645
9646    _setOption: function( key, value ) {
9647        this._super( key, value );
9648        if ( key === "handle" ) {
9649            this._removeHandleClassName();
9650            this._setHandleClassName();
9651        }
9652    },
9653
9654    _destroy: function() {
9655        if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
9656            this.destroyOnClear = true;
9657            return;
9658        }
9659        this._removeHandleClassName();
9660        this._mouseDestroy();
9661    },
9662
9663    _mouseCapture: function( event ) {
9664        var o = this.options;
9665
9666        // Among others, prevent a drag on a resizable-handle
9667        if ( this.helper || o.disabled ||
9668                $( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
9669            return false;
9670        }
9671
9672        //Quit if we're not on a valid handle
9673        this.handle = this._getHandle( event );
9674        if ( !this.handle ) {
9675            return false;
9676        }
9677
9678        this._blurActiveElement( event );
9679
9680        this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );
9681
9682        return true;
9683
9684    },
9685
9686    _blockFrames: function( selector ) {
9687        this.iframeBlocks = this.document.find( selector ).map( function() {
9688            var iframe = $( this );
9689
9690            return $( "<div>" )
9691                .css( "position", "absolute" )
9692                .appendTo( iframe.parent() )
9693                .outerWidth( iframe.outerWidth() )
9694                .outerHeight( iframe.outerHeight() )
9695                .offset( iframe.offset() )[ 0 ];
9696        } );
9697    },
9698
9699    _unblockFrames: function() {
9700        if ( this.iframeBlocks ) {
9701            this.iframeBlocks.remove();
9702            delete this.iframeBlocks;
9703        }
9704    },
9705
9706    _blurActiveElement: function( event ) {
9707        var activeElement = this.document[ 0 ].activeElement,
9708            target = $( event.target );
9709
9710        // Don't blur if the event occurred on an element that is within
9711        // the currently focused element
9712        // See #10527, #12472
9713        if ( target.closest( activeElement ).length ) {
9714            return;
9715        }
9716
9717        // Blur any element that currently has focus, see #4261
9718        $( activeElement ).trigger( "blur" );
9719    },
9720
9721    _mouseStart: function( event ) {
9722
9723        var o = this.options;
9724
9725        //Create and append the visible helper
9726        this.helper = this._createHelper( event );
9727
9728        this._addClass( this.helper, "ui-draggable-dragging" );
9729
9730        //Cache the helper size
9731        this._cacheHelperProportions();
9732
9733        //If ddmanager is used for droppables, set the global draggable
9734        if ( $.ui.ddmanager ) {
9735            $.ui.ddmanager.current = this;
9736        }
9737
9738        /*
9739         * - Position generation -
9740         * This block generates everything position related - it's the core of draggables.
9741         */
9742
9743        //Cache the margins of the original element
9744        this._cacheMargins();
9745
9746        //Store the helper's css position
9747        this.cssPosition = this.helper.css( "position" );
9748        this.scrollParent = this.helper.scrollParent( true );
9749        this.offsetParent = this.helper.offsetParent();
9750        this.hasFixedAncestor = this.helper.parents().filter( function() {
9751                return $( this ).css( "position" ) === "fixed";
9752            } ).length > 0;
9753
9754        //The element's absolute position on the page minus margins
9755        this.positionAbs = this.element.offset();
9756        this._refreshOffsets( event );
9757
9758        //Generate the original position
9759        this.originalPosition = this.position = this._generatePosition( event, false );
9760        this.originalPageX = event.pageX;
9761        this.originalPageY = event.pageY;
9762
9763        //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
9764        if ( o.cursorAt ) {
9765            this._adjustOffsetFromHelper( o.cursorAt );
9766        }
9767
9768        //Set a containment if given in the options
9769        this._setContainment();
9770
9771        //Trigger event + callbacks
9772        if ( this._trigger( "start", event ) === false ) {
9773            this._clear();
9774            return false;
9775        }
9776
9777        //Recache the helper size
9778        this._cacheHelperProportions();
9779
9780        //Prepare the droppable offsets
9781        if ( $.ui.ddmanager && !o.dropBehaviour ) {
9782            $.ui.ddmanager.prepareOffsets( this, event );
9783        }
9784
9785        // Execute the drag once - this causes the helper not to be visible before getting its
9786        // correct position
9787        this._mouseDrag( event, true );
9788
9789        // If the ddmanager is used for droppables, inform the manager that dragging has started
9790        // (see #5003)
9791        if ( $.ui.ddmanager ) {
9792            $.ui.ddmanager.dragStart( this, event );
9793        }
9794
9795        return true;
9796    },
9797
9798    _refreshOffsets: function( event ) {
9799        this.offset = {
9800            top: this.positionAbs.top - this.margins.top,
9801            left: this.positionAbs.left - this.margins.left,
9802            scroll: false,
9803            parent: this._getParentOffset(),
9804            relative: this._getRelativeOffset()
9805        };
9806
9807        this.offset.click = {
9808            left: event.pageX - this.offset.left,
9809            top: event.pageY - this.offset.top
9810        };
9811    },
9812
9813    _mouseDrag: function( event, noPropagation ) {
9814
9815        // reset any necessary cached properties (see #5009)
9816        if ( this.hasFixedAncestor ) {
9817            this.offset.parent = this._getParentOffset();
9818        }
9819
9820        //Compute the helpers position
9821        this.position = this._generatePosition( event, true );
9822        this.positionAbs = this._convertPositionTo( "absolute" );
9823
9824        //Call plugins and callbacks and use the resulting position if something is returned
9825        if ( !noPropagation ) {
9826            var ui = this._uiHash();
9827            if ( this._trigger( "drag", event, ui ) === false ) {
9828                this._mouseUp( new $.Event( "mouseup", event ) );
9829                return false;
9830            }
9831            this.position = ui.position;
9832        }
9833
9834        this.helper[ 0 ].style.left = this.position.left + "px";
9835        this.helper[ 0 ].style.top = this.position.top + "px";
9836
9837        if ( $.ui.ddmanager ) {
9838            $.ui.ddmanager.drag( this, event );
9839        }
9840
9841        return false;
9842    },
9843
9844    _mouseStop: function( event ) {
9845
9846        //If we are using droppables, inform the manager about the drop
9847        var that = this,
9848            dropped = false;
9849        if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
9850            dropped = $.ui.ddmanager.drop( this, event );
9851        }
9852
9853        //if a drop comes from outside (a sortable)
9854        if ( this.dropped ) {
9855            dropped = this.dropped;
9856            this.dropped = false;
9857        }
9858
9859        if ( ( this.options.revert === "invalid" && !dropped ) ||
9860                ( this.options.revert === "valid" && dropped ) ||
9861                this.options.revert === true || ( typeof this.options.revert === "function" &&
9862                this.options.revert.call( this.element, dropped ) )
9863        ) {
9864            $( this.helper ).animate(
9865                this.originalPosition,
9866                parseInt( this.options.revertDuration, 10 ),
9867                function() {
9868                    if ( that._trigger( "stop", event ) !== false ) {
9869                        that._clear();
9870                    }
9871                }
9872            );
9873        } else {
9874            if ( this._trigger( "stop", event ) !== false ) {
9875                this._clear();
9876            }
9877        }
9878
9879        return false;
9880    },
9881
9882    _mouseUp: function( event ) {
9883        this._unblockFrames();
9884
9885        // If the ddmanager is used for droppables, inform the manager that dragging has stopped
9886        // (see #5003)
9887        if ( $.ui.ddmanager ) {
9888            $.ui.ddmanager.dragStop( this, event );
9889        }
9890
9891        // Only need to focus if the event occurred on the draggable itself, see #10527
9892        if ( this.handleElement.is( event.target ) ) {
9893
9894            // The interaction is over; whether or not the click resulted in a drag,
9895            // focus the element
9896            this.element.trigger( "focus" );
9897        }
9898
9899        return $.ui.mouse.prototype._mouseUp.call( this, event );
9900    },
9901
9902    cancel: function() {
9903
9904        if ( this.helper.is( ".ui-draggable-dragging" ) ) {
9905            this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
9906        } else {
9907            this._clear();
9908        }
9909
9910        return this;
9911
9912    },
9913
9914    _getHandle: function( event ) {
9915        return this.options.handle ?
9916            !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
9917            true;
9918    },
9919
9920    _setHandleClassName: function() {
9921        this.handleElement = this.options.handle ?
9922            this.element.find( this.options.handle ) : this.element;
9923        this._addClass( this.handleElement, "ui-draggable-handle" );
9924    },
9925
9926    _removeHandleClassName: function() {
9927        this._removeClass( this.handleElement, "ui-draggable-handle" );
9928    },
9929
9930    _createHelper: function( event ) {
9931
9932        var o = this.options,
9933            helperIsFunction = typeof o.helper === "function",
9934            helper = helperIsFunction ?
9935                $( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
9936                ( o.helper === "clone" ?
9937                    this.element.clone().removeAttr( "id" ) :
9938                    this.element );
9939
9940        if ( !helper.parents( "body" ).length ) {
9941            helper.appendTo( ( o.appendTo === "parent" ?
9942                this.element[ 0 ].parentNode :
9943                o.appendTo ) );
9944        }
9945
9946        // https://bugs.jqueryui.com/ticket/9446
9947        // a helper function can return the original element
9948        // which wouldn't have been set to relative in _create
9949        if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
9950            this._setPositionRelative();
9951        }
9952
9953        if ( helper[ 0 ] !== this.element[ 0 ] &&
9954                !( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
9955            helper.css( "position", "absolute" );
9956        }
9957
9958        return helper;
9959
9960    },
9961
9962    _setPositionRelative: function() {
9963        if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
9964            this.element[ 0 ].style.position = "relative";
9965        }
9966    },
9967
9968    _adjustOffsetFromHelper: function( obj ) {
9969        if ( typeof obj === "string" ) {
9970            obj = obj.split( " " );
9971        }
9972        if ( Array.isArray( obj ) ) {
9973            obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
9974        }
9975        if ( "left" in obj ) {
9976            this.offset.click.left = obj.left + this.margins.left;
9977        }
9978        if ( "right" in obj ) {
9979            this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
9980        }
9981        if ( "top" in obj ) {
9982            this.offset.click.top = obj.top + this.margins.top;
9983        }
9984        if ( "bottom" in obj ) {
9985            this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
9986        }
9987    },
9988
9989    _isRootNode: function( element ) {
9990        return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
9991    },
9992
9993    _getParentOffset: function() {
9994
9995        //Get the offsetParent and cache its position
9996        var po = this.offsetParent.offset(),
9997            document = this.document[ 0 ];
9998
9999        // This is a special case where we need to modify a offset calculated on start, since the
10000        // following happened:
10001        // 1. The position of the helper is absolute, so it's position is calculated based on the
10002        // next positioned parent
10003        // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
10004        // the document, which means that the scroll is included in the initial calculation of the
10005        // offset of the parent, and never recalculated upon drag
10006        if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
10007                $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
10008            po.left += this.scrollParent.scrollLeft();
10009            po.top += this.scrollParent.scrollTop();
10010        }
10011
10012        if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
10013            po = { top: 0, left: 0 };
10014        }
10015
10016        return {
10017            top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
10018            left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
10019        };
10020
10021    },
10022
10023    _getRelativeOffset: function() {
10024        if ( this.cssPosition !== "relative" ) {
10025            return { top: 0, left: 0 };
10026        }
10027
10028        var p = this.element.position(),
10029            scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10030
10031        return {
10032            top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
10033                ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
10034            left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
10035                ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
10036        };
10037
10038    },
10039
10040    _cacheMargins: function() {
10041        this.margins = {
10042            left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
10043            top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
10044            right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
10045            bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
10046        };
10047    },
10048
10049    _cacheHelperProportions: function() {
10050        this.helperProportions = {
10051            width: this.helper.outerWidth(),
10052            height: this.helper.outerHeight()
10053        };
10054    },
10055
10056    _setContainment: function() {
10057
10058        var isUserScrollable, c, ce,
10059            o = this.options,
10060            document = this.document[ 0 ];
10061
10062        this.relativeContainer = null;
10063
10064        if ( !o.containment ) {
10065            this.containment = null;
10066            return;
10067        }
10068
10069        if ( o.containment === "window" ) {
10070            this.containment = [
10071                $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
10072                $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
10073                $( window ).scrollLeft() + $( window ).width() -
10074                    this.helperProportions.width - this.margins.left,
10075                $( window ).scrollTop() +
10076                    ( $( window ).height() || document.body.parentNode.scrollHeight ) -
10077                    this.helperProportions.height - this.margins.top
10078            ];
10079            return;
10080        }
10081
10082        if ( o.containment === "document" ) {
10083            this.containment = [
10084                0,
10085                0,
10086                $( document ).width() - this.helperProportions.width - this.margins.left,
10087                ( $( document ).height() || document.body.parentNode.scrollHeight ) -
10088                    this.helperProportions.height - this.margins.top
10089            ];
10090            return;
10091        }
10092
10093        if ( o.containment.constructor === Array ) {
10094            this.containment = o.containment;
10095            return;
10096        }
10097
10098        if ( o.containment === "parent" ) {
10099            o.containment = this.helper[ 0 ].parentNode;
10100        }
10101
10102        c = $( o.containment );
10103        ce = c[ 0 ];
10104
10105        if ( !ce ) {
10106            return;
10107        }
10108
10109        isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );
10110
10111        this.containment = [
10112            ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
10113                ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
10114            ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
10115                ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
10116            ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
10117                ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
10118                ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
10119                this.helperProportions.width -
10120                this.margins.left -
10121                this.margins.right,
10122            ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
10123                ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
10124                ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
10125                this.helperProportions.height -
10126                this.margins.top -
10127                this.margins.bottom
10128        ];
10129        this.relativeContainer = c;
10130    },
10131
10132    _convertPositionTo: function( d, pos ) {
10133
10134        if ( !pos ) {
10135            pos = this.position;
10136        }
10137
10138        var mod = d === "absolute" ? 1 : -1,
10139            scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );
10140
10141        return {
10142            top: (
10143
10144                // The absolute mouse position
10145                pos.top +
10146
10147                // Only for relative positioned nodes: Relative offset from element to offset parent
10148                this.offset.relative.top * mod +
10149
10150                // The offsetParent's offset without borders (offset + border)
10151                this.offset.parent.top * mod -
10152                ( ( this.cssPosition === "fixed" ?
10153                    -this.offset.scroll.top :
10154                    ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
10155            ),
10156            left: (
10157
10158                // The absolute mouse position
10159                pos.left +
10160
10161                // Only for relative positioned nodes: Relative offset from element to offset parent
10162                this.offset.relative.left * mod +
10163
10164                // The offsetParent's offset without borders (offset + border)
10165                this.offset.parent.left * mod   -
10166                ( ( this.cssPosition === "fixed" ?
10167                    -this.offset.scroll.left :
10168                    ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
10169            )
10170        };
10171
10172    },
10173
10174    _generatePosition: function( event, constrainPosition ) {
10175
10176        var containment, co, top, left,
10177            o = this.options,
10178            scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
10179            pageX = event.pageX,
10180            pageY = event.pageY;
10181
10182        // Cache the scroll
10183        if ( !scrollIsRootNode || !this.offset.scroll ) {
10184            this.offset.scroll = {
10185                top: this.scrollParent.scrollTop(),
10186                left: this.scrollParent.scrollLeft()
10187            };
10188        }
10189
10190        /*
10191         * - Position constraining -
10192         * Constrain the position to a mix of grid, containment.
10193         */
10194
10195        // If we are not dragging yet, we won't check for options
10196        if ( constrainPosition ) {
10197            if ( this.containment ) {
10198                if ( this.relativeContainer ) {
10199                    co = this.relativeContainer.offset();
10200                    containment = [
10201                        this.containment[ 0 ] + co.left,
10202                        this.containment[ 1 ] + co.top,
10203                        this.containment[ 2 ] + co.left,
10204                        this.containment[ 3 ] + co.top
10205                    ];
10206                } else {
10207                    containment = this.containment;
10208                }
10209
10210                if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
10211                    pageX = containment[ 0 ] + this.offset.click.left;
10212                }
10213                if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
10214                    pageY = containment[ 1 ] + this.offset.click.top;
10215                }
10216                if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
10217                    pageX = containment[ 2 ] + this.offset.click.left;
10218                }
10219                if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
10220                    pageY = containment[ 3 ] + this.offset.click.top;
10221                }
10222            }
10223
10224            if ( o.grid ) {
10225
10226                //Check for grid elements set to 0 to prevent divide by 0 error causing invalid
10227                // argument errors in IE (see ticket #6950)
10228                top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
10229                    this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
10230                pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
10231                    top - this.offset.click.top > containment[ 3 ] ) ?
10232                        top :
10233                        ( ( top - this.offset.click.top >= containment[ 1 ] ) ?
10234                            top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;
10235
10236                left = o.grid[ 0 ] ? this.originalPageX +
10237                    Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
10238                    this.originalPageX;
10239                pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
10240                    left - this.offset.click.left > containment[ 2 ] ) ?
10241                        left :
10242                        ( ( left - this.offset.click.left >= containment[ 0 ] ) ?
10243                            left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
10244            }
10245
10246            if ( o.axis === "y" ) {
10247                pageX = this.originalPageX;
10248            }
10249
10250            if ( o.axis === "x" ) {
10251                pageY = this.originalPageY;
10252            }
10253        }
10254
10255        return {
10256            top: (
10257
10258                // The absolute mouse position
10259                pageY -
10260
10261                // Click offset (relative to the element)
10262                this.offset.click.top -
10263
10264                // Only for relative positioned nodes: Relative offset from element to offset parent
10265                this.offset.relative.top -
10266
10267                // The offsetParent's offset without borders (offset + border)
10268                this.offset.parent.top +
10269                ( this.cssPosition === "fixed" ?
10270                    -this.offset.scroll.top :
10271                    ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
10272            ),
10273            left: (
10274
10275                // The absolute mouse position
10276                pageX -
10277
10278                // Click offset (relative to the element)
10279                this.offset.click.left -
10280
10281                // Only for relative positioned nodes: Relative offset from element to offset parent
10282                this.offset.relative.left -
10283
10284                // The offsetParent's offset without borders (offset + border)
10285                this.offset.parent.left +
10286                ( this.cssPosition === "fixed" ?
10287                    -this.offset.scroll.left :
10288                    ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
10289            )
10290        };
10291
10292    },
10293
10294    _clear: function() {
10295        this._removeClass( this.helper, "ui-draggable-dragging" );
10296        if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
10297            this.helper.remove();
10298        }
10299        this.helper = null;
10300        this.cancelHelperRemoval = false;
10301        if ( this.destroyOnClear ) {
10302            this.destroy();
10303        }
10304    },
10305
10306    // From now on bulk stuff - mainly helpers
10307
10308    _trigger: function( type, event, ui ) {
10309        ui = ui || this._uiHash();
10310        $.ui.plugin.call( this, type, [ event, ui, this ], true );
10311
10312        // Absolute position and offset (see #6884 ) have to be recalculated after plugins
10313        if ( /^(drag|start|stop)/.test( type ) ) {
10314            this.positionAbs = this._convertPositionTo( "absolute" );
10315            ui.offset = this.positionAbs;
10316        }
10317        return $.Widget.prototype._trigger.call( this, type, event, ui );
10318    },
10319
10320    plugins: {},
10321
10322    _uiHash: function() {
10323        return {
10324            helper: this.helper,
10325            position: this.position,
10326            originalPosition: this.originalPosition,
10327            offset: this.positionAbs
10328        };
10329    }
10330
10331} );
10332
10333$.ui.plugin.add( "draggable", "connectToSortable", {
10334    start: function( event, ui, draggable ) {
10335        var uiSortable = $.extend( {}, ui, {
10336            item: draggable.element
10337        } );
10338
10339        draggable.sortables = [];
10340        $( draggable.options.connectToSortable ).each( function() {
10341            var sortable = $( this ).sortable( "instance" );
10342
10343            if ( sortable && !sortable.options.disabled ) {
10344                draggable.sortables.push( sortable );
10345
10346                // RefreshPositions is called at drag start to refresh the containerCache
10347                // which is used in drag. This ensures it's initialized and synchronized
10348                // with any changes that might have happened on the page since initialization.
10349                sortable.refreshPositions();
10350                sortable._trigger( "activate", event, uiSortable );
10351            }
10352        } );
10353    },
10354    stop: function( event, ui, draggable ) {
10355        var uiSortable = $.extend( {}, ui, {
10356            item: draggable.element
10357        } );
10358
10359        draggable.cancelHelperRemoval = false;
10360
10361        $.each( draggable.sortables, function() {
10362            var sortable = this;
10363
10364            if ( sortable.isOver ) {
10365                sortable.isOver = 0;
10366
10367                // Allow this sortable to handle removing the helper
10368                draggable.cancelHelperRemoval = true;
10369                sortable.cancelHelperRemoval = false;
10370
10371                // Use _storedCSS To restore properties in the sortable,
10372                // as this also handles revert (#9675) since the draggable
10373                // may have modified them in unexpected ways (#8809)
10374                sortable._storedCSS = {
10375                    position: sortable.placeholder.css( "position" ),
10376                    top: sortable.placeholder.css( "top" ),
10377                    left: sortable.placeholder.css( "left" )
10378                };
10379
10380                sortable._mouseStop( event );
10381
10382                // Once drag has ended, the sortable should return to using
10383                // its original helper, not the shared helper from draggable
10384                sortable.options.helper = sortable.options._helper;
10385            } else {
10386
10387                // Prevent this Sortable from removing the helper.
10388                // However, don't set the draggable to remove the helper
10389                // either as another connected Sortable may yet handle the removal.
10390                sortable.cancelHelperRemoval = true;
10391
10392                sortable._trigger( "deactivate", event, uiSortable );
10393            }
10394        } );
10395    },
10396    drag: function( event, ui, draggable ) {
10397        $.each( draggable.sortables, function() {
10398            var innermostIntersecting = false,
10399                sortable = this;
10400
10401            // Copy over variables that sortable's _intersectsWith uses
10402            sortable.positionAbs = draggable.positionAbs;
10403            sortable.helperProportions = draggable.helperProportions;
10404            sortable.offset.click = draggable.offset.click;
10405
10406            if ( sortable._intersectsWith( sortable.containerCache ) ) {
10407                innermostIntersecting = true;
10408
10409                $.each( draggable.sortables, function() {
10410
10411                    // Copy over variables that sortable's _intersectsWith uses
10412                    this.positionAbs = draggable.positionAbs;
10413                    this.helperProportions = draggable.helperProportions;
10414                    this.offset.click = draggable.offset.click;
10415
10416                    if ( this !== sortable &&
10417                            this._intersectsWith( this.containerCache ) &&
10418                            $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
10419                        innermostIntersecting = false;
10420                    }
10421
10422                    return innermostIntersecting;
10423                } );
10424            }
10425
10426            if ( innermostIntersecting ) {
10427
10428                // If it intersects, we use a little isOver variable and set it once,
10429                // so that the move-in stuff gets fired only once.
10430                if ( !sortable.isOver ) {
10431                    sortable.isOver = 1;
10432
10433                    // Store draggable's parent in case we need to reappend to it later.
10434                    draggable._parent = ui.helper.parent();
10435
10436                    sortable.currentItem = ui.helper
10437                        .appendTo( sortable.element )
10438                        .data( "ui-sortable-item", true );
10439
10440                    // Store helper option to later restore it
10441                    sortable.options._helper = sortable.options.helper;
10442
10443                    sortable.options.helper = function() {
10444                        return ui.helper[ 0 ];
10445                    };
10446
10447                    // Fire the start events of the sortable with our passed browser event,
10448                    // and our own helper (so it doesn't create a new one)
10449                    event.target = sortable.currentItem[ 0 ];
10450                    sortable._mouseCapture( event, true );
10451                    sortable._mouseStart( event, true, true );
10452
10453                    // Because the browser event is way off the new appended portlet,
10454                    // modify necessary variables to reflect the changes
10455                    sortable.offset.click.top = draggable.offset.click.top;
10456                    sortable.offset.click.left = draggable.offset.click.left;
10457                    sortable.offset.parent.left -= draggable.offset.parent.left -
10458                        sortable.offset.parent.left;
10459                    sortable.offset.parent.top -= draggable.offset.parent.top -
10460                        sortable.offset.parent.top;
10461
10462                    draggable._trigger( "toSortable", event );
10463
10464                    // Inform draggable that the helper is in a valid drop zone,
10465                    // used solely in the revert option to handle "valid/invalid".
10466                    draggable.dropped = sortable.element;
10467
10468                    // Need to refreshPositions of all sortables in the case that
10469                    // adding to one sortable changes the location of the other sortables (#9675)
10470                    $.each( draggable.sortables, function() {
10471                        this.refreshPositions();
10472                    } );
10473
10474                    // Hack so receive/update callbacks work (mostly)
10475                    draggable.currentItem = draggable.element;
10476                    sortable.fromOutside = draggable;
10477                }
10478
10479                if ( sortable.currentItem ) {
10480                    sortable._mouseDrag( event );
10481
10482                    // Copy the sortable's position because the draggable's can potentially reflect
10483                    // a relative position, while sortable is always absolute, which the dragged
10484                    // element has now become. (#8809)
10485                    ui.position = sortable.position;
10486                }
10487            } else {
10488
10489                // If it doesn't intersect with the sortable, and it intersected before,
10490                // we fake the drag stop of the sortable, but make sure it doesn't remove
10491                // the helper by using cancelHelperRemoval.
10492                if ( sortable.isOver ) {
10493
10494                    sortable.isOver = 0;
10495                    sortable.cancelHelperRemoval = true;
10496
10497                    // Calling sortable's mouseStop would trigger a revert,
10498                    // so revert must be temporarily false until after mouseStop is called.
10499                    sortable.options._revert = sortable.options.revert;
10500                    sortable.options.revert = false;
10501
10502                    sortable._trigger( "out", event, sortable._uiHash( sortable ) );
10503                    sortable._mouseStop( event, true );
10504
10505                    // Restore sortable behaviors that were modfied
10506                    // when the draggable entered the sortable area (#9481)
10507                    sortable.options.revert = sortable.options._revert;
10508                    sortable.options.helper = sortable.options._helper;
10509
10510                    if ( sortable.placeholder ) {
10511                        sortable.placeholder.remove();
10512                    }
10513
10514                    // Restore and recalculate the draggable's offset considering the sortable
10515                    // may have modified them in unexpected ways. (#8809, #10669)
10516                    ui.helper.appendTo( draggable._parent );
10517                    draggable._refreshOffsets( event );
10518                    ui.position = draggable._generatePosition( event, true );
10519
10520                    draggable._trigger( "fromSortable", event );
10521
10522                    // Inform draggable that the helper is no longer in a valid drop zone
10523                    draggable.dropped = false;
10524
10525                    // Need to refreshPositions of all sortables just in case removing
10526                    // from one sortable changes the location of other sortables (#9675)
10527                    $.each( draggable.sortables, function() {
10528                        this.refreshPositions();
10529                    } );
10530                }
10531            }
10532        } );
10533    }
10534} );
10535
10536$.ui.plugin.add( "draggable", "cursor", {
10537    start: function( event, ui, instance ) {
10538        var t = $( "body" ),
10539            o = instance.options;
10540
10541        if ( t.css( "cursor" ) ) {
10542            o._cursor = t.css( "cursor" );
10543        }
10544        t.css( "cursor", o.cursor );
10545    },
10546    stop: function( event, ui, instance ) {
10547        var o = instance.options;
10548        if ( o._cursor ) {
10549            $( "body" ).css( "cursor", o._cursor );
10550        }
10551    }
10552} );
10553
10554$.ui.plugin.add( "draggable", "opacity", {
10555    start: function( event, ui, instance ) {
10556        var t = $( ui.helper ),
10557            o = instance.options;
10558        if ( t.css( "opacity" ) ) {
10559            o._opacity = t.css( "opacity" );
10560        }
10561        t.css( "opacity", o.opacity );
10562    },
10563    stop: function( event, ui, instance ) {
10564        var o = instance.options;
10565        if ( o._opacity ) {
10566            $( ui.helper ).css( "opacity", o._opacity );
10567        }
10568    }
10569} );
10570
10571$.ui.plugin.add( "draggable", "scroll", {
10572    start: function( event, ui, i ) {
10573        if ( !i.scrollParentNotHidden ) {
10574            i.scrollParentNotHidden = i.helper.scrollParent( false );
10575        }
10576
10577        if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
10578                i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
10579            i.overflowOffset = i.scrollParentNotHidden.offset();
10580        }
10581    },
10582    drag: function( event, ui, i  ) {
10583
10584        var o = i.options,
10585            scrolled = false,
10586            scrollParent = i.scrollParentNotHidden[ 0 ],
10587            document = i.document[ 0 ];
10588
10589        if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
10590            if ( !o.axis || o.axis !== "x" ) {
10591                if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
10592                        o.scrollSensitivity ) {
10593                    scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
10594                } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
10595                    scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
10596                }
10597            }
10598
10599            if ( !o.axis || o.axis !== "y" ) {
10600                if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
10601                        o.scrollSensitivity ) {
10602                    scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
10603                } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
10604                    scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
10605                }
10606            }
10607
10608        } else {
10609
10610            if ( !o.axis || o.axis !== "x" ) {
10611                if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
10612                    scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
10613                } else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
10614                        o.scrollSensitivity ) {
10615                    scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
10616                }
10617            }
10618
10619            if ( !o.axis || o.axis !== "y" ) {
10620                if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
10621                    scrolled = $( document ).scrollLeft(
10622                        $( document ).scrollLeft() - o.scrollSpeed
10623                    );
10624                } else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
10625                        o.scrollSensitivity ) {
10626                    scrolled = $( document ).scrollLeft(
10627                        $( document ).scrollLeft() + o.scrollSpeed
10628                    );
10629                }
10630            }
10631
10632        }
10633
10634        if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
10635            $.ui.ddmanager.prepareOffsets( i, event );
10636        }
10637
10638    }
10639} );
10640
10641$.ui.plugin.add( "draggable", "snap", {
10642    start: function( event, ui, i ) {
10643
10644        var o = i.options;
10645
10646        i.snapElements = [];
10647
10648        $( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
10649            .each( function() {
10650                var $t = $( this ),
10651                    $o = $t.offset();
10652                if ( this !== i.element[ 0 ] ) {
10653                    i.snapElements.push( {
10654                        item: this,
10655                        width: $t.outerWidth(), height: $t.outerHeight(),
10656                        top: $o.top, left: $o.left
10657                    } );
10658                }
10659            } );
10660
10661    },
10662    drag: function( event, ui, inst ) {
10663
10664        var ts, bs, ls, rs, l, r, t, b, i, first,
10665            o = inst.options,
10666            d = o.snapTolerance,
10667            x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
10668            y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;
10669
10670        for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {
10671
10672            l = inst.snapElements[ i ].left - inst.margins.left;
10673            r = l + inst.snapElements[ i ].width;
10674            t = inst.snapElements[ i ].top - inst.margins.top;
10675            b = t + inst.snapElements[ i ].height;
10676
10677            if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
10678                    !$.contains( inst.snapElements[ i ].item.ownerDocument,
10679                    inst.snapElements[ i ].item ) ) {
10680                if ( inst.snapElements[ i ].snapping ) {
10681                    if ( inst.options.snap.release ) {
10682                        inst.options.snap.release.call(
10683                            inst.element,
10684                            event,
10685                            $.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
10686                        );
10687                    }
10688                }
10689                inst.snapElements[ i ].snapping = false;
10690                continue;
10691            }
10692
10693            if ( o.snapMode !== "inner" ) {
10694                ts = Math.abs( t - y2 ) <= d;
10695                bs = Math.abs( b - y1 ) <= d;
10696                ls = Math.abs( l - x2 ) <= d;
10697                rs = Math.abs( r - x1 ) <= d;
10698                if ( ts ) {
10699                    ui.position.top = inst._convertPositionTo( "relative", {
10700                        top: t - inst.helperProportions.height,
10701                        left: 0
10702                    } ).top;
10703                }
10704                if ( bs ) {
10705                    ui.position.top = inst._convertPositionTo( "relative", {
10706                        top: b,
10707                        left: 0
10708                    } ).top;
10709                }
10710                if ( ls ) {
10711                    ui.position.left = inst._convertPositionTo( "relative", {
10712                        top: 0,
10713                        left: l - inst.helperProportions.width
10714                    } ).left;
10715                }
10716                if ( rs ) {
10717                    ui.position.left = inst._convertPositionTo( "relative", {
10718                        top: 0,
10719                        left: r
10720                    } ).left;
10721                }
10722            }
10723
10724            first = ( ts || bs || ls || rs );
10725
10726            if ( o.snapMode !== "outer" ) {
10727                ts = Math.abs( t - y1 ) <= d;
10728                bs = Math.abs( b - y2 ) <= d;
10729                ls = Math.abs( l - x1 ) <= d;
10730                rs = Math.abs( r - x2 ) <= d;
10731                if ( ts ) {
10732                    ui.position.top = inst._convertPositionTo( "relative", {
10733                        top: t,
10734                        left: 0
10735                    } ).top;
10736                }
10737                if ( bs ) {
10738                    ui.position.top = inst._convertPositionTo( "relative", {
10739                        top: b - inst.helperProportions.height,
10740                        left: 0
10741                    } ).top;
10742                }
10743                if ( ls ) {
10744                    ui.position.left = inst._convertPositionTo( "relative", {
10745                        top: 0,
10746                        left: l
10747                    } ).left;
10748                }
10749                if ( rs ) {
10750                    ui.position.left = inst._convertPositionTo( "relative", {
10751                        top: 0,
10752                        left: r - inst.helperProportions.width
10753                    } ).left;
10754                }
10755            }
10756
10757            if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
10758                if ( inst.options.snap.snap ) {
10759                    inst.options.snap.snap.call(
10760                        inst.element,
10761                        event,
10762                        $.extend( inst._uiHash(), {
10763                            snapItem: inst.snapElements[ i ].item
10764                        } ) );
10765                }
10766            }
10767            inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );
10768
10769        }
10770
10771    }
10772} );
10773
10774$.ui.plugin.add( "draggable", "stack", {
10775    start: function( event, ui, instance ) {
10776        var min,
10777            o = instance.options,
10778            group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
10779                return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
10780                    ( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
10781            } );
10782
10783        if ( !group.length ) {
10784            return;
10785        }
10786
10787        min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
10788        $( group ).each( function( i ) {
10789            $( this ).css( "zIndex", min + i );
10790        } );
10791        this.css( "zIndex", ( min + group.length ) );
10792    }
10793} );
10794
10795$.ui.plugin.add( "draggable", "zIndex", {
10796    start: function( event, ui, instance ) {
10797        var t = $( ui.helper ),
10798            o = instance.options;
10799
10800        if ( t.css( "zIndex" ) ) {
10801            o._zIndex = t.css( "zIndex" );
10802        }
10803        t.css( "zIndex", o.zIndex );
10804    },
10805    stop: function( event, ui, instance ) {
10806        var o = instance.options;
10807
10808        if ( o._zIndex ) {
10809            $( ui.helper ).css( "zIndex", o._zIndex );
10810        }
10811    }
10812} );
10813
10814var widgetsDraggable = $.ui.draggable;
10815
10816
10817/*!
10818 * jQuery UI Resizable 1.14.1
10819 * https://jqueryui.com
10820 *
10821 * Copyright OpenJS Foundation and other contributors
10822 * Released under the MIT license.
10823 * https://jquery.org/license
10824 */
10825
10826//>>label: Resizable
10827//>>group: Interactions
10828//>>description: Enables resize functionality for any element.
10829//>>docs: https://api.jqueryui.com/resizable/
10830//>>demos: https://jqueryui.com/resizable/
10831//>>css.structure: ../../themes/base/core.css
10832//>>css.structure: ../../themes/base/resizable.css
10833//>>css.theme: ../../themes/base/theme.css
10834
10835
10836$.widget( "ui.resizable", $.ui.mouse, {
10837    version: "1.14.1",
10838    widgetEventPrefix: "resize",
10839    options: {
10840        alsoResize: false,
10841        animate: false,
10842        animateDuration: "slow",
10843        animateEasing: "swing",
10844        aspectRatio: false,
10845        autoHide: false,
10846        classes: {
10847            "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
10848        },
10849        containment: false,
10850        ghost: false,
10851        grid: false,
10852        handles: "e,s,se",
10853        helper: false,
10854        maxHeight: null,
10855        maxWidth: null,
10856        minHeight: 10,
10857        minWidth: 10,
10858
10859        // See #7960
10860        zIndex: 90,
10861
10862        // Callbacks
10863        resize: null,
10864        start: null,
10865        stop: null
10866    },
10867
10868    _num: function( value ) {
10869        return parseFloat( value ) || 0;
10870    },
10871
10872    _isNumber: function( value ) {
10873        return !isNaN( parseFloat( value ) );
10874    },
10875
10876    _hasScroll: function( el, a ) {
10877
10878        var scroll,
10879            has = false,
10880            overflow = $( el ).css( "overflow" );
10881
10882        if ( overflow === "hidden" ) {
10883            return false;
10884        }
10885        if ( overflow === "scroll" ) {
10886            return true;
10887        }
10888
10889        scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop";
10890
10891        if ( el[ scroll ] > 0 ) {
10892            return true;
10893        }
10894
10895        // TODO: determine which cases actually cause this to happen
10896        // if the element doesn't have the scroll set, see if it's possible to
10897        // set the scroll
10898        try {
10899            el[ scroll ] = 1;
10900            has = ( el[ scroll ] > 0 );
10901            el[ scroll ] = 0;
10902        } catch ( e ) {
10903
10904            // `el` might be a string, then setting `scroll` will throw
10905            // an error in strict mode; ignore it.
10906        }
10907        return has;
10908    },
10909
10910    _create: function() {
10911
10912        var margins,
10913            o = this.options,
10914            that = this;
10915        this._addClass( "ui-resizable" );
10916
10917        $.extend( this, {
10918            _aspectRatio: !!( o.aspectRatio ),
10919            aspectRatio: o.aspectRatio,
10920            originalElement: this.element,
10921            _proportionallyResizeElements: [],
10922            _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
10923        } );
10924
10925        // Wrap the element if it cannot hold child nodes
10926        if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
10927
10928            this.element.wrap(
10929                $( "<div class='ui-wrapper'></div>" ).css( {
10930                    overflow: "hidden",
10931                    position: this.element.css( "position" ),
10932                    width: this.element.outerWidth(),
10933                    height: this.element.outerHeight(),
10934                    top: this.element.css( "top" ),
10935                    left: this.element.css( "left" )
10936                } )
10937            );
10938
10939            this.element = this.element.parent().data(
10940                "ui-resizable", this.element.resizable( "instance" )
10941            );
10942
10943            this.elementIsWrapper = true;
10944
10945            margins = {
10946                marginTop: this.originalElement.css( "marginTop" ),
10947                marginRight: this.originalElement.css( "marginRight" ),
10948                marginBottom: this.originalElement.css( "marginBottom" ),
10949                marginLeft: this.originalElement.css( "marginLeft" )
10950            };
10951
10952            this.element.css( margins );
10953
10954            // Support: Safari
10955            // Prevent Safari textarea resize
10956            this.originalResizeStyle = this.originalElement.css( "resize" );
10957            this.originalElement.css( "resize", "none" );
10958
10959            this._proportionallyResizeElements.push( this.originalElement.css( {
10960                position: "static",
10961                zoom: 1,
10962                display: "block"
10963            } ) );
10964
10965            this._proportionallyResize();
10966        }
10967
10968        this._setupHandles();
10969
10970        if ( o.autoHide ) {
10971            $( this.element )
10972                .on( "mouseenter", function() {
10973                    if ( o.disabled ) {
10974                        return;
10975                    }
10976                    that._removeClass( "ui-resizable-autohide" );
10977                    that._handles.show();
10978                } )
10979                .on( "mouseleave", function() {
10980                    if ( o.disabled ) {
10981                        return;
10982                    }
10983                    if ( !that.resizing ) {
10984                        that._addClass( "ui-resizable-autohide" );
10985                        that._handles.hide();
10986                    }
10987                } );
10988        }
10989
10990        this._mouseInit();
10991    },
10992
10993    _destroy: function() {
10994
10995        this._mouseDestroy();
10996        this._addedHandles.remove();
10997
10998        var wrapper,
10999            _destroy = function( exp ) {
11000                $( exp )
11001                    .removeData( "resizable" )
11002                    .removeData( "ui-resizable" )
11003                    .off( ".resizable" );
11004            };
11005
11006        // TODO: Unwrap at same DOM position
11007        if ( this.elementIsWrapper ) {
11008            _destroy( this.element );
11009            wrapper = this.element;
11010            this.originalElement.css( {
11011                position: wrapper.css( "position" ),
11012                width: wrapper.outerWidth(),
11013                height: wrapper.outerHeight(),
11014                top: wrapper.css( "top" ),
11015                left: wrapper.css( "left" )
11016            } ).insertAfter( wrapper );
11017            wrapper.remove();
11018        }
11019
11020        this.originalElement.css( "resize", this.originalResizeStyle );
11021        _destroy( this.originalElement );
11022
11023        return this;
11024    },
11025
11026    _setOption: function( key, value ) {
11027        this._super( key, value );
11028
11029        switch ( key ) {
11030        case "handles":
11031            this._removeHandles();
11032            this._setupHandles();
11033            break;
11034        case "aspectRatio":
11035            this._aspectRatio = !!value;
11036            break;
11037        default:
11038            break;
11039        }
11040    },
11041
11042    _setupHandles: function() {
11043        var o = this.options, handle, i, n, hname, axis, that = this;
11044        this.handles = o.handles ||
11045            ( !$( ".ui-resizable-handle", this.element ).length ?
11046                "e,s,se" : {
11047                    n: ".ui-resizable-n",
11048                    e: ".ui-resizable-e",
11049                    s: ".ui-resizable-s",
11050                    w: ".ui-resizable-w",
11051                    se: ".ui-resizable-se",
11052                    sw: ".ui-resizable-sw",
11053                    ne: ".ui-resizable-ne",
11054                    nw: ".ui-resizable-nw"
11055                } );
11056
11057        this._handles = $();
11058        this._addedHandles = $();
11059        if ( this.handles.constructor === String ) {
11060
11061            if ( this.handles === "all" ) {
11062                this.handles = "n,e,s,w,se,sw,ne,nw";
11063            }
11064
11065            n = this.handles.split( "," );
11066            this.handles = {};
11067
11068            for ( i = 0; i < n.length; i++ ) {
11069
11070                handle = String.prototype.trim.call( n[ i ] );
11071                hname = "ui-resizable-" + handle;
11072                axis = $( "<div>" );
11073                this._addClass( axis, "ui-resizable-handle " + hname );
11074
11075                axis.css( { zIndex: o.zIndex } );
11076
11077                this.handles[ handle ] = ".ui-resizable-" + handle;
11078                if ( !this.element.children( this.handles[ handle ] ).length ) {
11079                    this.element.append( axis );
11080                    this._addedHandles = this._addedHandles.add( axis );
11081                }
11082            }
11083
11084        }
11085
11086        this._renderAxis = function( target ) {
11087
11088            var i, axis, padPos, padWrapper;
11089
11090            target = target || this.element;
11091
11092            for ( i in this.handles ) {
11093
11094                if ( this.handles[ i ].constructor === String ) {
11095                    this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
11096                } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
11097                    this.handles[ i ] = $( this.handles[ i ] );
11098                    this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
11099                }
11100
11101                if ( this.elementIsWrapper &&
11102                        this.originalElement[ 0 ]
11103                            .nodeName
11104                            .match( /^(textarea|input|select|button)$/i ) ) {
11105                    axis = $( this.handles[ i ], this.element );
11106
11107                    padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
11108                        axis.outerHeight() :
11109                        axis.outerWidth();
11110
11111                    padPos = [ "padding",
11112                        /ne|nw|n/.test( i ) ? "Top" :
11113                        /se|sw|s/.test( i ) ? "Bottom" :
11114                        /^e$/.test( i ) ? "Right" : "Left" ].join( "" );
11115
11116                    target.css( padPos, padWrapper );
11117
11118                    this._proportionallyResize();
11119                }
11120
11121                this._handles = this._handles.add( this.handles[ i ] );
11122            }
11123        };
11124
11125        // TODO: make renderAxis a prototype function
11126        this._renderAxis( this.element );
11127
11128        this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
11129        this._handles.disableSelection();
11130
11131        this._handles.on( "mouseover", function() {
11132            if ( !that.resizing ) {
11133                if ( this.className ) {
11134                    axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
11135                }
11136                that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
11137            }
11138        } );
11139
11140        if ( o.autoHide ) {
11141            this._handles.hide();
11142            this._addClass( "ui-resizable-autohide" );
11143        }
11144    },
11145
11146    _removeHandles: function() {
11147        this._addedHandles.remove();
11148    },
11149
11150    _mouseCapture: function( event ) {
11151        var i, handle,
11152            capture = false;
11153
11154        for ( i in this.handles ) {
11155            handle = $( this.handles[ i ] )[ 0 ];
11156            if ( handle === event.target || $.contains( handle, event.target ) ) {
11157                capture = true;
11158            }
11159        }
11160
11161        return !this.options.disabled && capture;
11162    },
11163
11164    _mouseStart: function( event ) {
11165
11166        var curleft, curtop, cursor, calculatedSize,
11167            o = this.options,
11168            el = this.element;
11169
11170        this.resizing = true;
11171
11172        this._renderProxy();
11173
11174        curleft = this._num( this.helper.css( "left" ) );
11175        curtop = this._num( this.helper.css( "top" ) );
11176
11177        if ( o.containment ) {
11178            curleft += $( o.containment ).scrollLeft() || 0;
11179            curtop += $( o.containment ).scrollTop() || 0;
11180        }
11181
11182        this.offset = this.helper.offset();
11183        this.position = { left: curleft, top: curtop };
11184
11185        if ( !this._helper ) {
11186            calculatedSize = this._calculateAdjustedElementDimensions( el );
11187        }
11188
11189        this.size = this._helper ? {
11190                width: this.helper.width(),
11191                height: this.helper.height()
11192            } : {
11193                width: calculatedSize.width,
11194                height: calculatedSize.height
11195            };
11196
11197        this.originalSize = this._helper ? {
11198                width: el.outerWidth(),
11199                height: el.outerHeight()
11200            } : {
11201                width: calculatedSize.width,
11202                height: calculatedSize.height
11203            };
11204
11205        this.sizeDiff = {
11206            width: el.outerWidth() - el.width(),
11207            height: el.outerHeight() - el.height()
11208        };
11209
11210        this.originalPosition = { left: curleft, top: curtop };
11211        this.originalMousePosition = { left: event.pageX, top: event.pageY };
11212
11213        this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
11214            o.aspectRatio :
11215            ( ( this.originalSize.width / this.originalSize.height ) || 1 );
11216
11217        cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
11218        $( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
11219
11220        this._addClass( "ui-resizable-resizing" );
11221        this._propagate( "start", event );
11222        return true;
11223    },
11224
11225    _mouseDrag: function( event ) {
11226
11227        var data, props,
11228            smp = this.originalMousePosition,
11229            a = this.axis,
11230            dx = ( event.pageX - smp.left ) || 0,
11231            dy = ( event.pageY - smp.top ) || 0,
11232            trigger = this._change[ a ];
11233
11234        this._updatePrevProperties();
11235
11236        if ( !trigger ) {
11237            return false;
11238        }
11239
11240        data = trigger.apply( this, [ event, dx, dy ] );
11241
11242        this._updateVirtualBoundaries( event.shiftKey );
11243        if ( this._aspectRatio || event.shiftKey ) {
11244            data = this._updateRatio( data, event );
11245        }
11246
11247        data = this._respectSize( data, event );
11248
11249        this._updateCache( data );
11250
11251        this._propagate( "resize", event );
11252
11253        props = this._applyChanges();
11254
11255        if ( !this._helper && this._proportionallyResizeElements.length ) {
11256            this._proportionallyResize();
11257        }
11258
11259        if ( !$.isEmptyObject( props ) ) {
11260            this._updatePrevProperties();
11261            this._trigger( "resize", event, this.ui() );
11262            this._applyChanges();
11263        }
11264
11265        return false;
11266    },
11267
11268    _mouseStop: function( event ) {
11269
11270        this.resizing = false;
11271        var pr, ista, soffseth, soffsetw, s, left, top,
11272            o = this.options, that = this;
11273
11274        if ( this._helper ) {
11275
11276            pr = this._proportionallyResizeElements;
11277            ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
11278            soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
11279            soffsetw = ista ? 0 : that.sizeDiff.width;
11280
11281            s = {
11282                width: ( that.helper.width()  - soffsetw ),
11283                height: ( that.helper.height() - soffseth )
11284            };
11285            left = ( parseFloat( that.element.css( "left" ) ) +
11286                ( that.position.left - that.originalPosition.left ) ) || null;
11287            top = ( parseFloat( that.element.css( "top" ) ) +
11288                ( that.position.top - that.originalPosition.top ) ) || null;
11289
11290            if ( !o.animate ) {
11291                this.element.css( $.extend( s, { top: top, left: left } ) );
11292            }
11293
11294            that.helper.height( that.size.height );
11295            that.helper.width( that.size.width );
11296
11297            if ( this._helper && !o.animate ) {
11298                this._proportionallyResize();
11299            }
11300        }
11301
11302        $( "body" ).css( "cursor", "auto" );
11303
11304        this._removeClass( "ui-resizable-resizing" );
11305
11306        this._propagate( "stop", event );
11307
11308        if ( this._helper ) {
11309            this.helper.remove();
11310        }
11311
11312        return false;
11313
11314    },
11315
11316    _updatePrevProperties: function() {
11317        this.prevPosition = {
11318            top: this.position.top,
11319            left: this.position.left
11320        };
11321        this.prevSize = {
11322            width: this.size.width,
11323            height: this.size.height
11324        };
11325    },
11326
11327    _applyChanges: function() {
11328        var props = {};
11329
11330        if ( this.position.top !== this.prevPosition.top ) {
11331            props.top = this.position.top + "px";
11332        }
11333        if ( this.position.left !== this.prevPosition.left ) {
11334            props.left = this.position.left + "px";
11335        }
11336
11337        this.helper.css( props );
11338
11339        if ( this.size.width !== this.prevSize.width ) {
11340            props.width = this.size.width + "px";
11341            this.helper.width( props.width );
11342        }
11343        if ( this.size.height !== this.prevSize.height ) {
11344            props.height = this.size.height + "px";
11345            this.helper.height( props.height );
11346        }
11347
11348        return props;
11349    },
11350
11351    _updateVirtualBoundaries: function( forceAspectRatio ) {
11352        var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
11353            o = this.options;
11354
11355        b = {
11356            minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
11357            maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
11358            minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
11359            maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
11360        };
11361
11362        if ( this._aspectRatio || forceAspectRatio ) {
11363            pMinWidth = b.minHeight * this.aspectRatio;
11364            pMinHeight = b.minWidth / this.aspectRatio;
11365            pMaxWidth = b.maxHeight * this.aspectRatio;
11366            pMaxHeight = b.maxWidth / this.aspectRatio;
11367
11368            if ( pMinWidth > b.minWidth ) {
11369                b.minWidth = pMinWidth;
11370            }
11371            if ( pMinHeight > b.minHeight ) {
11372                b.minHeight = pMinHeight;
11373            }
11374            if ( pMaxWidth < b.maxWidth ) {
11375                b.maxWidth = pMaxWidth;
11376            }
11377            if ( pMaxHeight < b.maxHeight ) {
11378                b.maxHeight = pMaxHeight;
11379            }
11380        }
11381        this._vBoundaries = b;
11382    },
11383
11384    _updateCache: function( data ) {
11385        this.offset = this.helper.offset();
11386        if ( this._isNumber( data.left ) ) {
11387            this.position.left = data.left;
11388        }
11389        if ( this._isNumber( data.top ) ) {
11390            this.position.top = data.top;
11391        }
11392        if ( this._isNumber( data.height ) ) {
11393            this.size.height = data.height;
11394        }
11395        if ( this._isNumber( data.width ) ) {
11396            this.size.width = data.width;
11397        }
11398    },
11399
11400    _updateRatio: function( data ) {
11401
11402        var cpos = this.position,
11403            csize = this.size,
11404            a = this.axis;
11405
11406        if ( this._isNumber( data.height ) ) {
11407            data.width = ( data.height * this.aspectRatio );
11408        } else if ( this._isNumber( data.width ) ) {
11409            data.height = ( data.width / this.aspectRatio );
11410        }
11411
11412        if ( a === "sw" ) {
11413            data.left = cpos.left + ( csize.width - data.width );
11414            data.top = null;
11415        }
11416        if ( a === "nw" ) {
11417            data.top = cpos.top + ( csize.height - data.height );
11418            data.left = cpos.left + ( csize.width - data.width );
11419        }
11420
11421        return data;
11422    },
11423
11424    _respectSize: function( data ) {
11425
11426        var o = this._vBoundaries,
11427            a = this.axis,
11428            ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
11429            ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
11430            isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
11431            isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
11432            dw = this.originalPosition.left + this.originalSize.width,
11433            dh = this.originalPosition.top + this.originalSize.height,
11434            cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
11435        if ( isminw ) {
11436            data.width = o.minWidth;
11437        }
11438        if ( isminh ) {
11439            data.height = o.minHeight;
11440        }
11441        if ( ismaxw ) {
11442            data.width = o.maxWidth;
11443        }
11444        if ( ismaxh ) {
11445            data.height = o.maxHeight;
11446        }
11447
11448        if ( isminw && cw ) {
11449            data.left = dw - o.minWidth;
11450        }
11451        if ( ismaxw && cw ) {
11452            data.left = dw - o.maxWidth;
11453        }
11454        if ( isminh && ch ) {
11455            data.top = dh - o.minHeight;
11456        }
11457        if ( ismaxh && ch ) {
11458            data.top = dh - o.maxHeight;
11459        }
11460
11461        // Fixing jump error on top/left - bug #2330
11462        if ( !data.width && !data.height && !data.left && data.top ) {
11463            data.top = null;
11464        } else if ( !data.width && !data.height && !data.top && data.left ) {
11465            data.left = null;
11466        }
11467
11468        return data;
11469    },
11470
11471    _getPaddingPlusBorderDimensions: function( element ) {
11472        var i = 0,
11473            widths = [],
11474            borders = [
11475                element.css( "borderTopWidth" ),
11476                element.css( "borderRightWidth" ),
11477                element.css( "borderBottomWidth" ),
11478                element.css( "borderLeftWidth" )
11479            ],
11480            paddings = [
11481                element.css( "paddingTop" ),
11482                element.css( "paddingRight" ),
11483                element.css( "paddingBottom" ),
11484                element.css( "paddingLeft" )
11485            ];
11486
11487        for ( ; i < 4; i++ ) {
11488            widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
11489            widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
11490        }
11491
11492        return {
11493            height: widths[ 0 ] + widths[ 2 ],
11494            width: widths[ 1 ] + widths[ 3 ]
11495        };
11496    },
11497
11498    _calculateAdjustedElementDimensions: function( element ) {
11499        var elWidth, elHeight, paddingBorder,
11500            ce = element.get( 0 );
11501
11502        if ( element.css( "box-sizing" ) !== "content-box" ||
11503            ( !this._hasScroll( ce ) && !this._hasScroll( ce, "left" ) ) ) {
11504                return {
11505                    height: parseFloat( element.css( "height" ) ),
11506                    width: parseFloat( element.css( "width" ) )
11507                };
11508        }
11509
11510        // Check if CSS inline styles are set and use those (usually from previous resizes)
11511        elWidth = parseFloat( ce.style.width );
11512        elHeight = parseFloat( ce.style.height );
11513
11514        paddingBorder = this._getPaddingPlusBorderDimensions( element );
11515        elWidth = isNaN( elWidth ) ?
11516            this._getElementTheoreticalSize( element, paddingBorder, "width" ) :
11517            elWidth;
11518        elHeight = isNaN( elHeight ) ?
11519            this._getElementTheoreticalSize( element, paddingBorder, "height" ) :
11520            elHeight;
11521
11522        return {
11523            height: elHeight,
11524            width: elWidth
11525        };
11526    },
11527
11528    _getElementTheoreticalSize: function( element, extraSize, dimension ) {
11529
11530        // offsetWidth/offsetHeight is a rounded sum of content, padding, scroll gutter, and border
11531        var size = Math.max( 0, Math.ceil(
11532            element.get( 0 )[ "offset" + dimension[ 0 ].toUpperCase() + dimension.slice( 1 ) ] -
11533            extraSize[ dimension ] -
11534            0.5
11535
11536        // If offsetWidth/offsetHeight is unknown, then we can't determine theoretical size.
11537        // Use an explicit zero to avoid NaN.
11538        // See https://github.com/jquery/jquery/issues/3964
11539        ) ) || 0;
11540
11541        return size;
11542    },
11543
11544    _proportionallyResize: function() {
11545
11546        if ( !this._proportionallyResizeElements.length ) {
11547            return;
11548        }
11549
11550        var prel,
11551            i = 0,
11552            element = this.helper || this.element;
11553
11554        for ( ; i < this._proportionallyResizeElements.length; i++ ) {
11555
11556            prel = this._proportionallyResizeElements[ i ];
11557
11558            // TODO: Seems like a bug to cache this.outerDimensions
11559            // considering that we are in a loop.
11560            if ( !this.outerDimensions ) {
11561                this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
11562            }
11563
11564            prel.css( {
11565                height: ( element.height() - this.outerDimensions.height ) || 0,
11566                width: ( element.width() - this.outerDimensions.width ) || 0
11567            } );
11568
11569        }
11570
11571    },
11572
11573    _renderProxy: function() {
11574
11575        var el = this.element, o = this.options;
11576        this.elementOffset = el.offset();
11577
11578        if ( this._helper ) {
11579
11580            this.helper = this.helper || $( "<div></div>" ).css( { overflow: "hidden" } );
11581
11582            this._addClass( this.helper, this._helper );
11583            this.helper.css( {
11584                width: this.element.outerWidth(),
11585                height: this.element.outerHeight(),
11586                position: "absolute",
11587                left: this.elementOffset.left + "px",
11588                top: this.elementOffset.top + "px",
11589                zIndex: ++o.zIndex //TODO: Don't modify option
11590            } );
11591
11592            this.helper
11593                .appendTo( "body" )
11594                .disableSelection();
11595
11596        } else {
11597            this.helper = this.element;
11598        }
11599
11600    },
11601
11602    _change: {
11603        e: function( event, dx ) {
11604            return { width: this.originalSize.width + dx };
11605        },
11606        w: function( event, dx ) {
11607            var cs = this.originalSize, sp = this.originalPosition;
11608            return { left: sp.left + dx, width: cs.width - dx };
11609        },
11610        n: function( event, dx, dy ) {
11611            var cs = this.originalSize, sp = this.originalPosition;
11612            return { top: sp.top + dy, height: cs.height - dy };
11613        },
11614        s: function( event, dx, dy ) {
11615            return { height: this.originalSize.height + dy };
11616        },
11617        se: function( event, dx, dy ) {
11618            return $.extend( this._change.s.apply( this, arguments ),
11619                this._change.e.apply( this, [ event, dx, dy ] ) );
11620        },
11621        sw: function( event, dx, dy ) {
11622            return $.extend( this._change.s.apply( this, arguments ),
11623                this._change.w.apply( this, [ event, dx, dy ] ) );
11624        },
11625        ne: function( event, dx, dy ) {
11626            return $.extend( this._change.n.apply( this, arguments ),
11627                this._change.e.apply( this, [ event, dx, dy ] ) );
11628        },
11629        nw: function( event, dx, dy ) {
11630            return $.extend( this._change.n.apply( this, arguments ),
11631                this._change.w.apply( this, [ event, dx, dy ] ) );
11632        }
11633    },
11634
11635    _propagate: function( n, event ) {
11636        $.ui.plugin.call( this, n, [ event, this.ui() ] );
11637        if ( n !== "resize" ) {
11638            this._trigger( n, event, this.ui() );
11639        }
11640    },
11641
11642    plugins: {},
11643
11644    ui: function() {
11645        return {
11646            originalElement: this.originalElement,
11647            element: this.element,
11648            helper: this.helper,
11649            position: this.position,
11650            size: this.size,
11651            originalSize: this.originalSize,
11652            originalPosition: this.originalPosition
11653        };
11654    }
11655
11656} );
11657
11658/*
11659 * Resizable Extensions
11660 */
11661
11662$.ui.plugin.add( "resizable", "animate", {
11663
11664    stop: function( event ) {
11665        var that = $( this ).resizable( "instance" ),
11666            o = that.options,
11667            pr = that._proportionallyResizeElements,
11668            ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
11669            soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
11670            soffsetw = ista ? 0 : that.sizeDiff.width,
11671            style = {
11672                width: ( that.size.width - soffsetw ),
11673                height: ( that.size.height - soffseth )
11674            },
11675            left = ( parseFloat( that.element.css( "left" ) ) +
11676                ( that.position.left - that.originalPosition.left ) ) || null,
11677            top = ( parseFloat( that.element.css( "top" ) ) +
11678                ( that.position.top - that.originalPosition.top ) ) || null;
11679
11680        that.element.animate(
11681            $.extend( style, top && left ? { top: top, left: left } : {} ), {
11682                duration: o.animateDuration,
11683                easing: o.animateEasing,
11684                step: function() {
11685
11686                    var data = {
11687                        width: parseFloat( that.element.css( "width" ) ),
11688                        height: parseFloat( that.element.css( "height" ) ),
11689                        top: parseFloat( that.element.css( "top" ) ),
11690                        left: parseFloat( that.element.css( "left" ) )
11691                    };
11692
11693                    if ( pr && pr.length ) {
11694                        $( pr[ 0 ] ).css( { width: data.width, height: data.height } );
11695                    }
11696
11697                    // Propagating resize, and updating values for each animation step
11698                    that._updateCache( data );
11699                    that._propagate( "resize", event );
11700
11701                }
11702            }
11703        );
11704    }
11705
11706} );
11707
11708$.ui.plugin.add( "resizable", "containment", {
11709
11710    start: function() {
11711        var element, p, co, ch, cw, width, height,
11712            that = $( this ).resizable( "instance" ),
11713            o = that.options,
11714            el = that.element,
11715            oc = o.containment,
11716            ce = ( oc instanceof $ ) ?
11717                oc.get( 0 ) :
11718                ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
11719
11720        if ( !ce ) {
11721            return;
11722        }
11723
11724        that.containerElement = $( ce );
11725
11726        if ( /document/.test( oc ) || oc === document ) {
11727            that.containerOffset = {
11728                left: 0,
11729                top: 0
11730            };
11731            that.containerPosition = {
11732                left: 0,
11733                top: 0
11734            };
11735
11736            that.parentData = {
11737                element: $( document ),
11738                left: 0,
11739                top: 0,
11740                width: $( document ).width(),
11741                height: $( document ).height() || document.body.parentNode.scrollHeight
11742            };
11743        } else {
11744            element = $( ce );
11745            p = [];
11746            $( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
11747                p[ i ] = that._num( element.css( "padding" + name ) );
11748            } );
11749
11750            that.containerOffset = element.offset();
11751            that.containerPosition = element.position();
11752            that.containerSize = {
11753                height: ( element.innerHeight() - p[ 3 ] ),
11754                width: ( element.innerWidth() - p[ 1 ] )
11755            };
11756
11757            co = that.containerOffset;
11758            ch = that.containerSize.height;
11759            cw = that.containerSize.width;
11760            width = ( that._hasScroll( ce, "left" ) ? ce.scrollWidth : cw );
11761            height = ( that._hasScroll( ce ) ? ce.scrollHeight : ch );
11762
11763            that.parentData = {
11764                element: ce,
11765                left: co.left,
11766                top: co.top,
11767                width: width,
11768                height: height
11769            };
11770        }
11771    },
11772
11773    resize: function( event ) {
11774        var woset, hoset, isParent, isOffsetRelative,
11775            that = $( this ).resizable( "instance" ),
11776            o = that.options,
11777            co = that.containerOffset,
11778            cp = that.position,
11779            pRatio = that._aspectRatio || event.shiftKey,
11780            cop = {
11781                top: 0,
11782                left: 0
11783            },
11784            ce = that.containerElement,
11785            continueResize = true;
11786
11787        if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
11788            cop = co;
11789        }
11790
11791        if ( cp.left < ( that._helper ? co.left : 0 ) ) {
11792            that.size.width = that.size.width +
11793                ( that._helper ?
11794                    ( that.position.left - co.left ) :
11795                    ( that.position.left - cop.left ) );
11796
11797            if ( pRatio ) {
11798                that.size.height = that.size.width / that.aspectRatio;
11799                continueResize = false;
11800            }
11801            that.position.left = o.helper ? co.left : 0;
11802        }
11803
11804        if ( cp.top < ( that._helper ? co.top : 0 ) ) {
11805            that.size.height = that.size.height +
11806                ( that._helper ?
11807                    ( that.position.top - co.top ) :
11808                    that.position.top );
11809
11810            if ( pRatio ) {
11811                that.size.width = that.size.height * that.aspectRatio;
11812                continueResize = false;
11813            }
11814            that.position.top = that._helper ? co.top : 0;
11815        }
11816
11817        isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
11818        isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
11819
11820        if ( isParent && isOffsetRelative ) {
11821            that.offset.left = that.parentData.left + that.position.left;
11822            that.offset.top = that.parentData.top + that.position.top;
11823        } else {
11824            that.offset.left = that.element.offset().left;
11825            that.offset.top = that.element.offset().top;
11826        }
11827
11828        woset = Math.abs( that.sizeDiff.width +
11829            ( that._helper ?
11830                that.offset.left - cop.left :
11831                ( that.offset.left - co.left ) ) );
11832
11833        hoset = Math.abs( that.sizeDiff.height +
11834            ( that._helper ?
11835                that.offset.top - cop.top :
11836                ( that.offset.top - co.top ) ) );
11837
11838        if ( woset + that.size.width >= that.parentData.width ) {
11839            that.size.width = that.parentData.width - woset;
11840            if ( pRatio ) {
11841                that.size.height = that.size.width / that.aspectRatio;
11842                continueResize = false;
11843            }
11844        }
11845
11846        if ( hoset + that.size.height >= that.parentData.height ) {
11847            that.size.height = that.parentData.height - hoset;
11848            if ( pRatio ) {
11849                that.size.width = that.size.height * that.aspectRatio;
11850                continueResize = false;
11851            }
11852        }
11853
11854        if ( !continueResize ) {
11855            that.position.left = that.prevPosition.left;
11856            that.position.top = that.prevPosition.top;
11857            that.size.width = that.prevSize.width;
11858            that.size.height = that.prevSize.height;
11859        }
11860    },
11861
11862    stop: function() {
11863        var that = $( this ).resizable( "instance" ),
11864            o = that.options,
11865            co = that.containerOffset,
11866            cop = that.containerPosition,
11867            ce = that.containerElement,
11868            helper = $( that.helper ),
11869            ho = helper.offset(),
11870            w = helper.outerWidth() - that.sizeDiff.width,
11871            h = helper.outerHeight() - that.sizeDiff.height;
11872
11873        if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
11874            $( this ).css( {
11875                left: ho.left - cop.left - co.left,
11876                width: w,
11877                height: h
11878            } );
11879        }
11880
11881        if ( that._helper && !o.animate && ( /static/ ).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} );
11890
11891$.ui.plugin.add( "resizable", "alsoResize", {
11892
11893    start: function() {
11894        var that = $( this ).resizable( "instance" ),
11895            o = that.options;
11896
11897        $( o.alsoResize ).each( function() {
11898            var el = $( this ),
11899                elSize = that._calculateAdjustedElementDimensions( el );
11900
11901            el.data( "ui-resizable-alsoresize", {
11902                width: elSize.width, height: elSize.height,
11903                left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
11904            } );
11905        } );
11906    },
11907
11908    resize: function( event, ui ) {
11909        var that = $( this ).resizable( "instance" ),
11910            o = that.options,
11911            os = that.originalSize,
11912            op = that.originalPosition,
11913            delta = {
11914                height: ( that.size.height - os.height ) || 0,
11915                width: ( that.size.width - os.width ) || 0,
11916                top: ( that.position.top - op.top ) || 0,
11917                left: ( that.position.left - op.left ) || 0
11918            };
11919
11920            $( o.alsoResize ).each( function() {
11921                var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
11922                    css = el.parents( ui.originalElement[ 0 ] ).length ?
11923                            [ "width", "height" ] :
11924                            [ "width", "height", "top", "left" ];
11925
11926                $.each( css, function( i, prop ) {
11927                    var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
11928                    if ( sum && sum >= 0 ) {
11929                        style[ prop ] = sum || null;
11930                    }
11931                } );
11932
11933                el.css( style );
11934            } );
11935    },
11936
11937    stop: function() {
11938        $( this ).removeData( "ui-resizable-alsoresize" );
11939    }
11940} );
11941
11942$.ui.plugin.add( "resizable", "ghost", {
11943
11944    start: function() {
11945
11946        var that = $( this ).resizable( "instance" ), cs = that.size;
11947
11948        that.ghost = that.originalElement.clone();
11949        that.ghost.css( {
11950            opacity: 0.25,
11951            display: "block",
11952            position: "relative",
11953            height: cs.height,
11954            width: cs.width,
11955            margin: 0,
11956            left: 0,
11957            top: 0
11958        } );
11959
11960        that._addClass( that.ghost, "ui-resizable-ghost" );
11961
11962        // DEPRECATED
11963        // TODO: remove after 1.12
11964        if ( $.uiBackCompat === true && typeof that.options.ghost === "string" ) {
11965
11966            // Ghost option
11967            that.ghost.addClass( this.options.ghost );
11968        }
11969
11970        that.ghost.appendTo( that.helper );
11971
11972    },
11973
11974    resize: function() {
11975        var that = $( this ).resizable( "instance" );
11976        if ( that.ghost ) {
11977            that.ghost.css( {
11978                position: "relative",
11979                height: that.size.height,
11980                width: that.size.width
11981            } );
11982        }
11983    },
11984
11985    stop: function() {
11986        var that = $( this ).resizable( "instance" );
11987        if ( that.ghost && that.helper ) {
11988            that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
11989        }
11990    }
11991
11992} );
11993
11994$.ui.plugin.add( "resizable", "grid", {
11995
11996    resize: function() {
11997        var outerDimensions,
11998            that = $( this ).resizable( "instance" ),
11999            o = that.options,
12000            cs = that.size,
12001            os = that.originalSize,
12002            op = that.originalPosition,
12003            a = that.axis,
12004            grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
12005            gridX = ( grid[ 0 ] || 1 ),
12006            gridY = ( grid[ 1 ] || 1 ),
12007            ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
12008            oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
12009            newWidth = os.width + ox,
12010            newHeight = os.height + oy,
12011            isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
12012            isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
12013            isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
12014            isMinHeight = o.minHeight && ( o.minHeight > newHeight );
12015
12016        o.grid = grid;
12017
12018        if ( isMinWidth ) {
12019            newWidth += gridX;
12020        }
12021        if ( isMinHeight ) {
12022            newHeight += gridY;
12023        }
12024        if ( isMaxWidth ) {
12025            newWidth -= gridX;
12026        }
12027        if ( isMaxHeight ) {
12028            newHeight -= gridY;
12029        }
12030
12031        if ( /^(se|s|e)$/.test( a ) ) {
12032            that.size.width = newWidth;
12033            that.size.height = newHeight;
12034        } else if ( /^(ne)$/.test( a ) ) {
12035            that.size.width = newWidth;
12036            that.size.height = newHeight;
12037            that.position.top = op.top - oy;
12038        } else if ( /^(sw)$/.test( a ) ) {
12039            that.size.width = newWidth;
12040            that.size.height = newHeight;
12041            that.position.left = op.left - ox;
12042        } else {
12043            if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
12044                outerDimensions = that._getPaddingPlusBorderDimensions( this );
12045            }
12046
12047            if ( newHeight - gridY > 0 ) {
12048                that.size.height = newHeight;
12049                that.position.top = op.top - oy;
12050            } else {
12051                newHeight = gridY - outerDimensions.height;
12052                that.size.height = newHeight;
12053                that.position.top = op.top + os.height - newHeight;
12054            }
12055            if ( newWidth - gridX > 0 ) {
12056                that.size.width = newWidth;
12057                that.position.left = op.left - ox;
12058            } else {
12059                newWidth = gridX - outerDimensions.width;
12060                that.size.width = newWidth;
12061                that.position.left = op.left + os.width - newWidth;
12062            }
12063        }
12064    }
12065
12066} );
12067
12068var widgetsResizable = $.ui.resizable;
12069
12070
12071/*!
12072 * jQuery UI Dialog 1.14.1
12073 * https://jqueryui.com
12074 *
12075 * Copyright OpenJS Foundation and other contributors
12076 * Released under the MIT license.
12077 * https://jquery.org/license
12078 */
12079
12080//>>label: Dialog
12081//>>group: Widgets
12082//>>description: Displays customizable dialog windows.
12083//>>docs: https://api.jqueryui.com/dialog/
12084//>>demos: https://jqueryui.com/dialog/
12085//>>css.structure: ../../themes/base/core.css
12086//>>css.structure: ../../themes/base/dialog.css
12087//>>css.theme: ../../themes/base/theme.css
12088
12089
12090$.widget( "ui.dialog", {
12091    version: "1.14.1",
12092    options: {
12093        appendTo: "body",
12094        autoOpen: true,
12095        buttons: [],
12096        classes: {
12097            "ui-dialog": "ui-corner-all",
12098            "ui-dialog-titlebar": "ui-corner-all"
12099        },
12100        closeOnEscape: true,
12101        closeText: "Close",
12102        draggable: true,
12103        hide: null,
12104        height: "auto",
12105        maxHeight: null,
12106        maxWidth: null,
12107        minHeight: 150,
12108        minWidth: 150,
12109        modal: false,
12110        position: {
12111            my: "center",
12112            at: "center",
12113            of: window,
12114            collision: "fit",
12115
12116            // Ensure the titlebar is always visible
12117            using: function( pos ) {
12118                var topOffset = $( this ).css( pos ).offset().top;
12119                if ( topOffset < 0 ) {
12120                    $( this ).css( "top", pos.top - topOffset );
12121                }
12122            }
12123        },
12124        resizable: true,
12125        show: null,
12126        title: null,
12127        uiDialogTitleHeadingLevel: 0,
12128        width: 300,
12129
12130        // Callbacks
12131        beforeClose: null,
12132        close: null,
12133        drag: null,
12134        dragStart: null,
12135        dragStop: null,
12136        focus: null,
12137        open: null,
12138        resize: null,
12139        resizeStart: null,
12140        resizeStop: null
12141    },
12142
12143    sizeRelatedOptions: {
12144        buttons: true,
12145        height: true,
12146        maxHeight: true,
12147        maxWidth: true,
12148        minHeight: true,
12149        minWidth: true,
12150        width: true
12151    },
12152
12153    resizableRelatedOptions: {
12154        maxHeight: true,
12155        maxWidth: true,
12156        minHeight: true,
12157        minWidth: true
12158    },
12159
12160    _create: function() {
12161        this.originalCss = {
12162            display: this.element[ 0 ].style.display,
12163            width: this.element[ 0 ].style.width,
12164            minHeight: this.element[ 0 ].style.minHeight,
12165            maxHeight: this.element[ 0 ].style.maxHeight,
12166            height: this.element[ 0 ].style.height
12167        };
12168        this.originalPosition = {
12169            parent: this.element.parent(),
12170            index: this.element.parent().children().index( this.element )
12171        };
12172        this.originalTitle = this.element.attr( "title" );
12173        if ( this.options.title == null && this.originalTitle != null ) {
12174            this.options.title = this.originalTitle;
12175        }
12176
12177        // Dialogs can't be disabled
12178        if ( this.options.disabled ) {
12179            this.options.disabled = false;
12180        }
12181
12182        this._createWrapper();
12183
12184        this.element
12185            .show()
12186            .removeAttr( "title" )
12187            .appendTo( this.uiDialog );
12188
12189        this._addClass( "ui-dialog-content", "ui-widget-content" );
12190
12191        this._createTitlebar();
12192        this._createButtonPane();
12193
12194        if ( this.options.draggable && $.fn.draggable ) {
12195            this._makeDraggable();
12196        }
12197        if ( this.options.resizable && $.fn.resizable ) {
12198            this._makeResizable();
12199        }
12200
12201        this._isOpen = false;
12202
12203        this._trackFocus();
12204    },
12205
12206    _init: function() {
12207        if ( this.options.autoOpen ) {
12208            this.open();
12209        }
12210    },
12211
12212    _appendTo: function() {
12213        var element = this.options.appendTo;
12214        if ( element && ( element.jquery || element.nodeType ) ) {
12215            return $( element );
12216        }
12217        return this.document.find( element || "body" ).eq( 0 );
12218    },
12219
12220    _destroy: function() {
12221        var next,
12222            originalPosition = this.originalPosition;
12223
12224        this._untrackInstance();
12225        this._destroyOverlay();
12226
12227        this.element
12228            .removeUniqueId()
12229            .css( this.originalCss )
12230
12231            // Without detaching first, the following becomes really slow
12232            .detach();
12233
12234        this.uiDialog.remove();
12235
12236        if ( this.originalTitle ) {
12237            this.element.attr( "title", this.originalTitle );
12238        }
12239
12240        next = originalPosition.parent.children().eq( originalPosition.index );
12241
12242        // Don't try to place the dialog next to itself (#8613)
12243        if ( next.length && next[ 0 ] !== this.element[ 0 ] ) {
12244            next.before( this.element );
12245        } else {
12246            originalPosition.parent.append( this.element );
12247        }
12248    },
12249
12250    widget: function() {
12251        return this.uiDialog;
12252    },
12253
12254    disable: $.noop,
12255    enable: $.noop,
12256
12257    close: function( event ) {
12258        var that = this;
12259
12260        if ( !this._isOpen || this._trigger( "beforeClose", event ) === false ) {
12261            return;
12262        }
12263
12264        this._isOpen = false;
12265        this._focusedElement = null;
12266        this._destroyOverlay();
12267        this._untrackInstance();
12268
12269        if ( !this.opener.filter( ":focusable" ).trigger( "focus" ).length ) {
12270
12271            // Hiding a focused element doesn't trigger blur in WebKit
12272            // so in case we have nothing to focus on, explicitly blur the active element
12273            // https://bugs.webkit.org/show_bug.cgi?id=47182
12274            $( this.document[ 0 ].activeElement ).trigger( "blur" );
12275        }
12276
12277        this._hide( this.uiDialog, this.options.hide, function() {
12278            that._trigger( "close", event );
12279        } );
12280    },
12281
12282    isOpen: function() {
12283        return this._isOpen;
12284    },
12285
12286    moveToTop: function() {
12287        this._moveToTop();
12288    },
12289
12290    _moveToTop: function( event, silent ) {
12291        var moved = false,
12292            zIndices = this.uiDialog.siblings( ".ui-front:visible" ).map( function() {
12293                return +$( this ).css( "z-index" );
12294            } ).get(),
12295            zIndexMax = Math.max.apply( null, zIndices );
12296
12297        if ( zIndexMax >= +this.uiDialog.css( "z-index" ) ) {
12298            this.uiDialog.css( "z-index", zIndexMax + 1 );
12299            moved = true;
12300        }
12301
12302        if ( moved && !silent ) {
12303            this._trigger( "focus", event );
12304        }
12305        return moved;
12306    },
12307
12308    open: function() {
12309        var that = this;
12310        if ( this._isOpen ) {
12311            if ( this._moveToTop() ) {
12312                this._focusTabbable();
12313            }
12314            return;
12315        }
12316
12317        this._isOpen = true;
12318        this.opener = $( this.document[ 0 ].activeElement );
12319
12320        this._size();
12321        this._position();
12322        this._createOverlay();
12323        this._moveToTop( null, true );
12324
12325        // Ensure the overlay is moved to the top with the dialog, but only when
12326        // opening. The overlay shouldn't move after the dialog is open so that
12327        // modeless dialogs opened after the modal dialog stack properly.
12328        if ( this.overlay ) {
12329            this.overlay.css( "z-index", this.uiDialog.css( "z-index" ) - 1 );
12330        }
12331
12332        this._show( this.uiDialog, this.options.show, function() {
12333            that._focusTabbable();
12334            that._trigger( "focus" );
12335        } );
12336
12337        // Track the dialog immediately upon opening in case a focus event
12338        // somehow occurs outside of the dialog before an element inside the
12339        // dialog is focused (#10152)
12340        this._makeFocusTarget();
12341
12342        this._trigger( "open" );
12343    },
12344
12345    _focusTabbable: function() {
12346
12347        // Set focus to the first match:
12348        // 1. An element that was focused previously
12349        // 2. First element inside the dialog matching [autofocus]
12350        // 3. Tabbable element inside the content element
12351        // 4. Tabbable element inside the buttonpane
12352        // 5. The close button
12353        // 6. The dialog itself
12354        var hasFocus = this._focusedElement;
12355        if ( !hasFocus ) {
12356            hasFocus = this.element.find( "[autofocus]" );
12357        }
12358        if ( !hasFocus.length ) {
12359            hasFocus = this.element.find( ":tabbable" );
12360        }
12361        if ( !hasFocus.length ) {
12362            hasFocus = this.uiDialogButtonPane.find( ":tabbable" );
12363        }
12364        if ( !hasFocus.length ) {
12365            hasFocus = this.uiDialogTitlebarClose.filter( ":tabbable" );
12366        }
12367        if ( !hasFocus.length ) {
12368            hasFocus = this.uiDialog;
12369        }
12370        hasFocus.eq( 0 ).trigger( "focus" );
12371    },
12372
12373    _restoreTabbableFocus: function() {
12374        var activeElement = this.document[ 0 ].activeElement,
12375            isActive = this.uiDialog[ 0 ] === activeElement ||
12376                $.contains( this.uiDialog[ 0 ], activeElement );
12377        if ( !isActive ) {
12378            this._focusTabbable();
12379        }
12380    },
12381
12382    _keepFocus: function( event ) {
12383        event.preventDefault();
12384        this._restoreTabbableFocus();
12385    },
12386
12387    _createWrapper: function() {
12388        this.uiDialog = $( "<div>" )
12389            .hide()
12390            .attr( {
12391
12392                // Setting tabIndex makes the div focusable
12393                tabIndex: -1,
12394                role: "dialog",
12395                "aria-modal": this.options.modal ? "true" : null
12396            } )
12397            .appendTo( this._appendTo() );
12398
12399        this._addClass( this.uiDialog, "ui-dialog", "ui-widget ui-widget-content ui-front" );
12400        this._on( this.uiDialog, {
12401            keydown: function( event ) {
12402                if ( this.options.closeOnEscape && !event.isDefaultPrevented() && event.keyCode &&
12403                        event.keyCode === $.ui.keyCode.ESCAPE ) {
12404                    event.preventDefault();
12405                    this.close( event );
12406                    return;
12407                }
12408
12409                // Prevent tabbing out of dialogs
12410                if ( event.keyCode !== $.ui.keyCode.TAB || event.isDefaultPrevented() ) {
12411                    return;
12412                }
12413                var tabbables = this.uiDialog.find( ":tabbable" ),
12414                    first = tabbables.first(),
12415                    last = tabbables.last();
12416
12417                if ( ( event.target === last[ 0 ] || event.target === this.uiDialog[ 0 ] ) &&
12418                        !event.shiftKey ) {
12419                    this._delay( function() {
12420                        first.trigger( "focus" );
12421                    } );
12422                    event.preventDefault();
12423                } else if ( ( event.target === first[ 0 ] ||
12424                        event.target === this.uiDialog[ 0 ] ) && event.shiftKey ) {
12425                    this._delay( function() {
12426                        last.trigger( "focus" );
12427                    } );
12428                    event.preventDefault();
12429                }
12430            },
12431            mousedown: function( event ) {
12432                if ( this._moveToTop( event ) ) {
12433                    this._focusTabbable();
12434                }
12435            }
12436        } );
12437
12438        // We assume that any existing aria-describedby attribute means
12439        // that the dialog content is marked up properly
12440        // otherwise we brute force the content as the description
12441        if ( !this.element.find( "[aria-describedby]" ).length ) {
12442            this.uiDialog.attr( {
12443                "aria-describedby": this.element.uniqueId().attr( "id" )
12444            } );
12445        }
12446    },
12447
12448    _createTitlebar: function() {
12449        var uiDialogTitle;
12450
12451        this.uiDialogTitlebar = $( "<div>" );
12452        this._addClass( this.uiDialogTitlebar,
12453            "ui-dialog-titlebar", "ui-widget-header ui-helper-clearfix" );
12454        this._on( this.uiDialogTitlebar, {
12455            mousedown: function( event ) {
12456
12457                // Don't prevent click on close button (#8838)
12458                // Focusing a dialog that is partially scrolled out of view
12459                // causes the browser to scroll it into view, preventing the click event
12460                if ( !$( event.target ).closest( ".ui-dialog-titlebar-close" ) ) {
12461
12462                    // Dialog isn't getting focus when dragging (#8063)
12463                    this.uiDialog.trigger( "focus" );
12464                }
12465            }
12466        } );
12467
12468        this.uiDialogTitlebarClose = $( "<button type='button'></button>" )
12469            .button( {
12470                label: $( "<a>" ).text( this.options.closeText ).html(),
12471                icon: "ui-icon-closethick",
12472                showLabel: false
12473            } )
12474            .appendTo( this.uiDialogTitlebar );
12475
12476        this._addClass( this.uiDialogTitlebarClose, "ui-dialog-titlebar-close" );
12477        this._on( this.uiDialogTitlebarClose, {
12478            click: function( event ) {
12479                event.preventDefault();
12480                this.close( event );
12481            }
12482        } );
12483
12484        var uiDialogHeadingLevel = Number.isInteger( this.options.uiDialogTitleHeadingLevel ) &&
12485            this.options.uiDialogTitleHeadingLevel > 0 &&
12486            this.options.uiDialogTitleHeadingLevel <= 6 ?
12487            "h" + this.options.uiDialogTitleHeadingLevel : "span";
12488
12489        uiDialogTitle = $( "<" + uiDialogHeadingLevel + ">" )
12490            .uniqueId().prependTo( this.uiDialogTitlebar );
12491        this._addClass( uiDialogTitle, "ui-dialog-title" );
12492        this._title( uiDialogTitle );
12493
12494        this.uiDialogTitlebar.prependTo( this.uiDialog );
12495
12496        this.uiDialog.attr( {
12497            "aria-labelledby": uiDialogTitle.attr( "id" )
12498        } );
12499    },
12500
12501    _title: function( title ) {
12502        if ( this.options.title ) {
12503            title.text( this.options.title );
12504        } else {
12505            title.html( "&#160;" );
12506        }
12507    },
12508
12509    _createButtonPane: function() {
12510        this.uiDialogButtonPane = $( "<div>" );
12511        this._addClass( this.uiDialogButtonPane, "ui-dialog-buttonpane",
12512            "ui-widget-content ui-helper-clearfix" );
12513
12514        this.uiButtonSet = $( "<div>" )
12515            .appendTo( this.uiDialogButtonPane );
12516        this._addClass( this.uiButtonSet, "ui-dialog-buttonset" );
12517
12518        this._createButtons();
12519    },
12520
12521    _createButtons: function() {
12522        var that = this,
12523            buttons = this.options.buttons;
12524
12525        // If we already have a button pane, remove it
12526        this.uiDialogButtonPane.remove();
12527        this.uiButtonSet.empty();
12528
12529        if ( $.isEmptyObject( buttons ) || ( Array.isArray( buttons ) && !buttons.length ) ) {
12530            this._removeClass( this.uiDialog, "ui-dialog-buttons" );
12531            return;
12532        }
12533
12534        $.each( buttons, function( name, props ) {
12535            var click, buttonOptions;
12536            props = typeof props === "function" ?
12537                { click: props, text: name } :
12538                props;
12539
12540            // Default to a non-submitting button
12541            props = $.extend( { type: "button" }, props );
12542
12543            // Change the context for the click callback to be the main element
12544            click = props.click;
12545            buttonOptions = {
12546                icon: props.icon,
12547                iconPosition: props.iconPosition,
12548                showLabel: props.showLabel,
12549
12550                // Deprecated options
12551                icons: props.icons,
12552                text: props.text
12553            };
12554
12555            delete props.click;
12556            delete props.icon;
12557            delete props.iconPosition;
12558            delete props.showLabel;
12559
12560            // Deprecated options
12561            delete props.icons;
12562            if ( typeof props.text === "boolean" ) {
12563                delete props.text;
12564            }
12565
12566            $( "<button></button>", props )
12567                .button( buttonOptions )
12568                .appendTo( that.uiButtonSet )
12569                .on( "click", function() {
12570                    click.apply( that.element[ 0 ], arguments );
12571                } );
12572        } );
12573        this._addClass( this.uiDialog, "ui-dialog-buttons" );
12574        this.uiDialogButtonPane.appendTo( this.uiDialog );
12575    },
12576
12577    _makeDraggable: function() {
12578        var that = this,
12579            options = this.options;
12580
12581        function filteredUi( ui ) {
12582            return {
12583                position: ui.position,
12584                offset: ui.offset
12585            };
12586        }
12587
12588        this.uiDialog.draggable( {
12589            cancel: ".ui-dialog-content, .ui-dialog-titlebar-close",
12590            handle: ".ui-dialog-titlebar",
12591            containment: "document",
12592            start: function( event, ui ) {
12593                that._addClass( $( this ), "ui-dialog-dragging" );
12594                that._blockFrames();
12595                that._trigger( "dragStart", event, filteredUi( ui ) );
12596            },
12597            drag: function( event, ui ) {
12598                that._trigger( "drag", event, filteredUi( ui ) );
12599            },
12600            stop: function( event, ui ) {
12601                var left = ui.offset.left - that.document.scrollLeft(),
12602                    top = ui.offset.top - that.document.scrollTop();
12603
12604                options.position = {
12605                    my: "left top",
12606                    at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12607                        "top" + ( top >= 0 ? "+" : "" ) + top,
12608                    of: that.window
12609                };
12610                that._removeClass( $( this ), "ui-dialog-dragging" );
12611                that._unblockFrames();
12612                that._trigger( "dragStop", event, filteredUi( ui ) );
12613            }
12614        } );
12615    },
12616
12617    _makeResizable: function() {
12618        var that = this,
12619            options = this.options,
12620            handles = options.resizable,
12621
12622            // .ui-resizable has position: relative defined in the stylesheet
12623            // but dialogs have to use absolute or fixed positioning
12624            position = this.uiDialog.css( "position" ),
12625            resizeHandles = typeof handles === "string" ?
12626                handles :
12627                "n,e,s,w,se,sw,ne,nw";
12628
12629        function filteredUi( ui ) {
12630            return {
12631                originalPosition: ui.originalPosition,
12632                originalSize: ui.originalSize,
12633                position: ui.position,
12634                size: ui.size
12635            };
12636        }
12637
12638        this.uiDialog.resizable( {
12639            cancel: ".ui-dialog-content",
12640            containment: "document",
12641            alsoResize: this.element,
12642            maxWidth: options.maxWidth,
12643            maxHeight: options.maxHeight,
12644            minWidth: options.minWidth,
12645            minHeight: this._minHeight(),
12646            handles: resizeHandles,
12647            start: function( event, ui ) {
12648                that._addClass( $( this ), "ui-dialog-resizing" );
12649                that._blockFrames();
12650                that._trigger( "resizeStart", event, filteredUi( ui ) );
12651            },
12652            resize: function( event, ui ) {
12653                that._trigger( "resize", event, filteredUi( ui ) );
12654            },
12655            stop: function( event, ui ) {
12656                var offset = that.uiDialog.offset(),
12657                    left = offset.left - that.document.scrollLeft(),
12658                    top = offset.top - that.document.scrollTop();
12659
12660                options.height = that.uiDialog.height();
12661                options.width = that.uiDialog.width();
12662                options.position = {
12663                    my: "left top",
12664                    at: "left" + ( left >= 0 ? "+" : "" ) + left + " " +
12665                        "top" + ( top >= 0 ? "+" : "" ) + top,
12666                    of: that.window
12667                };
12668                that._removeClass( $( this ), "ui-dialog-resizing" );
12669                that._unblockFrames();
12670                that._trigger( "resizeStop", event, filteredUi( ui ) );
12671            }
12672        } )
12673            .css( "position", position );
12674    },
12675
12676    _trackFocus: function() {
12677        this._on( this.widget(), {
12678            focusin: function( event ) {
12679                this._makeFocusTarget();
12680                this._focusedElement = $( event.target );
12681            }
12682        } );
12683    },
12684
12685    _makeFocusTarget: function() {
12686        this._untrackInstance();
12687        this._trackingInstances().unshift( this );
12688    },
12689
12690    _untrackInstance: function() {
12691        var instances = this._trackingInstances(),
12692            exists = $.inArray( this, instances );
12693        if ( exists !== -1 ) {
12694            instances.splice( exists, 1 );
12695        }
12696    },
12697
12698    _trackingInstances: function() {
12699        var instances = this.document.data( "ui-dialog-instances" );
12700        if ( !instances ) {
12701            instances = [];
12702            this.document.data( "ui-dialog-instances", instances );
12703        }
12704        return instances;
12705    },
12706
12707    _minHeight: function() {
12708        var options = this.options;
12709
12710        return options.height === "auto" ?
12711            options.minHeight :
12712            Math.min( options.minHeight, options.height );
12713    },
12714
12715    _position: function() {
12716
12717        // Need to show the dialog to get the actual offset in the position plugin
12718        var isVisible = this.uiDialog.is( ":visible" );
12719        if ( !isVisible ) {
12720            this.uiDialog.show();
12721        }
12722        this.uiDialog.position( this.options.position );
12723        if ( !isVisible ) {
12724            this.uiDialog.hide();
12725        }
12726    },
12727
12728    _setOptions: function( options ) {
12729        var that = this,
12730            resize = false,
12731            resizableOptions = {};
12732
12733        $.each( options, function( key, value ) {
12734            that._setOption( key, value );
12735
12736            if ( key in that.sizeRelatedOptions ) {
12737                resize = true;
12738            }
12739            if ( key in that.resizableRelatedOptions ) {
12740                resizableOptions[ key ] = value;
12741            }
12742        } );
12743
12744        if ( resize ) {
12745            this._size();
12746            this._position();
12747        }
12748        if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12749            this.uiDialog.resizable( "option", resizableOptions );
12750        }
12751    },
12752
12753    _setOption: function( key, value ) {
12754        var isDraggable, isResizable,
12755            uiDialog = this.uiDialog;
12756
12757        if ( key === "disabled" ) {
12758            return;
12759        }
12760
12761        this._super( key, value );
12762
12763        if ( key === "appendTo" ) {
12764            this.uiDialog.appendTo( this._appendTo() );
12765        }
12766
12767        if ( key === "buttons" ) {
12768            this._createButtons();
12769        }
12770
12771        if ( key === "closeText" ) {
12772            this.uiDialogTitlebarClose.button( {
12773
12774                // Ensure that we always pass a string
12775                label: $( "<a>" ).text( "" + this.options.closeText ).html()
12776            } );
12777        }
12778
12779        if ( key === "draggable" ) {
12780            isDraggable = uiDialog.is( ":data(ui-draggable)" );
12781            if ( isDraggable && !value ) {
12782                uiDialog.draggable( "destroy" );
12783            }
12784
12785            if ( !isDraggable && value ) {
12786                this._makeDraggable();
12787            }
12788        }
12789
12790        if ( key === "position" ) {
12791            this._position();
12792        }
12793
12794        if ( key === "resizable" ) {
12795
12796            // currently resizable, becoming non-resizable
12797            isResizable = uiDialog.is( ":data(ui-resizable)" );
12798            if ( isResizable && !value ) {
12799                uiDialog.resizable( "destroy" );
12800            }
12801
12802            // Currently resizable, changing handles
12803            if ( isResizable && typeof value === "string" ) {
12804                uiDialog.resizable( "option", "handles", value );
12805            }
12806
12807            // Currently non-resizable, becoming resizable
12808            if ( !isResizable && value !== false ) {
12809                this._makeResizable();
12810            }
12811        }
12812
12813        if ( key === "title" ) {
12814            this._title( this.uiDialogTitlebar.find( ".ui-dialog-title" ) );
12815        }
12816
12817        if ( key === "modal" ) {
12818            uiDialog.attr( "aria-modal", value ? "true" : null );
12819        }
12820    },
12821
12822    _size: function() {
12823
12824        // If the user has resized the dialog, the .ui-dialog and .ui-dialog-content
12825        // divs will both have width and height set, so we need to reset them
12826        var nonContentHeight, minContentHeight, maxContentHeight,
12827            options = this.options;
12828
12829        // Reset content sizing
12830        this.element.show().css( {
12831            width: "auto",
12832            minHeight: 0,
12833            maxHeight: "none",
12834            height: 0
12835        } );
12836
12837        if ( options.minWidth > options.width ) {
12838            options.width = options.minWidth;
12839        }
12840
12841        // Reset wrapper sizing
12842        // determine the height of all the non-content elements
12843        nonContentHeight = this.uiDialog.css( {
12844            height: "auto",
12845            width: options.width
12846        } )
12847            .outerHeight();
12848        minContentHeight = Math.max( 0, options.minHeight - nonContentHeight );
12849        maxContentHeight = typeof options.maxHeight === "number" ?
12850            Math.max( 0, options.maxHeight - nonContentHeight ) :
12851            "none";
12852
12853        if ( options.height === "auto" ) {
12854            this.element.css( {
12855                minHeight: minContentHeight,
12856                maxHeight: maxContentHeight,
12857                height: "auto"
12858            } );
12859        } else {
12860            this.element.height( Math.max( 0, options.height - nonContentHeight ) );
12861        }
12862
12863        if ( this.uiDialog.is( ":data(ui-resizable)" ) ) {
12864            this.uiDialog.resizable( "option", "minHeight", this._minHeight() );
12865        }
12866    },
12867
12868    _blockFrames: function() {
12869        this.iframeBlocks = this.document.find( "iframe" ).map( function() {
12870            var iframe = $( this );
12871
12872            return $( "<div>" )
12873                .css( {
12874                    position: "absolute",
12875                    width: iframe.outerWidth(),
12876                    height: iframe.outerHeight()
12877                } )
12878                .appendTo( iframe.parent() )
12879                .offset( iframe.offset() )[ 0 ];
12880        } );
12881    },
12882
12883    _unblockFrames: function() {
12884        if ( this.iframeBlocks ) {
12885            this.iframeBlocks.remove();
12886            delete this.iframeBlocks;
12887        }
12888    },
12889
12890    _allowInteraction: function( event ) {
12891        if ( $( event.target ).closest( ".ui-dialog" ).length ) {
12892            return true;
12893        }
12894
12895        // TODO: Remove hack when datepicker implements
12896        // the .ui-front logic (#8989)
12897        return !!$( event.target ).closest( ".ui-datepicker" ).length;
12898    },
12899
12900    _createOverlay: function() {
12901        if ( !this.options.modal ) {
12902            return;
12903        }
12904
12905        // We use a delay in case the overlay is created from an
12906        // event that we're going to be cancelling (#2804)
12907        var isOpening = true;
12908        this._delay( function() {
12909            isOpening = false;
12910        } );
12911
12912        if ( !this.document.data( "ui-dialog-overlays" ) ) {
12913
12914            // Prevent use of anchors and inputs
12915            // This doesn't use `_on()` because it is a shared event handler
12916            // across all open modal dialogs.
12917            this.document.on( "focusin.ui-dialog", function( event ) {
12918                if ( isOpening ) {
12919                    return;
12920                }
12921
12922                var instance = this._trackingInstances()[ 0 ];
12923                if ( !instance._allowInteraction( event ) ) {
12924                    event.preventDefault();
12925                    instance._focusTabbable();
12926                }
12927            }.bind( this ) );
12928        }
12929
12930        this.overlay = $( "<div>" )
12931            .appendTo( this._appendTo() );
12932
12933        this._addClass( this.overlay, null, "ui-widget-overlay ui-front" );
12934        this._on( this.overlay, {
12935            mousedown: "_keepFocus"
12936        } );
12937        this.document.data( "ui-dialog-overlays",
12938            ( this.document.data( "ui-dialog-overlays" ) || 0 ) + 1 );
12939    },
12940
12941    _destroyOverlay: function() {
12942        if ( !this.options.modal ) {
12943            return;
12944        }
12945
12946        if ( this.overlay ) {
12947            var overlays = this.document.data( "ui-dialog-overlays" ) - 1;
12948
12949            if ( !overlays ) {
12950                this.document.off( "focusin.ui-dialog" );
12951                this.document.removeData( "ui-dialog-overlays" );
12952            } else {
12953                this.document.data( "ui-dialog-overlays", overlays );
12954            }
12955
12956            this.overlay.remove();
12957            this.overlay = null;
12958        }
12959    }
12960} );
12961
12962// DEPRECATED
12963// TODO: switch return back to widget declaration at top of file when this is removed
12964if ( $.uiBackCompat === true ) {
12965
12966    // Backcompat for dialogClass option
12967    $.widget( "ui.dialog", $.ui.dialog, {
12968        options: {
12969            dialogClass: ""
12970        },
12971        _createWrapper: function() {
12972            this._super();
12973            this.uiDialog.addClass( this.options.dialogClass );
12974        },
12975        _setOption: function( key, value ) {
12976            if ( key === "dialogClass" ) {
12977                this.uiDialog
12978                    .removeClass( this.options.dialogClass )
12979                    .addClass( value );
12980            }
12981            this._superApply( arguments );
12982        }
12983    } );
12984}
12985
12986var widgetsDialog = $.ui.dialog;
12987
12988
12989/*!
12990 * jQuery UI Droppable 1.14.1
12991 * https://jqueryui.com
12992 *
12993 * Copyright OpenJS Foundation and other contributors
12994 * Released under the MIT license.
12995 * https://jquery.org/license
12996 */
12997
12998//>>label: Droppable
12999//>>group: Interactions
13000//>>description: Enables drop targets for draggable elements.
13001//>>docs: https://api.jqueryui.com/droppable/
13002//>>demos: https://jqueryui.com/droppable/
13003
13004
13005$.widget( "ui.droppable", {
13006    version: "1.14.1",
13007    widgetEventPrefix: "drop",
13008    options: {
13009        accept: "*",
13010        addClasses: true,
13011        greedy: false,
13012        scope: "default",
13013        tolerance: "intersect",
13014
13015        // Callbacks
13016        activate: null,
13017        deactivate: null,
13018        drop: null,
13019        out: null,
13020        over: null
13021    },
13022    _create: function() {
13023
13024        var proportions,
13025            o = this.options,
13026            accept = o.accept;
13027
13028        this.isover = false;
13029        this.isout = true;
13030
13031        this.accept = typeof accept === "function" ? accept : function( d ) {
13032            return d.is( accept );
13033        };
13034
13035        this.proportions = function( /* valueToWrite */ ) {
13036            if ( arguments.length ) {
13037
13038                // Store the droppable's proportions
13039                proportions = arguments[ 0 ];
13040            } else {
13041
13042                // Retrieve or derive the droppable's proportions
13043                return proportions ?
13044                    proportions :
13045                    proportions = {
13046                        width: this.element[ 0 ].offsetWidth,
13047                        height: this.element[ 0 ].offsetHeight
13048                    };
13049            }
13050        };
13051
13052        this._addToManager( o.scope );
13053
13054        if ( o.addClasses ) {
13055            this._addClass( "ui-droppable" );
13056        }
13057
13058    },
13059
13060    _addToManager: function( scope ) {
13061
13062        // Add the reference and positions to the manager
13063        $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
13064        $.ui.ddmanager.droppables[ scope ].push( this );
13065    },
13066
13067    _splice: function( drop ) {
13068        var i = 0;
13069        for ( ; i < drop.length; i++ ) {
13070            if ( drop[ i ] === this ) {
13071                drop.splice( i, 1 );
13072            }
13073        }
13074    },
13075
13076    _destroy: function() {
13077        var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13078
13079        this._splice( drop );
13080    },
13081
13082    _setOption: function( key, value ) {
13083
13084        if ( key === "accept" ) {
13085            this.accept = typeof value === "function" ? value : function( d ) {
13086                return d.is( value );
13087            };
13088        } else if ( key === "scope" ) {
13089            var drop = $.ui.ddmanager.droppables[ this.options.scope ];
13090
13091            this._splice( drop );
13092            this._addToManager( value );
13093        }
13094
13095        this._super( key, value );
13096    },
13097
13098    _activate: function( event ) {
13099        var draggable = $.ui.ddmanager.current;
13100
13101        this._addActiveClass();
13102        if ( draggable ) {
13103            this._trigger( "activate", event, this.ui( draggable ) );
13104        }
13105    },
13106
13107    _deactivate: function( event ) {
13108        var draggable = $.ui.ddmanager.current;
13109
13110        this._removeActiveClass();
13111        if ( draggable ) {
13112            this._trigger( "deactivate", event, this.ui( draggable ) );
13113        }
13114    },
13115
13116    _over: function( event ) {
13117
13118        var draggable = $.ui.ddmanager.current;
13119
13120        // Bail if draggable and droppable are same element
13121        if ( !draggable || ( draggable.currentItem ||
13122                draggable.element )[ 0 ] === this.element[ 0 ] ) {
13123            return;
13124        }
13125
13126        if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13127                draggable.element ) ) ) {
13128            this._addHoverClass();
13129            this._trigger( "over", event, this.ui( draggable ) );
13130        }
13131
13132    },
13133
13134    _out: function( event ) {
13135
13136        var draggable = $.ui.ddmanager.current;
13137
13138        // Bail if draggable and droppable are same element
13139        if ( !draggable || ( draggable.currentItem ||
13140                draggable.element )[ 0 ] === this.element[ 0 ] ) {
13141            return;
13142        }
13143
13144        if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
13145                draggable.element ) ) ) {
13146            this._removeHoverClass();
13147            this._trigger( "out", event, this.ui( draggable ) );
13148        }
13149
13150    },
13151
13152    _drop: function( event, custom ) {
13153
13154        var draggable = custom || $.ui.ddmanager.current,
13155            childrenIntersection = false;
13156
13157        // Bail if draggable and droppable are same element
13158        if ( !draggable || ( draggable.currentItem ||
13159                draggable.element )[ 0 ] === this.element[ 0 ] ) {
13160            return false;
13161        }
13162
13163        this.element
13164            .find( ":data(ui-droppable)" )
13165            .not( ".ui-draggable-dragging" )
13166            .each( function() {
13167                var inst = $( this ).droppable( "instance" );
13168                if (
13169                    inst.options.greedy &&
13170                    !inst.options.disabled &&
13171                    inst.options.scope === draggable.options.scope &&
13172                    inst.accept.call(
13173                        inst.element[ 0 ], ( draggable.currentItem || draggable.element )
13174                    ) &&
13175                    $.ui.intersect(
13176                        draggable,
13177                        $.extend( inst, { offset: inst.element.offset() } ),
13178                        inst.options.tolerance, event
13179                    )
13180                ) {
13181                    childrenIntersection = true;
13182                    return false;
13183                }
13184            } );
13185        if ( childrenIntersection ) {
13186            return false;
13187        }
13188
13189        if ( this.accept.call( this.element[ 0 ],
13190                ( draggable.currentItem || draggable.element ) ) ) {
13191            this._removeActiveClass();
13192            this._removeHoverClass();
13193
13194            this._trigger( "drop", event, this.ui( draggable ) );
13195            return this.element;
13196        }
13197
13198        return false;
13199
13200    },
13201
13202    ui: function( c ) {
13203        return {
13204            draggable: ( c.currentItem || c.element ),
13205            helper: c.helper,
13206            position: c.position,
13207            offset: c.positionAbs
13208        };
13209    },
13210
13211    // Extension points just to make backcompat sane and avoid duplicating logic
13212    // TODO: Remove in 1.14 along with call to it below
13213    _addHoverClass: function() {
13214        this._addClass( "ui-droppable-hover" );
13215    },
13216
13217    _removeHoverClass: function() {
13218        this._removeClass( "ui-droppable-hover" );
13219    },
13220
13221    _addActiveClass: function() {
13222        this._addClass( "ui-droppable-active" );
13223    },
13224
13225    _removeActiveClass: function() {
13226        this._removeClass( "ui-droppable-active" );
13227    }
13228} );
13229
13230$.ui.intersect = ( function() {
13231    function isOverAxis( x, reference, size ) {
13232        return ( x >= reference ) && ( x < ( reference + size ) );
13233    }
13234
13235    return function( draggable, droppable, toleranceMode, event ) {
13236
13237        if ( !droppable.offset ) {
13238            return false;
13239        }
13240
13241        var x1 = ( draggable.positionAbs ||
13242                draggable.position.absolute ).left + draggable.margins.left,
13243            y1 = ( draggable.positionAbs ||
13244                draggable.position.absolute ).top + draggable.margins.top,
13245            x2 = x1 + draggable.helperProportions.width,
13246            y2 = y1 + draggable.helperProportions.height,
13247            l = droppable.offset.left,
13248            t = droppable.offset.top,
13249            r = l + droppable.proportions().width,
13250            b = t + droppable.proportions().height;
13251
13252        switch ( toleranceMode ) {
13253        case "fit":
13254            return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
13255        case "intersect":
13256            return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
13257                x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
13258                t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
13259                y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
13260        case "pointer":
13261            return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
13262                isOverAxis( event.pageX, l, droppable.proportions().width );
13263        case "touch":
13264            return (
13265                ( y1 >= t && y1 <= b ) || // Top edge touching
13266                ( y2 >= t && y2 <= b ) || // Bottom edge touching
13267                ( y1 < t && y2 > b ) // Surrounded vertically
13268            ) && (
13269                ( x1 >= l && x1 <= r ) || // Left edge touching
13270                ( x2 >= l && x2 <= r ) || // Right edge touching
13271                ( x1 < l && x2 > r ) // Surrounded horizontally
13272            );
13273        default:
13274            return false;
13275        }
13276    };
13277} )();
13278
13279/*
13280    This manager tracks offsets of draggables and droppables
13281*/
13282$.ui.ddmanager = {
13283    current: null,
13284    droppables: { "default": [] },
13285    prepareOffsets: function( t, event ) {
13286
13287        var i, j,
13288            m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
13289            type = event ? event.type : null, // workaround for #2317
13290            list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();
13291
13292        droppablesLoop: for ( i = 0; i < m.length; i++ ) {
13293
13294            // No disabled and non-accepted
13295            if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
13296                    ( t.currentItem || t.element ) ) ) ) {
13297                continue;
13298            }
13299
13300            // Filter out elements in the current dragged item
13301            for ( j = 0; j < list.length; j++ ) {
13302                if ( list[ j ] === m[ i ].element[ 0 ] ) {
13303                    m[ i ].proportions().height = 0;
13304                    continue droppablesLoop;
13305                }
13306            }
13307
13308            m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
13309            if ( !m[ i ].visible ) {
13310                continue;
13311            }
13312
13313            // Activate the droppable if used directly from draggables
13314            if ( type === "mousedown" ) {
13315                m[ i ]._activate.call( m[ i ], event );
13316            }
13317
13318            m[ i ].offset = m[ i ].element.offset();
13319            m[ i ].proportions( {
13320                width: m[ i ].element[ 0 ].offsetWidth,
13321                height: m[ i ].element[ 0 ].offsetHeight
13322            } );
13323
13324        }
13325
13326    },
13327    drop: function( draggable, event ) {
13328
13329        var dropped = false;
13330
13331        // Create a copy of the droppables in case the list changes during the drop (#9116)
13332        $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {
13333
13334            if ( !this.options ) {
13335                return;
13336            }
13337            if ( !this.options.disabled && this.visible &&
13338                    $.ui.intersect( draggable, this, this.options.tolerance, event ) ) {
13339                dropped = this._drop.call( this, event ) || dropped;
13340            }
13341
13342            if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
13343                    ( draggable.currentItem || draggable.element ) ) ) {
13344                this.isout = true;
13345                this.isover = false;
13346                this._deactivate.call( this, event );
13347            }
13348
13349        } );
13350        return dropped;
13351
13352    },
13353    dragStart: function( draggable, event ) {
13354
13355        // Listen for scrolling so that if the dragging causes scrolling the position of the
13356        // droppables can be recalculated (see #5003)
13357        draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
13358            if ( !draggable.options.refreshPositions ) {
13359                $.ui.ddmanager.prepareOffsets( draggable, event );
13360            }
13361        } );
13362    },
13363    drag: function( draggable, event ) {
13364
13365        // If you have a highly dynamic page, you might try this option. It renders positions
13366        // every time you move the mouse.
13367        if ( draggable.options.refreshPositions ) {
13368            $.ui.ddmanager.prepareOffsets( draggable, event );
13369        }
13370
13371        // Run through all droppables and check their positions based on specific tolerance options
13372        $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {
13373
13374            if ( this.options.disabled || this.greedyChild || !this.visible ) {
13375                return;
13376            }
13377
13378            var parentInstance, scope, parent,
13379                intersects = $.ui.intersect( draggable, this, this.options.tolerance, event ),
13380                c = !intersects && this.isover ?
13381                    "isout" :
13382                    ( intersects && !this.isover ? "isover" : null );
13383            if ( !c ) {
13384                return;
13385            }
13386
13387            if ( this.options.greedy ) {
13388
13389                // find droppable parents with same scope
13390                scope = this.options.scope;
13391                parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
13392                    return $( this ).droppable( "instance" ).options.scope === scope;
13393                } );
13394
13395                if ( parent.length ) {
13396                    parentInstance = $( parent[ 0 ] ).droppable( "instance" );
13397                    parentInstance.greedyChild = ( c === "isover" );
13398                }
13399            }
13400
13401            // We just moved into a greedy child
13402            if ( parentInstance && c === "isover" ) {
13403                parentInstance.isover = false;
13404                parentInstance.isout = true;
13405                parentInstance._out.call( parentInstance, event );
13406            }
13407
13408            this[ c ] = true;
13409            this[ c === "isout" ? "isover" : "isout" ] = false;
13410            this[ c === "isover" ? "_over" : "_out" ].call( this, event );
13411
13412            // We just moved out of a greedy child
13413            if ( parentInstance && c === "isout" ) {
13414                parentInstance.isout = false;
13415                parentInstance.isover = true;
13416                parentInstance._over.call( parentInstance, event );
13417            }
13418        } );
13419
13420    },
13421    dragStop: function( draggable, event ) {
13422        draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );
13423
13424        // Call prepareOffsets one final time since IE does not fire return scroll events when
13425        // overflow was caused by drag (see #5003)
13426        if ( !draggable.options.refreshPositions ) {
13427            $.ui.ddmanager.prepareOffsets( draggable, event );
13428        }
13429    }
13430};
13431
13432// DEPRECATED
13433// TODO: switch return back to widget declaration at top of file when this is removed
13434if ( $.uiBackCompat === true ) {
13435
13436    // Backcompat for activeClass and hoverClass options
13437    $.widget( "ui.droppable", $.ui.droppable, {
13438        options: {
13439            hoverClass: false,
13440            activeClass: false
13441        },
13442        _addActiveClass: function() {
13443            this._super();
13444            if ( this.options.activeClass ) {
13445                this.element.addClass( this.options.activeClass );
13446            }
13447        },
13448        _removeActiveClass: function() {
13449            this._super();
13450            if ( this.options.activeClass ) {
13451                this.element.removeClass( this.options.activeClass );
13452            }
13453        },
13454        _addHoverClass: function() {
13455            this._super();
13456            if ( this.options.hoverClass ) {
13457                this.element.addClass( this.options.hoverClass );
13458            }
13459        },
13460        _removeHoverClass: function() {
13461            this._super();
13462            if ( this.options.hoverClass ) {
13463                this.element.removeClass( this.options.hoverClass );
13464            }
13465        }
13466    } );
13467}
13468
13469var widgetsDroppable = $.ui.droppable;
13470
13471
13472/*!
13473 * jQuery UI Progressbar 1.14.1
13474 * https://jqueryui.com
13475 *
13476 * Copyright OpenJS Foundation and other contributors
13477 * Released under the MIT license.
13478 * https://jquery.org/license
13479 */
13480
13481//>>label: Progressbar
13482//>>group: Widgets
13483/* eslint-disable max-len */
13484//>>description: Displays a status indicator for loading state, standard percentage, and other progress indicators.
13485/* eslint-enable max-len */
13486//>>docs: https://api.jqueryui.com/progressbar/
13487//>>demos: https://jqueryui.com/progressbar/
13488//>>css.structure: ../../themes/base/core.css
13489//>>css.structure: ../../themes/base/progressbar.css
13490//>>css.theme: ../../themes/base/theme.css
13491
13492
13493var widgetsProgressbar = $.widget( "ui.progressbar", {
13494    version: "1.14.1",
13495    options: {
13496        classes: {
13497            "ui-progressbar": "ui-corner-all",
13498            "ui-progressbar-value": "ui-corner-left",
13499            "ui-progressbar-complete": "ui-corner-right"
13500        },
13501        max: 100,
13502        value: 0,
13503
13504        change: null,
13505        complete: null
13506    },
13507
13508    min: 0,
13509
13510    _create: function() {
13511
13512        // Constrain initial value
13513        this.oldValue = this.options.value = this._constrainedValue();
13514
13515        this.element.attr( {
13516
13517            // Only set static values; aria-valuenow and aria-valuemax are
13518            // set inside _refreshValue()
13519            role: "progressbar",
13520            "aria-valuemin": this.min
13521        } );
13522        this._addClass( "ui-progressbar", "ui-widget ui-widget-content" );
13523
13524        this.valueDiv = $( "<div>" ).appendTo( this.element );
13525        this._addClass( this.valueDiv, "ui-progressbar-value", "ui-widget-header" );
13526        this._refreshValue();
13527    },
13528
13529    _destroy: function() {
13530        this.element.removeAttr( "role aria-valuemin aria-valuemax aria-valuenow" );
13531
13532        this.valueDiv.remove();
13533    },
13534
13535    value: function( newValue ) {
13536        if ( newValue === undefined ) {
13537            return this.options.value;
13538        }
13539
13540        this.options.value = this._constrainedValue( newValue );
13541        this._refreshValue();
13542    },
13543
13544    _constrainedValue: function( newValue ) {
13545        if ( newValue === undefined ) {
13546            newValue = this.options.value;
13547        }
13548
13549        this.indeterminate = newValue === false;
13550
13551        // Sanitize value
13552        if ( typeof newValue !== "number" ) {
13553            newValue = 0;
13554        }
13555
13556        return this.indeterminate ? false :
13557            Math.min( this.options.max, Math.max( this.min, newValue ) );
13558    },
13559
13560    _setOptions: function( options ) {
13561
13562        // Ensure "value" option is set after other values (like max)
13563        var value = options.value;
13564        delete options.value;
13565
13566        this._super( options );
13567
13568        this.options.value = this._constrainedValue( value );
13569        this._refreshValue();
13570    },
13571
13572    _setOption: function( key, value ) {
13573        if ( key === "max" ) {
13574
13575            // Don't allow a max less than min
13576            value = Math.max( this.min, value );
13577        }
13578        this._super( key, value );
13579    },
13580
13581    _setOptionDisabled: function( value ) {
13582        this._super( value );
13583
13584        this.element.attr( "aria-disabled", value );
13585        this._toggleClass( null, "ui-state-disabled", !!value );
13586    },
13587
13588    _percentage: function() {
13589        return this.indeterminate ?
13590            100 :
13591            100 * ( this.options.value - this.min ) / ( this.options.max - this.min );
13592    },
13593
13594    _refreshValue: function() {
13595        var value = this.options.value,
13596            percentage = this._percentage();
13597
13598        this.valueDiv
13599            .toggle( this.indeterminate || value > this.min )
13600            .width( percentage.toFixed( 0 ) + "%" );
13601
13602        this
13603            ._toggleClass( this.valueDiv, "ui-progressbar-complete", null,
13604                value === this.options.max )
13605            ._toggleClass( "ui-progressbar-indeterminate", null, this.indeterminate );
13606
13607        if ( this.indeterminate ) {
13608            this.element.removeAttr( "aria-valuenow" );
13609            if ( !this.overlayDiv ) {
13610                this.overlayDiv = $( "<div>" ).appendTo( this.valueDiv );
13611                this._addClass( this.overlayDiv, "ui-progressbar-overlay" );
13612            }
13613        } else {
13614            this.element.attr( {
13615                "aria-valuemax": this.options.max,
13616                "aria-valuenow": value
13617            } );
13618            if ( this.overlayDiv ) {
13619                this.overlayDiv.remove();
13620                this.overlayDiv = null;
13621            }
13622        }
13623
13624        if ( this.oldValue !== value ) {
13625            this.oldValue = value;
13626            this._trigger( "change" );
13627        }
13628        if ( value === this.options.max ) {
13629            this._trigger( "complete" );
13630        }
13631    }
13632} );
13633
13634
13635/*!
13636 * jQuery UI Selectable 1.14.1
13637 * https://jqueryui.com
13638 *
13639 * Copyright OpenJS Foundation and other contributors
13640 * Released under the MIT license.
13641 * https://jquery.org/license
13642 */
13643
13644//>>label: Selectable
13645//>>group: Interactions
13646//>>description: Allows groups of elements to be selected with the mouse.
13647//>>docs: https://api.jqueryui.com/selectable/
13648//>>demos: https://jqueryui.com/selectable/
13649//>>css.structure: ../../themes/base/selectable.css
13650
13651
13652var widgetsSelectable = $.widget( "ui.selectable", $.ui.mouse, {
13653    version: "1.14.1",
13654    options: {
13655        appendTo: "body",
13656        autoRefresh: true,
13657        distance: 0,
13658        filter: "*",
13659        tolerance: "touch",
13660
13661        // Callbacks
13662        selected: null,
13663        selecting: null,
13664        start: null,
13665        stop: null,
13666        unselected: null,
13667        unselecting: null
13668    },
13669    _create: function() {
13670        var that = this;
13671
13672        this._addClass( "ui-selectable" );
13673
13674        this.dragged = false;
13675
13676        // Cache selectee children based on filter
13677        this.refresh = function() {
13678            that.elementPos = $( that.element[ 0 ] ).offset();
13679            that.selectees = $( that.options.filter, that.element[ 0 ] );
13680            that._addClass( that.selectees, "ui-selectee" );
13681            that.selectees.each( function() {
13682                var $this = $( this ),
13683                    selecteeOffset = $this.offset(),
13684                    pos = {
13685                        left: selecteeOffset.left - that.elementPos.left,
13686                        top: selecteeOffset.top - that.elementPos.top
13687                    };
13688                $.data( this, "selectable-item", {
13689                    element: this,
13690                    $element: $this,
13691                    left: pos.left,
13692                    top: pos.top,
13693                    right: pos.left + $this.outerWidth(),
13694                    bottom: pos.top + $this.outerHeight(),
13695                    startselected: false,
13696                    selected: $this.hasClass( "ui-selected" ),
13697                    selecting: $this.hasClass( "ui-selecting" ),
13698                    unselecting: $this.hasClass( "ui-unselecting" )
13699                } );
13700            } );
13701        };
13702        this.refresh();
13703
13704        this._mouseInit();
13705
13706        this.helper = $( "<div>" );
13707        this._addClass( this.helper, "ui-selectable-helper" );
13708    },
13709
13710    _destroy: function() {
13711        this.selectees.removeData( "selectable-item" );
13712        this._mouseDestroy();
13713    },
13714
13715    _mouseStart: function( event ) {
13716        var that = this,
13717            options = this.options;
13718
13719        this.opos = [ event.pageX, event.pageY ];
13720        this.elementPos = $( this.element[ 0 ] ).offset();
13721
13722        if ( this.options.disabled ) {
13723            return;
13724        }
13725
13726        this.selectees = $( options.filter, this.element[ 0 ] );
13727
13728        this._trigger( "start", event );
13729
13730        $( options.appendTo ).append( this.helper );
13731
13732        // position helper (lasso)
13733        this.helper.css( {
13734            "left": event.pageX,
13735            "top": event.pageY,
13736            "width": 0,
13737            "height": 0
13738        } );
13739
13740        if ( options.autoRefresh ) {
13741            this.refresh();
13742        }
13743
13744        this.selectees.filter( ".ui-selected" ).each( function() {
13745            var selectee = $.data( this, "selectable-item" );
13746            selectee.startselected = true;
13747            if ( !event.metaKey && !event.ctrlKey ) {
13748                that._removeClass( selectee.$element, "ui-selected" );
13749                selectee.selected = false;
13750                that._addClass( selectee.$element, "ui-unselecting" );
13751                selectee.unselecting = true;
13752
13753                // selectable UNSELECTING callback
13754                that._trigger( "unselecting", event, {
13755                    unselecting: selectee.element
13756                } );
13757            }
13758        } );
13759
13760        $( event.target ).parents().addBack().each( function() {
13761            var doSelect,
13762                selectee = $.data( this, "selectable-item" );
13763            if ( selectee ) {
13764                doSelect = ( !event.metaKey && !event.ctrlKey ) ||
13765                    !selectee.$element.hasClass( "ui-selected" );
13766                that._removeClass( selectee.$element, doSelect ? "ui-unselecting" : "ui-selected" )
13767                    ._addClass( selectee.$element, doSelect ? "ui-selecting" : "ui-unselecting" );
13768                selectee.unselecting = !doSelect;
13769                selectee.selecting = doSelect;
13770                selectee.selected = doSelect;
13771
13772                // selectable (UN)SELECTING callback
13773                if ( doSelect ) {
13774                    that._trigger( "selecting", event, {
13775                        selecting: selectee.element
13776                    } );
13777                } else {
13778                    that._trigger( "unselecting", event, {
13779                        unselecting: selectee.element
13780                    } );
13781                }
13782                return false;
13783            }
13784        } );
13785
13786    },
13787
13788    _mouseDrag: function( event ) {
13789
13790        this.dragged = true;
13791
13792        if ( this.options.disabled ) {
13793            return;
13794        }
13795
13796        var tmp,
13797            that = this,
13798            options = this.options,
13799            x1 = this.opos[ 0 ],
13800            y1 = this.opos[ 1 ],
13801            x2 = event.pageX,
13802            y2 = event.pageY;
13803
13804        if ( x1 > x2 ) {
13805            tmp = x2; x2 = x1; x1 = tmp;
13806        }
13807        if ( y1 > y2 ) {
13808            tmp = y2; y2 = y1; y1 = tmp;
13809        }
13810        this.helper.css( { left: x1, top: y1, width: x2 - x1, height: y2 - y1 } );
13811
13812        this.selectees.each( function() {
13813            var selectee = $.data( this, "selectable-item" ),
13814                hit = false,
13815                offset = {};
13816
13817            //prevent helper from being selected if appendTo: selectable
13818            if ( !selectee || selectee.element === that.element[ 0 ] ) {
13819                return;
13820            }
13821
13822            offset.left   = selectee.left   + that.elementPos.left;
13823            offset.right  = selectee.right  + that.elementPos.left;
13824            offset.top    = selectee.top    + that.elementPos.top;
13825            offset.bottom = selectee.bottom + that.elementPos.top;
13826
13827            if ( options.tolerance === "touch" ) {
13828                hit = ( !( offset.left > x2 || offset.right < x1 || offset.top > y2 ||
13829                    offset.bottom < y1 ) );
13830            } else if ( options.tolerance === "fit" ) {
13831                hit = ( offset.left > x1 && offset.right < x2 && offset.top > y1 &&
13832                    offset.bottom < y2 );
13833            }
13834
13835            if ( hit ) {
13836
13837                // SELECT
13838                if ( selectee.selected ) {
13839                    that._removeClass( selectee.$element, "ui-selected" );
13840                    selectee.selected = false;
13841                }
13842                if ( selectee.unselecting ) {
13843                    that._removeClass( selectee.$element, "ui-unselecting" );
13844                    selectee.unselecting = false;
13845                }
13846                if ( !selectee.selecting ) {
13847                    that._addClass( selectee.$element, "ui-selecting" );
13848                    selectee.selecting = true;
13849
13850                    // selectable SELECTING callback
13851                    that._trigger( "selecting", event, {
13852                        selecting: selectee.element
13853                    } );
13854                }
13855            } else {
13856
13857                // UNSELECT
13858                if ( selectee.selecting ) {
13859                    if ( ( event.metaKey || event.ctrlKey ) && selectee.startselected ) {
13860                        that._removeClass( selectee.$element, "ui-selecting" );
13861                        selectee.selecting = false;
13862                        that._addClass( selectee.$element, "ui-selected" );
13863                        selectee.selected = true;
13864                    } else {
13865                        that._removeClass( selectee.$element, "ui-selecting" );
13866                        selectee.selecting = false;
13867                        if ( selectee.startselected ) {
13868                            that._addClass( selectee.$element, "ui-unselecting" );
13869                            selectee.unselecting = true;
13870                        }
13871
13872                        // selectable UNSELECTING callback
13873                        that._trigger( "unselecting", event, {
13874                            unselecting: selectee.element
13875                        } );
13876                    }
13877                }
13878                if ( selectee.selected ) {
13879                    if ( !event.metaKey && !event.ctrlKey && !selectee.startselected ) {
13880                        that._removeClass( selectee.$element, "ui-selected" );
13881                        selectee.selected = false;
13882
13883                        that._addClass( selectee.$element, "ui-unselecting" );
13884                        selectee.unselecting = true;
13885
13886                        // selectable UNSELECTING callback
13887                        that._trigger( "unselecting", event, {
13888                            unselecting: selectee.element
13889                        } );
13890                    }
13891                }
13892            }
13893        } );
13894
13895        return false;
13896    },
13897
13898    _mouseStop: function( event ) {
13899        var that = this;
13900
13901        this.dragged = false;
13902
13903        $( ".ui-unselecting", this.element[ 0 ] ).each( function() {
13904            var selectee = $.data( this, "selectable-item" );
13905            that._removeClass( selectee.$element, "ui-unselecting" );
13906            selectee.unselecting = false;
13907            selectee.startselected = false;
13908            that._trigger( "unselected", event, {
13909                unselected: selectee.element
13910            } );
13911        } );
13912        $( ".ui-selecting", this.element[ 0 ] ).each( function() {
13913            var selectee = $.data( this, "selectable-item" );
13914            that._removeClass( selectee.$element, "ui-selecting" )
13915                ._addClass( selectee.$element, "ui-selected" );
13916            selectee.selecting = false;
13917            selectee.selected = true;
13918            selectee.startselected = true;
13919            that._trigger( "selected", event, {
13920                selected: selectee.element
13921            } );
13922        } );
13923        this._trigger( "stop", event );
13924
13925        this.helper.remove();
13926
13927        return false;
13928    }
13929
13930} );
13931
13932
13933/*!
13934 * jQuery UI Selectmenu 1.14.1
13935 * https://jqueryui.com
13936 *
13937 * Copyright OpenJS Foundation and other contributors
13938 * Released under the MIT license.
13939 * https://jquery.org/license
13940 */
13941
13942//>>label: Selectmenu
13943//>>group: Widgets
13944/* eslint-disable max-len */
13945//>>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.
13946/* eslint-enable max-len */
13947//>>docs: https://api.jqueryui.com/selectmenu/
13948//>>demos: https://jqueryui.com/selectmenu/
13949//>>css.structure: ../../themes/base/core.css
13950//>>css.structure: ../../themes/base/selectmenu.css, ../../themes/base/button.css
13951//>>css.theme: ../../themes/base/theme.css
13952
13953
13954var widgetsSelectmenu = $.widget( "ui.selectmenu", [ $.ui.formResetMixin, {
13955    version: "1.14.1",
13956    defaultElement: "<select>",
13957    options: {
13958        appendTo: null,
13959        classes: {
13960            "ui-selectmenu-button-open": "ui-corner-top",
13961            "ui-selectmenu-button-closed": "ui-corner-all"
13962        },
13963        disabled: null,
13964        icons: {
13965            button: "ui-icon-triangle-1-s"
13966        },
13967        position: {
13968            my: "left top",
13969            at: "left bottom",
13970            collision: "none"
13971        },
13972        width: false,
13973
13974        // Callbacks
13975        change: null,
13976        close: null,
13977        focus: null,
13978        open: null,
13979        select: null
13980    },
13981
13982    _create: function() {
13983        var selectmenuId = this.element.uniqueId().attr( "id" );
13984        this.ids = {
13985            element: selectmenuId,
13986            button: selectmenuId + "-button",
13987            menu: selectmenuId + "-menu"
13988        };
13989
13990        this._drawButton();
13991        this._drawMenu();
13992        this._bindFormResetHandler();
13993
13994        this._rendered = false;
13995        this.menuItems = $();
13996    },
13997
13998    _drawButton: function() {
13999        var icon,
14000            that = this,
14001            item = this._parseOption(
14002                this.element.find( "option:selected" ),
14003                this.element[ 0 ].selectedIndex
14004            );
14005
14006        // Associate existing label with the new button
14007        this.labels = this.element.labels().attr( "for", this.ids.button );
14008        this._on( this.labels, {
14009            click: function( event ) {
14010                this.button.trigger( "focus" );
14011                event.preventDefault();
14012            }
14013        } );
14014
14015        // Hide original select element
14016        this.element.hide();
14017
14018        // Create button
14019        this.button = $( "<span>", {
14020            tabindex: this.options.disabled ? -1 : 0,
14021            id: this.ids.button,
14022            role: "combobox",
14023            "aria-expanded": "false",
14024            "aria-autocomplete": "list",
14025            "aria-owns": this.ids.menu,
14026            "aria-haspopup": "true",
14027            title: this.element.attr( "title" )
14028        } )
14029            .insertAfter( this.element );
14030
14031        this._addClass( this.button, "ui-selectmenu-button ui-selectmenu-button-closed",
14032            "ui-button ui-widget" );
14033
14034        icon = $( "<span>" ).appendTo( this.button );
14035        this._addClass( icon, "ui-selectmenu-icon", "ui-icon " + this.options.icons.button );
14036        this.buttonItem = this._renderButtonItem( item )
14037            .appendTo( this.button );
14038
14039        if ( this.options.width !== false ) {
14040            this._resizeButton();
14041        }
14042
14043        this._on( this.button, this._buttonEvents );
14044        this.button.one( "focusin", function() {
14045
14046            // Delay rendering the menu items until the button receives focus.
14047            // The menu may have already been rendered via a programmatic open.
14048            if ( !that._rendered ) {
14049                that._refreshMenu();
14050            }
14051        } );
14052    },
14053
14054    _drawMenu: function() {
14055        var that = this;
14056
14057        // Create menu
14058        this.menu = $( "<ul>", {
14059            "aria-hidden": "true",
14060            "aria-labelledby": this.ids.button,
14061            id: this.ids.menu
14062        } );
14063
14064        // Wrap menu
14065        this.menuWrap = $( "<div>" ).append( this.menu );
14066        this._addClass( this.menuWrap, "ui-selectmenu-menu", "ui-front" );
14067        this.menuWrap.appendTo( this._appendTo() );
14068
14069        // Initialize menu widget
14070        this.menuInstance = this.menu
14071            .menu( {
14072                classes: {
14073                    "ui-menu": "ui-corner-bottom"
14074                },
14075                role: "listbox",
14076                select: function( event, ui ) {
14077                    event.preventDefault();
14078                    that._select( ui.item.data( "ui-selectmenu-item" ), event );
14079                },
14080                focus: function( event, ui ) {
14081                    var item = ui.item.data( "ui-selectmenu-item" );
14082
14083                    // Prevent inital focus from firing and check if its a newly focused item
14084                    if ( that.focusIndex != null && item.index !== that.focusIndex ) {
14085                        that._trigger( "focus", event, { item: item } );
14086                        if ( !that.isOpen ) {
14087                            that._select( item, event );
14088                        }
14089                    }
14090                    that.focusIndex = item.index;
14091
14092                    that.button.attr( "aria-activedescendant",
14093                        that.menuItems.eq( item.index ).attr( "id" ) );
14094                }
14095            } )
14096            .menu( "instance" );
14097
14098        // Don't close the menu on mouseleave
14099        this.menuInstance._off( this.menu, "mouseleave" );
14100
14101        // Cancel the menu's collapseAll on document click
14102        this.menuInstance._closeOnDocumentClick = function() {
14103            return false;
14104        };
14105
14106        // Selects often contain empty items, but never contain dividers
14107        this.menuInstance._isDivider = function() {
14108            return false;
14109        };
14110    },
14111
14112    refresh: function() {
14113        this._refreshMenu();
14114        this.buttonItem.replaceWith(
14115            this.buttonItem = this._renderButtonItem(
14116
14117                // Fall back to an empty object in case there are no options
14118                this._getSelectedItem().data( "ui-selectmenu-item" ) || {}
14119            )
14120        );
14121        if ( this.options.width === null ) {
14122            this._resizeButton();
14123        }
14124    },
14125
14126    _refreshMenu: function() {
14127        var item,
14128            options = this.element.find( "option" );
14129
14130        this.menu.empty();
14131
14132        this._parseOptions( options );
14133        this._renderMenu( this.menu, this.items );
14134
14135        this.menuInstance.refresh();
14136        this.menuItems = this.menu.find( "li" )
14137            .not( ".ui-selectmenu-optgroup" )
14138                .find( ".ui-menu-item-wrapper" );
14139
14140        this._rendered = true;
14141
14142        if ( !options.length ) {
14143            return;
14144        }
14145
14146        item = this._getSelectedItem();
14147
14148        // Update the menu to have the correct item focused
14149        this.menuInstance.focus( null, item );
14150        this._setAria( item.data( "ui-selectmenu-item" ) );
14151
14152        // Set disabled state
14153        this._setOption( "disabled", this.element.prop( "disabled" ) );
14154    },
14155
14156    open: function( event ) {
14157        if ( this.options.disabled ) {
14158            return;
14159        }
14160
14161        // If this is the first time the menu is being opened, render the items
14162        if ( !this._rendered ) {
14163            this._refreshMenu();
14164        } else {
14165
14166            // Menu clears focus on close, reset focus to selected item
14167            this._removeClass( this.menu.find( ".ui-state-active" ), null, "ui-state-active" );
14168            this.menuInstance.focus( null, this._getSelectedItem() );
14169        }
14170
14171        // If there are no options, don't open the menu
14172        if ( !this.menuItems.length ) {
14173            return;
14174        }
14175
14176        this.isOpen = true;
14177        this._toggleAttr();
14178        this._resizeMenu();
14179        this._position();
14180
14181        this._on( this.document, this._documentClick );
14182
14183        this._trigger( "open", event );
14184    },
14185
14186    _position: function() {
14187        this.menuWrap.position( $.extend( { of: this.button }, this.options.position ) );
14188    },
14189
14190    close: function( event ) {
14191        if ( !this.isOpen ) {
14192            return;
14193        }
14194
14195        this.isOpen = false;
14196        this._toggleAttr();
14197
14198        this.range = null;
14199        this._off( this.document );
14200
14201        this._trigger( "close", event );
14202    },
14203
14204    widget: function() {
14205        return this.button;
14206    },
14207
14208    menuWidget: function() {
14209        return this.menu;
14210    },
14211
14212    _renderButtonItem: function( item ) {
14213        var buttonItem = $( "<span>" );
14214
14215        this._setText( buttonItem, item.label );
14216        this._addClass( buttonItem, "ui-selectmenu-text" );
14217
14218        return buttonItem;
14219    },
14220
14221    _renderMenu: function( ul, items ) {
14222        var that = this,
14223            currentOptgroup = "";
14224
14225        $.each( items, function( index, item ) {
14226            var li;
14227
14228            if ( item.optgroup !== currentOptgroup ) {
14229                li = $( "<li>", {
14230                    text: item.optgroup
14231                } );
14232                that._addClass( li, "ui-selectmenu-optgroup", "ui-menu-divider" +
14233                    ( item.element.parent( "optgroup" ).prop( "disabled" ) ?
14234                        " ui-state-disabled" :
14235                        "" ) );
14236
14237                li.appendTo( ul );
14238
14239                currentOptgroup = item.optgroup;
14240            }
14241
14242            that._renderItemData( ul, item );
14243        } );
14244    },
14245
14246    _renderItemData: function( ul, item ) {
14247        return this._renderItem( ul, item ).data( "ui-selectmenu-item", item );
14248    },
14249
14250    _renderItem: function( ul, item ) {
14251        var li = $( "<li>" ),
14252            wrapper = $( "<div>", {
14253                title: item.element.attr( "title" )
14254            } );
14255
14256        if ( item.disabled ) {
14257            this._addClass( li, null, "ui-state-disabled" );
14258        }
14259
14260        if ( item.hidden ) {
14261            li.prop( "hidden", true );
14262        } else {
14263            this._setText( wrapper, item.label );
14264        }
14265
14266        return li.append( wrapper ).appendTo( ul );
14267    },
14268
14269    _setText: function( element, value ) {
14270        if ( value ) {
14271            element.text( value );
14272        } else {
14273            element.html( "&#160;" );
14274        }
14275    },
14276
14277    _move: function( direction, event ) {
14278        var item, next,
14279            filter = ".ui-menu-item";
14280
14281        if ( this.isOpen ) {
14282            item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14283        } else {
14284            item = this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14285            filter += ":not(.ui-state-disabled)";
14286        }
14287
14288        if ( direction === "first" || direction === "last" ) {
14289            next = item[ direction === "first" ? "prevAll" : "nextAll" ]( filter ).eq( -1 );
14290        } else {
14291            next = item[ direction + "All" ]( filter ).eq( 0 );
14292        }
14293
14294        if ( next.length ) {
14295            this.menuInstance.focus( event, next );
14296        }
14297    },
14298
14299    _getSelectedItem: function() {
14300        return this.menuItems.eq( this.element[ 0 ].selectedIndex ).parent( "li" );
14301    },
14302
14303    _toggle: function( event ) {
14304        this[ this.isOpen ? "close" : "open" ]( event );
14305    },
14306
14307    _setSelection: function() {
14308        var selection;
14309
14310        if ( !this.range ) {
14311            return;
14312        }
14313
14314        selection = window.getSelection();
14315        selection.removeAllRanges();
14316        selection.addRange( this.range );
14317    },
14318
14319    _documentClick: {
14320        mousedown: function( event ) {
14321            if ( !this.isOpen ) {
14322                return;
14323            }
14324
14325            if ( !$( event.target ).closest( ".ui-selectmenu-menu, #" +
14326                CSS.escape( this.ids.button ) ).length ) {
14327                this.close( event );
14328            }
14329        }
14330    },
14331
14332    _buttonEvents: {
14333
14334        // Prevent text selection from being reset when interacting with the selectmenu (#10144)
14335        mousedown: function() {
14336            var selection = window.getSelection();
14337            if ( selection.rangeCount ) {
14338                this.range = selection.getRangeAt( 0 );
14339            }
14340        },
14341
14342        click: function( event ) {
14343            this._setSelection();
14344            this._toggle( event );
14345        },
14346
14347        keydown: function( event ) {
14348            var preventDefault = true;
14349            switch ( event.keyCode ) {
14350            case $.ui.keyCode.TAB:
14351            case $.ui.keyCode.ESCAPE:
14352                this.close( event );
14353                preventDefault = false;
14354                break;
14355            case $.ui.keyCode.ENTER:
14356                if ( this.isOpen ) {
14357                    this._selectFocusedItem( event );
14358                }
14359                break;
14360            case $.ui.keyCode.UP:
14361                if ( event.altKey ) {
14362                    this._toggle( event );
14363                } else {
14364                    this._move( "prev", event );
14365                }
14366                break;
14367            case $.ui.keyCode.DOWN:
14368                if ( event.altKey ) {
14369                    this._toggle( event );
14370                } else {
14371                    this._move( "next", event );
14372                }
14373                break;
14374            case $.ui.keyCode.SPACE:
14375                if ( this.isOpen ) {
14376                    this._selectFocusedItem( event );
14377                } else {
14378                    this._toggle( event );
14379                }
14380                break;
14381            case $.ui.keyCode.LEFT:
14382                this._move( "prev", event );
14383                break;
14384            case $.ui.keyCode.RIGHT:
14385                this._move( "next", event );
14386                break;
14387            case $.ui.keyCode.HOME:
14388            case $.ui.keyCode.PAGE_UP:
14389                this._move( "first", event );
14390                break;
14391            case $.ui.keyCode.END:
14392            case $.ui.keyCode.PAGE_DOWN:
14393                this._move( "last", event );
14394                break;
14395            default:
14396                this.menu.trigger( event );
14397                preventDefault = false;
14398            }
14399
14400            if ( preventDefault ) {
14401                event.preventDefault();
14402            }
14403        }
14404    },
14405
14406    _selectFocusedItem: function( event ) {
14407        var item = this.menuItems.eq( this.focusIndex ).parent( "li" );
14408        if ( !item.hasClass( "ui-state-disabled" ) ) {
14409            this._select( item.data( "ui-selectmenu-item" ), event );
14410        }
14411    },
14412
14413    _select: function( item, event ) {
14414        var oldIndex = this.element[ 0 ].selectedIndex;
14415
14416        // Change native select element
14417        this.element[ 0 ].selectedIndex = item.index;
14418        this.buttonItem.replaceWith( this.buttonItem = this._renderButtonItem( item ) );
14419        this._setAria( item );
14420        this._trigger( "select", event, { item: item } );
14421
14422        if ( item.index !== oldIndex ) {
14423            this._trigger( "change", event, { item: item } );
14424        }
14425
14426        this.close( event );
14427    },
14428
14429    _setAria: function( item ) {
14430        var id = this.menuItems.eq( item.index ).attr( "id" );
14431
14432        this.button.attr( {
14433            "aria-labelledby": id,
14434            "aria-activedescendant": id
14435        } );
14436        this.menu.attr( "aria-activedescendant", id );
14437    },
14438
14439    _setOption: function( key, value ) {
14440        if ( key === "icons" ) {
14441            var icon = this.button.find( "span.ui-icon" );
14442            this._removeClass( icon, null, this.options.icons.button )
14443                ._addClass( icon, null, value.button );
14444        }
14445
14446        this._super( key, value );
14447
14448        if ( key === "appendTo" ) {
14449            this.menuWrap.appendTo( this._appendTo() );
14450        }
14451
14452        if ( key === "width" ) {
14453            this._resizeButton();
14454        }
14455    },
14456
14457    _setOptionDisabled: function( value ) {
14458        this._super( value );
14459
14460        this.menuInstance.option( "disabled", value );
14461        this.button.attr( "aria-disabled", value );
14462        this._toggleClass( this.button, null, "ui-state-disabled", value );
14463
14464        this.element.prop( "disabled", value );
14465        if ( value ) {
14466            this.button.attr( "tabindex", -1 );
14467            this.close();
14468        } else {
14469            this.button.attr( "tabindex", 0 );
14470        }
14471    },
14472
14473    _appendTo: function() {
14474        var element = this.options.appendTo;
14475
14476        if ( element ) {
14477            element = element.jquery || element.nodeType ?
14478                $( element ) :
14479                this.document.find( element ).eq( 0 );
14480        }
14481
14482        if ( !element || !element[ 0 ] ) {
14483            element = this.element.closest( ".ui-front, dialog" );
14484        }
14485
14486        if ( !element.length ) {
14487            element = this.document[ 0 ].body;
14488        }
14489
14490        return element;
14491    },
14492
14493    _toggleAttr: function() {
14494        this.button.attr( "aria-expanded", this.isOpen );
14495
14496        // We can't use two _toggleClass() calls here, because we need to make sure
14497        // we always remove classes first and add them second, otherwise if both classes have the
14498        // same theme class, it will be removed after we add it.
14499        this._removeClass( this.button, "ui-selectmenu-button-" +
14500            ( this.isOpen ? "closed" : "open" ) )
14501            ._addClass( this.button, "ui-selectmenu-button-" +
14502                ( this.isOpen ? "open" : "closed" ) )
14503            ._toggleClass( this.menuWrap, "ui-selectmenu-open", null, this.isOpen );
14504
14505        this.menu.attr( "aria-hidden", !this.isOpen );
14506    },
14507
14508    _resizeButton: function() {
14509        var width = this.options.width;
14510
14511        // For `width: false`, just remove inline style and stop
14512        if ( width === false ) {
14513            this.button.css( "width", "" );
14514            return;
14515        }
14516
14517        // For `width: null`, match the width of the original element
14518        if ( width === null ) {
14519            width = this.element.show().outerWidth();
14520            this.element.hide();
14521        }
14522
14523        this.button.outerWidth( width );
14524    },
14525
14526    _resizeMenu: function() {
14527        this.menu.outerWidth( Math.max(
14528            this.button.outerWidth(),
14529            this.menu.width( "" ).outerWidth()
14530        ) );
14531    },
14532
14533    _getCreateOptions: function() {
14534        var options = this._super();
14535
14536        options.disabled = this.element.prop( "disabled" );
14537
14538        return options;
14539    },
14540
14541    _parseOptions: function( options ) {
14542        var that = this,
14543            data = [];
14544        options.each( function( index, item ) {
14545            data.push( that._parseOption( $( item ), index ) );
14546        } );
14547        this.items = data;
14548    },
14549
14550    _parseOption: function( option, index ) {
14551        var optgroup = option.parent( "optgroup" );
14552
14553        return {
14554            element: option,
14555            index: index,
14556            value: option.val(),
14557            label: option.text(),
14558            hidden: optgroup.prop( "hidden" ) || option.prop( "hidden" ),
14559            optgroup: optgroup.attr( "label" ) || "",
14560            disabled: optgroup.prop( "disabled" ) || option.prop( "disabled" )
14561        };
14562    },
14563
14564    _destroy: function() {
14565        this._unbindFormResetHandler();
14566        this.menuWrap.remove();
14567        this.button.remove();
14568        this.element.show();
14569        this.element.removeUniqueId();
14570        this.labels.attr( "for", this.ids.element );
14571    }
14572} ] );
14573
14574
14575/*!
14576 * jQuery UI Slider 1.14.1
14577 * https://jqueryui.com
14578 *
14579 * Copyright OpenJS Foundation and other contributors
14580 * Released under the MIT license.
14581 * https://jquery.org/license
14582 */
14583
14584//>>label: Slider
14585//>>group: Widgets
14586//>>description: Displays a flexible slider with ranges and accessibility via keyboard.
14587//>>docs: https://api.jqueryui.com/slider/
14588//>>demos: https://jqueryui.com/slider/
14589//>>css.structure: ../../themes/base/core.css
14590//>>css.structure: ../../themes/base/slider.css
14591//>>css.theme: ../../themes/base/theme.css
14592
14593
14594var widgetsSlider = $.widget( "ui.slider", $.ui.mouse, {
14595    version: "1.14.1",
14596    widgetEventPrefix: "slide",
14597
14598    options: {
14599        animate: false,
14600        classes: {
14601            "ui-slider": "ui-corner-all",
14602            "ui-slider-handle": "ui-corner-all",
14603
14604            // Note: ui-widget-header isn't the most fittingly semantic framework class for this
14605            // element, but worked best visually with a variety of themes
14606            "ui-slider-range": "ui-corner-all ui-widget-header"
14607        },
14608        distance: 0,
14609        max: 100,
14610        min: 0,
14611        orientation: "horizontal",
14612        range: false,
14613        step: 1,
14614        value: 0,
14615        values: null,
14616
14617        // Callbacks
14618        change: null,
14619        slide: null,
14620        start: null,
14621        stop: null
14622    },
14623
14624    // Number of pages in a slider
14625    // (how many times can you page up/down to go through the whole range)
14626    numPages: 5,
14627
14628    _create: function() {
14629        this._keySliding = false;
14630        this._mouseSliding = false;
14631        this._animateOff = true;
14632        this._handleIndex = null;
14633        this._detectOrientation();
14634        this._mouseInit();
14635        this._calculateNewMax();
14636
14637        this._addClass( "ui-slider ui-slider-" + this.orientation,
14638            "ui-widget ui-widget-content" );
14639
14640        this._refresh();
14641
14642        this._animateOff = false;
14643    },
14644
14645    _refresh: function() {
14646        this._createRange();
14647        this._createHandles();
14648        this._setupEvents();
14649        this._refreshValue();
14650    },
14651
14652    _createHandles: function() {
14653        var i, handleCount,
14654            options = this.options,
14655            existingHandles = this.element.find( ".ui-slider-handle" ),
14656            handle = "<span tabindex='0'></span>",
14657            handles = [];
14658
14659        handleCount = ( options.values && options.values.length ) || 1;
14660
14661        if ( existingHandles.length > handleCount ) {
14662            existingHandles.slice( handleCount ).remove();
14663            existingHandles = existingHandles.slice( 0, handleCount );
14664        }
14665
14666        for ( i = existingHandles.length; i < handleCount; i++ ) {
14667            handles.push( handle );
14668        }
14669
14670        this.handles = existingHandles.add( $( handles.join( "" ) ).appendTo( this.element ) );
14671
14672        this._addClass( this.handles, "ui-slider-handle", "ui-state-default" );
14673
14674        this.handle = this.handles.eq( 0 );
14675
14676        this.handles.each( function( i ) {
14677            $( this )
14678                .data( "ui-slider-handle-index", i )
14679                .attr( "tabIndex", 0 );
14680        } );
14681    },
14682
14683    _createRange: function() {
14684        var options = this.options;
14685
14686        if ( options.range ) {
14687            if ( options.range === true ) {
14688                if ( !options.values ) {
14689                    options.values = [ this._valueMin(), this._valueMin() ];
14690                } else if ( options.values.length && options.values.length !== 2 ) {
14691                    options.values = [ options.values[ 0 ], options.values[ 0 ] ];
14692                } else if ( Array.isArray( options.values ) ) {
14693                    options.values = options.values.slice( 0 );
14694                }
14695            }
14696
14697            if ( !this.range || !this.range.length ) {
14698                this.range = $( "<div>" )
14699                    .appendTo( this.element );
14700
14701                this._addClass( this.range, "ui-slider-range" );
14702            } else {
14703                this._removeClass( this.range, "ui-slider-range-min ui-slider-range-max" );
14704
14705                // Handle range switching from true to min/max
14706                this.range.css( {
14707                    "left": "",
14708                    "bottom": ""
14709                } );
14710            }
14711            if ( options.range === "min" || options.range === "max" ) {
14712                this._addClass( this.range, "ui-slider-range-" + options.range );
14713            }
14714        } else {
14715            if ( this.range ) {
14716                this.range.remove();
14717            }
14718            this.range = null;
14719        }
14720    },
14721
14722    _setupEvents: function() {
14723        this._off( this.handles );
14724        this._on( this.handles, this._handleEvents );
14725        this._hoverable( this.handles );
14726        this._focusable( this.handles );
14727    },
14728
14729    _destroy: function() {
14730        this.handles.remove();
14731        if ( this.range ) {
14732            this.range.remove();
14733        }
14734
14735        this._mouseDestroy();
14736    },
14737
14738    _mouseCapture: function( event ) {
14739        var position, normValue, distance, closestHandle, index, allowed, offset, mouseOverHandle,
14740            that = this,
14741            o = this.options;
14742
14743        if ( o.disabled ) {
14744            return false;
14745        }
14746
14747        this.elementSize = {
14748            width: this.element.outerWidth(),
14749            height: this.element.outerHeight()
14750        };
14751        this.elementOffset = this.element.offset();
14752
14753        position = { x: event.pageX, y: event.pageY };
14754        normValue = this._normValueFromMouse( position );
14755        distance = this._valueMax() - this._valueMin() + 1;
14756        this.handles.each( function( i ) {
14757            var thisDistance = Math.abs( normValue - that.values( i ) );
14758            if ( ( distance > thisDistance ) ||
14759                ( distance === thisDistance &&
14760                    ( i === that._lastChangedValue || that.values( i ) === o.min ) ) ) {
14761                distance = thisDistance;
14762                closestHandle = $( this );
14763                index = i;
14764            }
14765        } );
14766
14767        allowed = this._start( event, index );
14768        if ( allowed === false ) {
14769            return false;
14770        }
14771        this._mouseSliding = true;
14772
14773        this._handleIndex = index;
14774
14775        this._addClass( closestHandle, null, "ui-state-active" );
14776        closestHandle.trigger( "focus" );
14777
14778        offset = closestHandle.offset();
14779        mouseOverHandle = !$( event.target ).parents().addBack().is( ".ui-slider-handle" );
14780        this._clickOffset = mouseOverHandle ? { left: 0, top: 0 } : {
14781            left: event.pageX - offset.left - ( closestHandle.width() / 2 ),
14782            top: event.pageY - offset.top -
14783                ( closestHandle.height() / 2 ) -
14784                ( parseInt( closestHandle.css( "borderTopWidth" ), 10 ) || 0 ) -
14785                ( parseInt( closestHandle.css( "borderBottomWidth" ), 10 ) || 0 ) +
14786                ( parseInt( closestHandle.css( "marginTop" ), 10 ) || 0 )
14787        };
14788
14789        if ( !this.handles.hasClass( "ui-state-hover" ) ) {
14790            this._slide( event, index, normValue );
14791        }
14792        this._animateOff = true;
14793        return true;
14794    },
14795
14796    _mouseStart: function() {
14797        return true;
14798    },
14799
14800    _mouseDrag: function( event ) {
14801        var position = { x: event.pageX, y: event.pageY },
14802            normValue = this._normValueFromMouse( position );
14803
14804        this._slide( event, this._handleIndex, normValue );
14805
14806        return false;
14807    },
14808
14809    _mouseStop: function( event ) {
14810        this._removeClass( this.handles, null, "ui-state-active" );
14811        this._mouseSliding = false;
14812
14813        this._stop( event, this._handleIndex );
14814        this._change( event, this._handleIndex );
14815
14816        this._handleIndex = null;
14817        this._clickOffset = null;
14818        this._animateOff = false;
14819
14820        return false;
14821    },
14822
14823    _detectOrientation: function() {
14824        this.orientation = ( this.options.orientation === "vertical" ) ? "vertical" : "horizontal";
14825    },
14826
14827    _normValueFromMouse: function( position ) {
14828        var pixelTotal,
14829            pixelMouse,
14830            percentMouse,
14831            valueTotal,
14832            valueMouse;
14833
14834        if ( this.orientation === "horizontal" ) {
14835            pixelTotal = this.elementSize.width;
14836            pixelMouse = position.x - this.elementOffset.left -
14837                ( this._clickOffset ? this._clickOffset.left : 0 );
14838        } else {
14839            pixelTotal = this.elementSize.height;
14840            pixelMouse = position.y - this.elementOffset.top -
14841                ( this._clickOffset ? this._clickOffset.top : 0 );
14842        }
14843
14844        percentMouse = ( pixelMouse / pixelTotal );
14845        if ( percentMouse > 1 ) {
14846            percentMouse = 1;
14847        }
14848        if ( percentMouse < 0 ) {
14849            percentMouse = 0;
14850        }
14851        if ( this.orientation === "vertical" ) {
14852            percentMouse = 1 - percentMouse;
14853        }
14854
14855        valueTotal = this._valueMax() - this._valueMin();
14856        valueMouse = this._valueMin() + percentMouse * valueTotal;
14857
14858        return this._trimAlignValue( valueMouse );
14859    },
14860
14861    _uiHash: function( index, value, values ) {
14862        var uiHash = {
14863            handle: this.handles[ index ],
14864            handleIndex: index,
14865            value: value !== undefined ? value : this.value()
14866        };
14867
14868        if ( this._hasMultipleValues() ) {
14869            uiHash.value = value !== undefined ? value : this.values( index );
14870            uiHash.values = values || this.values();
14871        }
14872
14873        return uiHash;
14874    },
14875
14876    _hasMultipleValues: function() {
14877        return this.options.values && this.options.values.length;
14878    },
14879
14880    _start: function( event, index ) {
14881        return this._trigger( "start", event, this._uiHash( index ) );
14882    },
14883
14884    _slide: function( event, index, newVal ) {
14885        var allowed, otherVal,
14886            currentValue = this.value(),
14887            newValues = this.values();
14888
14889        if ( this._hasMultipleValues() ) {
14890            otherVal = this.values( index ? 0 : 1 );
14891            currentValue = this.values( index );
14892
14893            if ( this.options.values.length === 2 && this.options.range === true ) {
14894                newVal =  index === 0 ? Math.min( otherVal, newVal ) : Math.max( otherVal, newVal );
14895            }
14896
14897            newValues[ index ] = newVal;
14898        }
14899
14900        if ( newVal === currentValue ) {
14901            return;
14902        }
14903
14904        allowed = this._trigger( "slide", event, this._uiHash( index, newVal, newValues ) );
14905
14906        // A slide can be canceled by returning false from the slide callback
14907        if ( allowed === false ) {
14908            return;
14909        }
14910
14911        if ( this._hasMultipleValues() ) {
14912            this.values( index, newVal );
14913        } else {
14914            this.value( newVal );
14915        }
14916    },
14917
14918    _stop: function( event, index ) {
14919        this._trigger( "stop", event, this._uiHash( index ) );
14920    },
14921
14922    _change: function( event, index ) {
14923        if ( !this._keySliding && !this._mouseSliding ) {
14924
14925            //store the last changed value index for reference when handles overlap
14926            this._lastChangedValue = index;
14927            this._trigger( "change", event, this._uiHash( index ) );
14928        }
14929    },
14930
14931    value: function( newValue ) {
14932        if ( arguments.length ) {
14933            this.options.value = this._trimAlignValue( newValue );
14934            this._refreshValue();
14935            this._change( null, 0 );
14936            return;
14937        }
14938
14939        return this._value();
14940    },
14941
14942    values: function( index, newValue ) {
14943        var vals,
14944            newValues,
14945            i;
14946
14947        if ( arguments.length > 1 ) {
14948            this.options.values[ index ] = this._trimAlignValue( newValue );
14949            this._refreshValue();
14950            this._change( null, index );
14951            return;
14952        }
14953
14954        if ( arguments.length ) {
14955            if ( Array.isArray( arguments[ 0 ] ) ) {
14956                vals = this.options.values;
14957                newValues = arguments[ 0 ];
14958                for ( i = 0; i < vals.length; i += 1 ) {
14959                    vals[ i ] = this._trimAlignValue( newValues[ i ] );
14960                    this._change( null, i );
14961                }
14962                this._refreshValue();
14963            } else {
14964                if ( this._hasMultipleValues() ) {
14965                    return this._values( index );
14966                } else {
14967                    return this.value();
14968                }
14969            }
14970        } else {
14971            return this._values();
14972        }
14973    },
14974
14975    _setOption: function( key, value ) {
14976        var i,
14977            valsLength = 0;
14978
14979        if ( key === "range" && this.options.range === true ) {
14980            if ( value === "min" ) {
14981                this.options.value = this._values( 0 );
14982                this.options.values = null;
14983            } else if ( value === "max" ) {
14984                this.options.value = this._values( this.options.values.length - 1 );
14985                this.options.values = null;
14986            }
14987        }
14988
14989        if ( Array.isArray( this.options.values ) ) {
14990            valsLength = this.options.values.length;
14991        }
14992
14993        this._super( key, value );
14994
14995        switch ( key ) {
14996            case "orientation":
14997                this._detectOrientation();
14998                this._removeClass( "ui-slider-horizontal ui-slider-vertical" )
14999                    ._addClass( "ui-slider-" + this.orientation );
15000                this._refreshValue();
15001                if ( this.options.range ) {
15002                    this._refreshRange( value );
15003                }
15004
15005                // Reset positioning from previous orientation
15006                this.handles.css( value === "horizontal" ? "bottom" : "left", "" );
15007                break;
15008            case "value":
15009                this._animateOff = true;
15010                this._refreshValue();
15011                this._change( null, 0 );
15012                this._animateOff = false;
15013                break;
15014            case "values":
15015                this._animateOff = true;
15016                this._refreshValue();
15017
15018                // Start from the last handle to prevent unreachable handles (#9046)
15019                for ( i = valsLength - 1; i >= 0; i-- ) {
15020                    this._change( null, i );
15021                }
15022                this._animateOff = false;
15023                break;
15024            case "step":
15025            case "min":
15026            case "max":
15027                this._animateOff = true;
15028                this._calculateNewMax();
15029                this._refreshValue();
15030                this._animateOff = false;
15031                break;
15032            case "range":
15033                this._animateOff = true;
15034                this._refresh();
15035                this._animateOff = false;
15036                break;
15037        }
15038    },
15039
15040    _setOptionDisabled: function( value ) {
15041        this._super( value );
15042
15043        this._toggleClass( null, "ui-state-disabled", !!value );
15044    },
15045
15046    //internal value getter
15047    // _value() returns value trimmed by min and max, aligned by step
15048    _value: function() {
15049        var val = this.options.value;
15050        val = this._trimAlignValue( val );
15051
15052        return val;
15053    },
15054
15055    //internal values getter
15056    // _values() returns array of values trimmed by min and max, aligned by step
15057    // _values( index ) returns single value trimmed by min and max, aligned by step
15058    _values: function( index ) {
15059        var val,
15060            vals,
15061            i;
15062
15063        if ( arguments.length ) {
15064            val = this.options.values[ index ];
15065            val = this._trimAlignValue( val );
15066
15067            return val;
15068        } else if ( this._hasMultipleValues() ) {
15069
15070            // .slice() creates a copy of the array
15071            // this copy gets trimmed by min and max and then returned
15072            vals = this.options.values.slice();
15073            for ( i = 0; i < vals.length; i += 1 ) {
15074                vals[ i ] = this._trimAlignValue( vals[ i ] );
15075            }
15076
15077            return vals;
15078        } else {
15079            return [];
15080        }
15081    },
15082
15083    // Returns the step-aligned value that val is closest to, between (inclusive) min and max
15084    _trimAlignValue: function( val ) {
15085        if ( val <= this._valueMin() ) {
15086            return this._valueMin();
15087        }
15088        if ( val >= this._valueMax() ) {
15089            return this._valueMax();
15090        }
15091        var step = ( this.options.step > 0 ) ? this.options.step : 1,
15092            valModStep = ( val - this._valueMin() ) % step,
15093            alignValue = val - valModStep;
15094
15095        if ( Math.abs( valModStep ) * 2 >= step ) {
15096            alignValue += ( valModStep > 0 ) ? step : ( -step );
15097        }
15098
15099        // Since JavaScript has problems with large floats, round
15100        // the final value to 5 digits after the decimal point (see #4124)
15101        return parseFloat( alignValue.toFixed( 5 ) );
15102    },
15103
15104    _calculateNewMax: function() {
15105        var max = this.options.max,
15106            min = this._valueMin(),
15107            step = this.options.step,
15108            aboveMin = Math.round( ( max - min ) / step ) * step;
15109        max = aboveMin + min;
15110        if ( max > this.options.max ) {
15111
15112            //If max is not divisible by step, rounding off may increase its value
15113            max -= step;
15114        }
15115        this.max = parseFloat( max.toFixed( this._precision() ) );
15116    },
15117
15118    _precision: function() {
15119        var precision = this._precisionOf( this.options.step );
15120        if ( this.options.min !== null ) {
15121            precision = Math.max( precision, this._precisionOf( this.options.min ) );
15122        }
15123        return precision;
15124    },
15125
15126    _precisionOf: function( num ) {
15127        var str = num.toString(),
15128            decimal = str.indexOf( "." );
15129        return decimal === -1 ? 0 : str.length - decimal - 1;
15130    },
15131
15132    _valueMin: function() {
15133        return this.options.min;
15134    },
15135
15136    _valueMax: function() {
15137        return this.max;
15138    },
15139
15140    _refreshRange: function( orientation ) {
15141        if ( orientation === "vertical" ) {
15142            this.range.css( { "width": "", "left": "" } );
15143        }
15144        if ( orientation === "horizontal" ) {
15145            this.range.css( { "height": "", "bottom": "" } );
15146        }
15147    },
15148
15149    _refreshValue: function() {
15150        var lastValPercent, valPercent, value, valueMin, valueMax,
15151            oRange = this.options.range,
15152            o = this.options,
15153            that = this,
15154            animate = ( !this._animateOff ) ? o.animate : false,
15155            _set = {};
15156
15157        if ( this._hasMultipleValues() ) {
15158            this.handles.each( function( i ) {
15159                valPercent = ( that.values( i ) - that._valueMin() ) / ( that._valueMax() -
15160                    that._valueMin() ) * 100;
15161                _set[ that.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15162                $( this ).stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15163                if ( that.options.range === true ) {
15164                    if ( that.orientation === "horizontal" ) {
15165                        if ( i === 0 ) {
15166                            that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15167                                left: valPercent + "%"
15168                            }, o.animate );
15169                        }
15170                        if ( i === 1 ) {
15171                            that.range[ animate ? "animate" : "css" ]( {
15172                                width: ( valPercent - lastValPercent ) + "%"
15173                            }, {
15174                                queue: false,
15175                                duration: o.animate
15176                            } );
15177                        }
15178                    } else {
15179                        if ( i === 0 ) {
15180                            that.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15181                                bottom: ( valPercent ) + "%"
15182                            }, o.animate );
15183                        }
15184                        if ( i === 1 ) {
15185                            that.range[ animate ? "animate" : "css" ]( {
15186                                height: ( valPercent - lastValPercent ) + "%"
15187                            }, {
15188                                queue: false,
15189                                duration: o.animate
15190                            } );
15191                        }
15192                    }
15193                }
15194                lastValPercent = valPercent;
15195            } );
15196        } else {
15197            value = this.value();
15198            valueMin = this._valueMin();
15199            valueMax = this._valueMax();
15200            valPercent = ( valueMax !== valueMin ) ?
15201                    ( value - valueMin ) / ( valueMax - valueMin ) * 100 :
15202                    0;
15203            _set[ this.orientation === "horizontal" ? "left" : "bottom" ] = valPercent + "%";
15204            this.handle.stop( 1, 1 )[ animate ? "animate" : "css" ]( _set, o.animate );
15205
15206            if ( oRange === "min" && this.orientation === "horizontal" ) {
15207                this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15208                    width: valPercent + "%"
15209                }, o.animate );
15210            }
15211            if ( oRange === "max" && this.orientation === "horizontal" ) {
15212                this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15213                    width: ( 100 - valPercent ) + "%"
15214                }, o.animate );
15215            }
15216            if ( oRange === "min" && this.orientation === "vertical" ) {
15217                this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15218                    height: valPercent + "%"
15219                }, o.animate );
15220            }
15221            if ( oRange === "max" && this.orientation === "vertical" ) {
15222                this.range.stop( 1, 1 )[ animate ? "animate" : "css" ]( {
15223                    height: ( 100 - valPercent ) + "%"
15224                }, o.animate );
15225            }
15226        }
15227    },
15228
15229    _handleEvents: {
15230        keydown: function( event ) {
15231            var allowed, curVal, newVal, step,
15232                index = $( event.target ).data( "ui-slider-handle-index" );
15233
15234            switch ( event.keyCode ) {
15235                case $.ui.keyCode.HOME:
15236                case $.ui.keyCode.END:
15237                case $.ui.keyCode.PAGE_UP:
15238                case $.ui.keyCode.PAGE_DOWN:
15239                case $.ui.keyCode.UP:
15240                case $.ui.keyCode.RIGHT:
15241                case $.ui.keyCode.DOWN:
15242                case $.ui.keyCode.LEFT:
15243                    event.preventDefault();
15244                    if ( !this._keySliding ) {
15245                        this._keySliding = true;
15246                        this._addClass( $( event.target ), null, "ui-state-active" );
15247                        allowed = this._start( event, index );
15248                        if ( allowed === false ) {
15249                            return;
15250                        }
15251                    }
15252                    break;
15253            }
15254
15255            step = this.options.step;
15256            if ( this._hasMultipleValues() ) {
15257                curVal = newVal = this.values( index );
15258            } else {
15259                curVal = newVal = this.value();
15260            }
15261
15262            switch ( event.keyCode ) {
15263                case $.ui.keyCode.HOME:
15264                    newVal = this._valueMin();
15265                    break;
15266                case $.ui.keyCode.END:
15267                    newVal = this._valueMax();
15268                    break;
15269                case $.ui.keyCode.PAGE_UP:
15270                    newVal = this._trimAlignValue(
15271                        curVal + ( ( this._valueMax() - this._valueMin() ) / this.numPages )
15272                    );
15273                    break;
15274                case $.ui.keyCode.PAGE_DOWN:
15275                    newVal = this._trimAlignValue(
15276                        curVal - ( ( this._valueMax() - this._valueMin() ) / this.numPages ) );
15277                    break;
15278                case $.ui.keyCode.UP:
15279                case $.ui.keyCode.RIGHT:
15280                    if ( curVal === this._valueMax() ) {
15281                        return;
15282                    }
15283                    newVal = this._trimAlignValue( curVal + step );
15284                    break;
15285                case $.ui.keyCode.DOWN:
15286                case $.ui.keyCode.LEFT:
15287                    if ( curVal === this._valueMin() ) {
15288                        return;
15289                    }
15290                    newVal = this._trimAlignValue( curVal - step );
15291                    break;
15292            }
15293
15294            this._slide( event, index, newVal );
15295        },
15296        keyup: function( event ) {
15297            var index = $( event.target ).data( "ui-slider-handle-index" );
15298
15299            if ( this._keySliding ) {
15300                this._keySliding = false;
15301                this._stop( event, index );
15302                this._change( event, index );
15303                this._removeClass( $( event.target ), null, "ui-state-active" );
15304            }
15305        }
15306    }
15307} );
15308
15309
15310/*!
15311 * jQuery UI Sortable 1.14.1
15312 * https://jqueryui.com
15313 *
15314 * Copyright OpenJS Foundation and other contributors
15315 * Released under the MIT license.
15316 * https://jquery.org/license
15317 */
15318
15319//>>label: Sortable
15320//>>group: Interactions
15321//>>description: Enables items in a list to be sorted using the mouse.
15322//>>docs: https://api.jqueryui.com/sortable/
15323//>>demos: https://jqueryui.com/sortable/
15324//>>css.structure: ../../themes/base/sortable.css
15325
15326
15327var widgetsSortable = $.widget( "ui.sortable", $.ui.mouse, {
15328    version: "1.14.1",
15329    widgetEventPrefix: "sort",
15330    ready: false,
15331    options: {
15332        appendTo: "parent",
15333        axis: false,
15334        connectWith: false,
15335        containment: false,
15336        cursor: "auto",
15337        cursorAt: false,
15338        dropOnEmpty: true,
15339        forcePlaceholderSize: false,
15340        forceHelperSize: false,
15341        grid: false,
15342        handle: false,
15343        helper: "original",
15344        items: "> *",
15345        opacity: false,
15346        placeholder: false,
15347        revert: false,
15348        scroll: true,
15349        scrollSensitivity: 20,
15350        scrollSpeed: 20,
15351        scope: "default",
15352        tolerance: "intersect",
15353        zIndex: 1000,
15354
15355        // Callbacks
15356        activate: null,
15357        beforeStop: null,
15358        change: null,
15359        deactivate: null,
15360        out: null,
15361        over: null,
15362        receive: null,
15363        remove: null,
15364        sort: null,
15365        start: null,
15366        stop: null,
15367        update: null
15368    },
15369
15370    _isOverAxis: function( x, reference, size ) {
15371        return ( x >= reference ) && ( x < ( reference + size ) );
15372    },
15373
15374    _isFloating: function( item ) {
15375        return ( /left|right/ ).test( item.css( "float" ) ) ||
15376            ( /inline|table-cell/ ).test( item.css( "display" ) );
15377    },
15378
15379    _create: function() {
15380        this.containerCache = {};
15381        this._addClass( "ui-sortable" );
15382
15383        //Get the items
15384        this.refresh();
15385
15386        //Let's determine the parent's offset
15387        this.offset = this.element.offset();
15388
15389        //Initialize mouse events for interaction
15390        this._mouseInit();
15391
15392        this._setHandleClassName();
15393
15394        //We're ready to go
15395        this.ready = true;
15396
15397    },
15398
15399    _setOption: function( key, value ) {
15400        this._super( key, value );
15401
15402        if ( key === "handle" ) {
15403            this._setHandleClassName();
15404        }
15405    },
15406
15407    _setHandleClassName: function() {
15408        var that = this;
15409        this._removeClass( this.element.find( ".ui-sortable-handle" ), "ui-sortable-handle" );
15410        $.each( this.items, function() {
15411            that._addClass(
15412                this.instance.options.handle ?
15413                    this.item.find( this.instance.options.handle ) :
15414                    this.item,
15415                "ui-sortable-handle"
15416            );
15417        } );
15418    },
15419
15420    _destroy: function() {
15421        this._mouseDestroy();
15422
15423        for ( var i = this.items.length - 1; i >= 0; i-- ) {
15424            this.items[ i ].item.removeData( this.widgetName + "-item" );
15425        }
15426
15427        return this;
15428    },
15429
15430    _mouseCapture: function( event, overrideHandle ) {
15431        var currentItem = null,
15432            validHandle = false,
15433            that = this;
15434
15435        if ( this.reverting ) {
15436            return false;
15437        }
15438
15439        if ( this.options.disabled || this.options.type === "static" ) {
15440            return false;
15441        }
15442
15443        //We have to refresh the items data once first
15444        this._refreshItems( event );
15445
15446        //Find out if the clicked node (or one of its parents) is a actual item in this.items
15447        $( event.target ).parents().each( function() {
15448            if ( $.data( this, that.widgetName + "-item" ) === that ) {
15449                currentItem = $( this );
15450                return false;
15451            }
15452        } );
15453        if ( $.data( event.target, that.widgetName + "-item" ) === that ) {
15454            currentItem = $( event.target );
15455        }
15456
15457        if ( !currentItem ) {
15458            return false;
15459        }
15460        if ( this.options.handle && !overrideHandle ) {
15461            $( this.options.handle, currentItem ).find( "*" ).addBack().each( function() {
15462                if ( this === event.target ) {
15463                    validHandle = true;
15464                }
15465            } );
15466            if ( !validHandle ) {
15467                return false;
15468            }
15469        }
15470
15471        this.currentItem = currentItem;
15472        this._removeCurrentsFromItems();
15473        return true;
15474
15475    },
15476
15477    _mouseStart: function( event, overrideHandle, noActivation ) {
15478
15479        var i, body,
15480            o = this.options;
15481
15482        this.currentContainer = this;
15483
15484        //We only need to call refreshPositions, because the refreshItems call has been moved to
15485        // mouseCapture
15486        this.refreshPositions();
15487
15488        //Prepare the dragged items parent
15489        this.appendTo = $( o.appendTo !== "parent" ?
15490                o.appendTo :
15491                this.currentItem.parent() );
15492
15493        //Create and append the visible helper
15494        this.helper = this._createHelper( event );
15495
15496        //Cache the helper size
15497        this._cacheHelperProportions();
15498
15499        /*
15500         * - Position generation -
15501         * This block generates everything position related - it's the core of draggables.
15502         */
15503
15504        //Cache the margins of the original element
15505        this._cacheMargins();
15506
15507        //The element's absolute position on the page minus margins
15508        this.offset = this.currentItem.offset();
15509        this.offset = {
15510            top: this.offset.top - this.margins.top,
15511            left: this.offset.left - this.margins.left
15512        };
15513
15514        $.extend( this.offset, {
15515            click: { //Where the click happened, relative to the element
15516                left: event.pageX - this.offset.left,
15517                top: event.pageY - this.offset.top
15518            },
15519
15520            // This is a relative to absolute position minus the actual position calculation -
15521            // only used for relative positioned helper
15522            relative: this._getRelativeOffset()
15523        } );
15524
15525        // After we get the helper offset, but before we get the parent offset we can
15526        // change the helper's position to absolute
15527        // TODO: Still need to figure out a way to make relative sorting possible
15528        this.helper.css( "position", "absolute" );
15529        this.cssPosition = this.helper.css( "position" );
15530
15531        //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
15532        if ( o.cursorAt ) {
15533            this._adjustOffsetFromHelper( o.cursorAt );
15534        }
15535
15536        //Cache the former DOM position
15537        this.domPosition = {
15538            prev: this.currentItem.prev()[ 0 ],
15539            parent: this.currentItem.parent()[ 0 ]
15540        };
15541
15542        // If the helper is not the original, hide the original so it's not playing any role during
15543        // the drag, won't cause anything bad this way
15544        if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
15545            this.currentItem.hide();
15546        }
15547
15548        //Create the placeholder
15549        this._createPlaceholder();
15550
15551        //Get the next scrolling parent
15552        this.scrollParent = this.placeholder.scrollParent();
15553
15554        $.extend( this.offset, {
15555            parent: this._getParentOffset()
15556        } );
15557
15558        //Set a containment if given in the options
15559        if ( o.containment ) {
15560            this._setContainment();
15561        }
15562
15563        if ( o.cursor && o.cursor !== "auto" ) { // cursor option
15564            body = this.document.find( "body" );
15565
15566            this._storedStylesheet =
15567                $( "<style>*{ cursor: " + o.cursor + " !important; }</style>" ).appendTo( body );
15568        }
15569
15570        // We need to make sure to grab the zIndex before setting the
15571        // opacity, because setting the opacity to anything lower than 1
15572        // causes the zIndex to change from "auto" to 0.
15573        if ( o.zIndex ) { // zIndex option
15574            if ( this.helper.css( "zIndex" ) ) {
15575                this._storedZIndex = this.helper.css( "zIndex" );
15576            }
15577            this.helper.css( "zIndex", o.zIndex );
15578        }
15579
15580        if ( o.opacity ) { // opacity option
15581            if ( this.helper.css( "opacity" ) ) {
15582                this._storedOpacity = this.helper.css( "opacity" );
15583            }
15584            this.helper.css( "opacity", o.opacity );
15585        }
15586
15587        //Prepare scrolling
15588        if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15589                this.scrollParent[ 0 ].tagName !== "HTML" ) {
15590            this.overflowOffset = this.scrollParent.offset();
15591        }
15592
15593        //Call callbacks
15594        this._trigger( "start", event, this._uiHash() );
15595
15596        //Recache the helper size
15597        if ( !this._preserveHelperProportions ) {
15598            this._cacheHelperProportions();
15599        }
15600
15601        //Post "activate" events to possible containers
15602        if ( !noActivation ) {
15603            for ( i = this.containers.length - 1; i >= 0; i-- ) {
15604                this.containers[ i ]._trigger( "activate", event, this._uiHash( this ) );
15605            }
15606        }
15607
15608        //Prepare possible droppables
15609        if ( $.ui.ddmanager ) {
15610            $.ui.ddmanager.current = this;
15611        }
15612
15613        if ( $.ui.ddmanager && !o.dropBehaviour ) {
15614            $.ui.ddmanager.prepareOffsets( this, event );
15615        }
15616
15617        this.dragging = true;
15618
15619        this._addClass( this.helper, "ui-sortable-helper" );
15620
15621        //Move the helper, if needed
15622        if ( !this.helper.parent().is( this.appendTo ) ) {
15623            this.helper.detach().appendTo( this.appendTo );
15624
15625            //Update position
15626            this.offset.parent = this._getParentOffset();
15627        }
15628
15629        //Generate the original position
15630        this.position = this.originalPosition = this._generatePosition( event );
15631        this.originalPageX = event.pageX;
15632        this.originalPageY = event.pageY;
15633        this.lastPositionAbs = this.positionAbs = this._convertPositionTo( "absolute" );
15634
15635        this._mouseDrag( event );
15636
15637        return true;
15638
15639    },
15640
15641    _scroll: function( event ) {
15642        var o = this.options,
15643            scrolled = false;
15644
15645        if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
15646                this.scrollParent[ 0 ].tagName !== "HTML" ) {
15647
15648            if ( ( this.overflowOffset.top + this.scrollParent[ 0 ].offsetHeight ) -
15649                    event.pageY < o.scrollSensitivity ) {
15650                this.scrollParent[ 0 ].scrollTop =
15651                    scrolled = this.scrollParent[ 0 ].scrollTop + o.scrollSpeed;
15652            } else if ( event.pageY - this.overflowOffset.top < o.scrollSensitivity ) {
15653                this.scrollParent[ 0 ].scrollTop =
15654                    scrolled = this.scrollParent[ 0 ].scrollTop - o.scrollSpeed;
15655            }
15656
15657            if ( ( this.overflowOffset.left + this.scrollParent[ 0 ].offsetWidth ) -
15658                    event.pageX < o.scrollSensitivity ) {
15659                this.scrollParent[ 0 ].scrollLeft = scrolled =
15660                    this.scrollParent[ 0 ].scrollLeft + o.scrollSpeed;
15661            } else if ( event.pageX - this.overflowOffset.left < o.scrollSensitivity ) {
15662                this.scrollParent[ 0 ].scrollLeft = scrolled =
15663                    this.scrollParent[ 0 ].scrollLeft - o.scrollSpeed;
15664            }
15665
15666        } else {
15667
15668            if ( event.pageY - this.document.scrollTop() < o.scrollSensitivity ) {
15669                scrolled = this.document.scrollTop( this.document.scrollTop() - o.scrollSpeed );
15670            } else if ( this.window.height() - ( event.pageY - this.document.scrollTop() ) <
15671                    o.scrollSensitivity ) {
15672                scrolled = this.document.scrollTop( this.document.scrollTop() + o.scrollSpeed );
15673            }
15674
15675            if ( event.pageX - this.document.scrollLeft() < o.scrollSensitivity ) {
15676                scrolled = this.document.scrollLeft(
15677                    this.document.scrollLeft() - o.scrollSpeed
15678                );
15679            } else if ( this.window.width() - ( event.pageX - this.document.scrollLeft() ) <
15680                    o.scrollSensitivity ) {
15681                scrolled = this.document.scrollLeft(
15682                    this.document.scrollLeft() + o.scrollSpeed
15683                );
15684            }
15685
15686        }
15687
15688        return scrolled;
15689    },
15690
15691    _mouseDrag: function( event ) {
15692        var i, item, itemElement, intersection,
15693            o = this.options;
15694
15695        //Compute the helpers position
15696        this.position = this._generatePosition( event );
15697        this.positionAbs = this._convertPositionTo( "absolute" );
15698
15699        //Set the helper position
15700        if ( !this.options.axis || this.options.axis !== "y" ) {
15701            this.helper[ 0 ].style.left = this.position.left + "px";
15702        }
15703        if ( !this.options.axis || this.options.axis !== "x" ) {
15704            this.helper[ 0 ].style.top = this.position.top + "px";
15705        }
15706
15707        //Do scrolling
15708        if ( o.scroll ) {
15709            if ( this._scroll( event ) !== false ) {
15710
15711                //Update item positions used in position checks
15712                this._refreshItemPositions( true );
15713
15714                if ( $.ui.ddmanager && !o.dropBehaviour ) {
15715                    $.ui.ddmanager.prepareOffsets( this, event );
15716                }
15717            }
15718        }
15719
15720        this.dragDirection = {
15721            vertical: this._getDragVerticalDirection(),
15722            horizontal: this._getDragHorizontalDirection()
15723        };
15724
15725        //Rearrange
15726        for ( i = this.items.length - 1; i >= 0; i-- ) {
15727
15728            //Cache variables and intersection, continue if no intersection
15729            item = this.items[ i ];
15730            itemElement = item.item[ 0 ];
15731            intersection = this._intersectsWithPointer( item );
15732            if ( !intersection ) {
15733                continue;
15734            }
15735
15736            // Only put the placeholder inside the current Container, skip all
15737            // items from other containers. This works because when moving
15738            // an item from one container to another the
15739            // currentContainer is switched before the placeholder is moved.
15740            //
15741            // Without this, moving items in "sub-sortables" can cause
15742            // the placeholder to jitter between the outer and inner container.
15743            if ( item.instance !== this.currentContainer ) {
15744                continue;
15745            }
15746
15747            // Cannot intersect with itself
15748            // no useless actions that have been done before
15749            // no action if the item moved is the parent of the item checked
15750            if ( itemElement !== this.currentItem[ 0 ] &&
15751                this.placeholder[ intersection === 1 ?
15752                "next" : "prev" ]()[ 0 ] !== itemElement &&
15753                !$.contains( this.placeholder[ 0 ], itemElement ) &&
15754                ( this.options.type === "semi-dynamic" ?
15755                    !$.contains( this.element[ 0 ], itemElement ) :
15756                    true
15757                )
15758            ) {
15759
15760                this.direction = intersection === 1 ? "down" : "up";
15761
15762                if ( this.options.tolerance === "pointer" ||
15763                        this._intersectsWithSides( item ) ) {
15764                    this._rearrange( event, item );
15765                } else {
15766                    break;
15767                }
15768
15769                this._trigger( "change", event, this._uiHash() );
15770                break;
15771            }
15772        }
15773
15774        //Post events to containers
15775        this._contactContainers( event );
15776
15777        //Interconnect with droppables
15778        if ( $.ui.ddmanager ) {
15779            $.ui.ddmanager.drag( this, event );
15780        }
15781
15782        //Call callbacks
15783        this._trigger( "sort", event, this._uiHash() );
15784
15785        this.lastPositionAbs = this.positionAbs;
15786        return false;
15787
15788    },
15789
15790    _mouseStop: function( event, noPropagation ) {
15791
15792        if ( !event ) {
15793            return;
15794        }
15795
15796        //If we are using droppables, inform the manager about the drop
15797        if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
15798            $.ui.ddmanager.drop( this, event );
15799        }
15800
15801        if ( this.options.revert ) {
15802            var that = this,
15803                cur = this.placeholder.offset(),
15804                axis = this.options.axis,
15805                animation = {};
15806
15807            if ( !axis || axis === "x" ) {
15808                animation.left = cur.left - this.offset.parent.left - this.margins.left +
15809                    ( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15810                        0 :
15811                        this.offsetParent[ 0 ].scrollLeft
15812                    );
15813            }
15814            if ( !axis || axis === "y" ) {
15815                animation.top = cur.top - this.offset.parent.top - this.margins.top +
15816                    ( this.offsetParent[ 0 ] === this.document[ 0 ].body ?
15817                        0 :
15818                        this.offsetParent[ 0 ].scrollTop
15819                    );
15820            }
15821            this.reverting = true;
15822            $( this.helper ).animate(
15823                animation,
15824                parseInt( this.options.revert, 10 ) || 500,
15825                function() {
15826                    that._clear( event );
15827                }
15828            );
15829        } else {
15830            this._clear( event, noPropagation );
15831        }
15832
15833        return false;
15834
15835    },
15836
15837    cancel: function() {
15838
15839        if ( this.dragging ) {
15840
15841            this._mouseUp( new $.Event( "mouseup", { target: null } ) );
15842
15843            if ( this.options.helper === "original" ) {
15844                this.currentItem.css( this._storedCSS );
15845                this._removeClass( this.currentItem, "ui-sortable-helper" );
15846            } else {
15847                this.currentItem.show();
15848            }
15849
15850            //Post deactivating events to containers
15851            for ( var i = this.containers.length - 1; i >= 0; i-- ) {
15852                this.containers[ i ]._trigger( "deactivate", null, this._uiHash( this ) );
15853                if ( this.containers[ i ].containerCache.over ) {
15854                    this.containers[ i ]._trigger( "out", null, this._uiHash( this ) );
15855                    this.containers[ i ].containerCache.over = 0;
15856                }
15857            }
15858
15859        }
15860
15861        if ( this.placeholder ) {
15862
15863            //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
15864            // it unbinds ALL events from the original node!
15865            if ( this.placeholder[ 0 ].parentNode ) {
15866                this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
15867            }
15868            if ( this.options.helper !== "original" && this.helper &&
15869                    this.helper[ 0 ].parentNode ) {
15870                this.helper.remove();
15871            }
15872
15873            $.extend( this, {
15874                helper: null,
15875                dragging: false,
15876                reverting: false,
15877                _noFinalSort: null
15878            } );
15879
15880            if ( this.domPosition.prev ) {
15881                $( this.domPosition.prev ).after( this.currentItem );
15882            } else {
15883                $( this.domPosition.parent ).prepend( this.currentItem );
15884            }
15885        }
15886
15887        return this;
15888
15889    },
15890
15891    serialize: function( o ) {
15892
15893        var items = this._getItemsAsjQuery( o && o.connected ),
15894            str = [];
15895        o = o || {};
15896
15897        $( items ).each( function() {
15898            var res = ( $( o.item || this ).attr( o.attribute || "id" ) || "" )
15899                .match( o.expression || ( /(.+)[\-=_](.+)/ ) );
15900            if ( res ) {
15901                str.push(
15902                    ( o.key || res[ 1 ] + "[]" ) +
15903                    "=" + ( o.key && o.expression ? res[ 1 ] : res[ 2 ] ) );
15904            }
15905        } );
15906
15907        if ( !str.length && o.key ) {
15908            str.push( o.key + "=" );
15909        }
15910
15911        return str.join( "&" );
15912
15913    },
15914
15915    toArray: function( o ) {
15916
15917        var items = this._getItemsAsjQuery( o && o.connected ),
15918            ret = [];
15919
15920        o = o || {};
15921
15922        items.each( function() {
15923            ret.push( $( o.item || this ).attr( o.attribute || "id" ) || "" );
15924        } );
15925        return ret;
15926
15927    },
15928
15929    /* Be careful with the following core functions */
15930    _intersectsWith: function( item ) {
15931
15932        var x1 = this.positionAbs.left,
15933            x2 = x1 + this.helperProportions.width,
15934            y1 = this.positionAbs.top,
15935            y2 = y1 + this.helperProportions.height,
15936            l = item.left,
15937            r = l + item.width,
15938            t = item.top,
15939            b = t + item.height,
15940            dyClick = this.offset.click.top,
15941            dxClick = this.offset.click.left,
15942            isOverElementHeight = ( this.options.axis === "x" ) || ( ( y1 + dyClick ) > t &&
15943                ( y1 + dyClick ) < b ),
15944            isOverElementWidth = ( this.options.axis === "y" ) || ( ( x1 + dxClick ) > l &&
15945                ( x1 + dxClick ) < r ),
15946            isOverElement = isOverElementHeight && isOverElementWidth;
15947
15948        if ( this.options.tolerance === "pointer" ||
15949            this.options.forcePointerForContainers ||
15950            ( this.options.tolerance !== "pointer" &&
15951                this.helperProportions[ this.floating ? "width" : "height" ] >
15952                item[ this.floating ? "width" : "height" ] )
15953        ) {
15954            return isOverElement;
15955        } else {
15956
15957            return ( l < x1 + ( this.helperProportions.width / 2 ) && // Right Half
15958                x2 - ( this.helperProportions.width / 2 ) < r && // Left Half
15959                t < y1 + ( this.helperProportions.height / 2 ) && // Bottom Half
15960                y2 - ( this.helperProportions.height / 2 ) < b ); // Top Half
15961
15962        }
15963    },
15964
15965    _intersectsWithPointer: function( item ) {
15966        var verticalDirection, horizontalDirection,
15967            isOverElementHeight = ( this.options.axis === "x" ) ||
15968                this._isOverAxis(
15969                    this.positionAbs.top + this.offset.click.top, item.top, item.height ),
15970            isOverElementWidth = ( this.options.axis === "y" ) ||
15971                this._isOverAxis(
15972                    this.positionAbs.left + this.offset.click.left, item.left, item.width ),
15973            isOverElement = isOverElementHeight && isOverElementWidth;
15974
15975        if ( !isOverElement ) {
15976            return false;
15977        }
15978
15979        verticalDirection = this.dragDirection.vertical;
15980        horizontalDirection = this.dragDirection.horizontal;
15981
15982        return this.floating ?
15983            ( ( horizontalDirection === "right" || verticalDirection === "down" ) ? 2 : 1 ) :
15984            ( verticalDirection && ( verticalDirection === "down" ? 2 : 1 ) );
15985
15986    },
15987
15988    _intersectsWithSides: function( item ) {
15989
15990        var isOverBottomHalf = this._isOverAxis( this.positionAbs.top +
15991                this.offset.click.top, item.top + ( item.height / 2 ), item.height ),
15992            isOverRightHalf = this._isOverAxis( this.positionAbs.left +
15993                this.offset.click.left, item.left + ( item.width / 2 ), item.width ),
15994            verticalDirection = this.dragDirection.vertical,
15995            horizontalDirection = this.dragDirection.horizontal;
15996
15997        if ( this.floating && horizontalDirection ) {
15998            return ( ( horizontalDirection === "right" && isOverRightHalf ) ||
15999                ( horizontalDirection === "left" && !isOverRightHalf ) );
16000        } else {
16001            return verticalDirection && ( ( verticalDirection === "down" && isOverBottomHalf ) ||
16002                ( verticalDirection === "up" && !isOverBottomHalf ) );
16003        }
16004
16005    },
16006
16007    _getDragVerticalDirection: function() {
16008        var delta = this.positionAbs.top - this.lastPositionAbs.top;
16009        return delta !== 0 && ( delta > 0 ? "down" : "up" );
16010    },
16011
16012    _getDragHorizontalDirection: function() {
16013        var delta = this.positionAbs.left - this.lastPositionAbs.left;
16014        return delta !== 0 && ( delta > 0 ? "right" : "left" );
16015    },
16016
16017    refresh: function( event ) {
16018        this._refreshItems( event );
16019        this._setHandleClassName();
16020        this.refreshPositions();
16021        return this;
16022    },
16023
16024    _connectWith: function() {
16025        var options = this.options;
16026        return options.connectWith.constructor === String ?
16027            [ options.connectWith ] :
16028            options.connectWith;
16029    },
16030
16031    _getItemsAsjQuery: function( connected ) {
16032
16033        var i, j, cur, inst,
16034            items = [],
16035            queries = [],
16036            connectWith = this._connectWith();
16037
16038        if ( connectWith && connected ) {
16039            for ( i = connectWith.length - 1; i >= 0; i-- ) {
16040                cur = $( connectWith[ i ], this.document[ 0 ] );
16041                for ( j = cur.length - 1; j >= 0; j-- ) {
16042                    inst = $.data( cur[ j ], this.widgetFullName );
16043                    if ( inst && inst !== this && !inst.options.disabled ) {
16044                        queries.push( [ typeof inst.options.items === "function" ?
16045                            inst.options.items.call( inst.element ) :
16046                            $( inst.options.items, inst.element )
16047                                .not( ".ui-sortable-helper" )
16048                                .not( ".ui-sortable-placeholder" ), inst ] );
16049                    }
16050                }
16051            }
16052        }
16053
16054        queries.push( [ typeof this.options.items === "function" ?
16055            this.options.items
16056                .call( this.element, null, { options: this.options, item: this.currentItem } ) :
16057            $( this.options.items, this.element )
16058                .not( ".ui-sortable-helper" )
16059                .not( ".ui-sortable-placeholder" ), this ] );
16060
16061        function addItems() {
16062            items.push( this );
16063        }
16064        for ( i = queries.length - 1; i >= 0; i-- ) {
16065            queries[ i ][ 0 ].each( addItems );
16066        }
16067
16068        return $( items );
16069
16070    },
16071
16072    _removeCurrentsFromItems: function() {
16073
16074        var list = this.currentItem.find( ":data(" + this.widgetName + "-item)" );
16075
16076        this.items = $.grep( this.items, function( item ) {
16077            for ( var j = 0; j < list.length; j++ ) {
16078                if ( list[ j ] === item.item[ 0 ] ) {
16079                    return false;
16080                }
16081            }
16082            return true;
16083        } );
16084
16085    },
16086
16087    _refreshItems: function( event ) {
16088
16089        this.items = [];
16090        this.containers = [ this ];
16091
16092        var i, j, cur, inst, targetData, _queries, item, queriesLength,
16093            items = this.items,
16094            queries = [ [ typeof this.options.items === "function" ?
16095                this.options.items.call( this.element[ 0 ], event, { item: this.currentItem } ) :
16096                $( this.options.items, this.element ), this ] ],
16097            connectWith = this._connectWith();
16098
16099        //Shouldn't be run the first time through due to massive slow-down
16100        if ( connectWith && this.ready ) {
16101            for ( i = connectWith.length - 1; i >= 0; i-- ) {
16102                cur = $( connectWith[ i ], this.document[ 0 ] );
16103                for ( j = cur.length - 1; j >= 0; j-- ) {
16104                    inst = $.data( cur[ j ], this.widgetFullName );
16105                    if ( inst && inst !== this && !inst.options.disabled ) {
16106                        queries.push( [ typeof inst.options.items === "function" ?
16107                            inst.options.items
16108                                .call( inst.element[ 0 ], event, { item: this.currentItem } ) :
16109                            $( inst.options.items, inst.element ), inst ] );
16110                        this.containers.push( inst );
16111                    }
16112                }
16113            }
16114        }
16115
16116        for ( i = queries.length - 1; i >= 0; i-- ) {
16117            targetData = queries[ i ][ 1 ];
16118            _queries = queries[ i ][ 0 ];
16119
16120            for ( j = 0, queriesLength = _queries.length; j < queriesLength; j++ ) {
16121                item = $( _queries[ j ] );
16122
16123                // Data for target checking (mouse manager)
16124                item.data( this.widgetName + "-item", targetData );
16125
16126                items.push( {
16127                    item: item,
16128                    instance: targetData,
16129                    width: 0, height: 0,
16130                    left: 0, top: 0
16131                } );
16132            }
16133        }
16134
16135    },
16136
16137    _refreshItemPositions: function( fast ) {
16138        var i, item, t, p;
16139
16140        for ( i = this.items.length - 1; i >= 0; i-- ) {
16141            item = this.items[ i ];
16142
16143            //We ignore calculating positions of all connected containers when we're not over them
16144            if ( this.currentContainer && item.instance !== this.currentContainer &&
16145                    item.item[ 0 ] !== this.currentItem[ 0 ] ) {
16146                continue;
16147            }
16148
16149            t = this.options.toleranceElement ?
16150                $( this.options.toleranceElement, item.item ) :
16151                item.item;
16152
16153            if ( !fast ) {
16154                item.width = t.outerWidth();
16155                item.height = t.outerHeight();
16156            }
16157
16158            p = t.offset();
16159            item.left = p.left;
16160            item.top = p.top;
16161        }
16162    },
16163
16164    refreshPositions: function( fast ) {
16165
16166        // Determine whether items are being displayed horizontally
16167        this.floating = this.items.length ?
16168            this.options.axis === "x" || this._isFloating( this.items[ 0 ].item ) :
16169            false;
16170
16171        // This has to be redone because due to the item being moved out/into the offsetParent,
16172        // the offsetParent's position will change
16173        if ( this.offsetParent && this.helper ) {
16174            this.offset.parent = this._getParentOffset();
16175        }
16176
16177        this._refreshItemPositions( fast );
16178
16179        var i, p;
16180
16181        if ( this.options.custom && this.options.custom.refreshContainers ) {
16182            this.options.custom.refreshContainers.call( this );
16183        } else {
16184            for ( i = this.containers.length - 1; i >= 0; i-- ) {
16185                p = this.containers[ i ].element.offset();
16186                this.containers[ i ].containerCache.left = p.left;
16187                this.containers[ i ].containerCache.top = p.top;
16188                this.containers[ i ].containerCache.width =
16189                    this.containers[ i ].element.outerWidth();
16190                this.containers[ i ].containerCache.height =
16191                    this.containers[ i ].element.outerHeight();
16192            }
16193        }
16194
16195        return this;
16196    },
16197
16198    _createPlaceholder: function( that ) {
16199        that = that || this;
16200        var className, nodeName,
16201            o = that.options;
16202
16203        if ( !o.placeholder || o.placeholder.constructor === String ) {
16204            className = o.placeholder;
16205            nodeName = that.currentItem[ 0 ].nodeName.toLowerCase();
16206            o.placeholder = {
16207                element: function() {
16208
16209                    var element = $( "<" + nodeName + ">", that.document[ 0 ] );
16210
16211                    that._addClass( element, "ui-sortable-placeholder",
16212                            className || that.currentItem[ 0 ].className )
16213                        ._removeClass( element, "ui-sortable-helper" );
16214
16215                    if ( nodeName === "tbody" ) {
16216                        that._createTrPlaceholder(
16217                            that.currentItem.find( "tr" ).eq( 0 ),
16218                            $( "<tr>", that.document[ 0 ] ).appendTo( element )
16219                        );
16220                    } else if ( nodeName === "tr" ) {
16221                        that._createTrPlaceholder( that.currentItem, element );
16222                    } else if ( nodeName === "img" ) {
16223                        element.attr( "src", that.currentItem.attr( "src" ) );
16224                    }
16225
16226                    if ( !className ) {
16227                        element.css( "visibility", "hidden" );
16228                    }
16229
16230                    return element;
16231                },
16232                update: function( container, p ) {
16233
16234                    // 1. If a className is set as 'placeholder option, we don't force sizes -
16235                    // the class is responsible for that
16236                    // 2. The option 'forcePlaceholderSize can be enabled to force it even if a
16237                    // class name is specified
16238                    if ( className && !o.forcePlaceholderSize ) {
16239                        return;
16240                    }
16241
16242                    // If the element doesn't have a actual height or width by itself (without
16243                    // styles coming from a stylesheet), it receives the inline height and width
16244                    // from the dragged item. Or, if it's a tbody or tr, it's going to have a height
16245                    // anyway since we're populating them with <td>s above, but they're unlikely to
16246                    // be the correct height on their own if the row heights are dynamic, so we'll
16247                    // always assign the height of the dragged item given forcePlaceholderSize
16248                    // is true.
16249                    if ( !p.height() || ( o.forcePlaceholderSize &&
16250                            ( nodeName === "tbody" || nodeName === "tr" ) ) ) {
16251                        p.height(
vendor: 39,394 bytes, lines 16252-17334
16252                            that.currentItem.innerHeight() -
16253                            parseInt( that.currentItem.css( "paddingTop" ) || 0, 10 ) -
16254                            parseInt( that.currentItem.css( "paddingBottom" ) || 0, 10 ) );
16255                    }
16256                    if ( !p.width() ) {
16257                        p.width(
16258                            that.currentItem.innerWidth() -
16259                            parseInt( that.currentItem.css( "paddingLeft" ) || 0, 10 ) -
16260                            parseInt( that.currentItem.css( "paddingRight" ) || 0, 10 ) );
16261                    }
16262                }
16263            };
16264        }
16265
16266        //Create the placeholder
16267        that.placeholder = $( o.placeholder.element.call( that.element, that.currentItem ) );
16268
16269        //Append it after the actual current item
16270        that.currentItem.after( that.placeholder );
16271
16272        //Update the size of the placeholder (TODO: Logic to fuzzy, see line 316/317)
16273        o.placeholder.update( that, that.placeholder );
16274
16275    },
16276
16277    _createTrPlaceholder: function( sourceTr, targetTr ) {
16278        var that = this;
16279
16280        sourceTr.children().each( function() {
16281            $( "<td>&#160;</td>", that.document[ 0 ] )
16282                .attr( "colspan", $( this ).attr( "colspan" ) || 1 )
16283                .appendTo( targetTr );
16284        } );
16285    },
16286
16287    _contactContainers: function( event ) {
16288        var i, j, dist, itemWithLeastDistance, posProperty, sizeProperty, cur, nearBottom,
16289            floating, axis,
16290            innermostContainer = null,
16291            innermostIndex = null;
16292
16293        // Get innermost container that intersects with item
16294        for ( i = this.containers.length - 1; i >= 0; i-- ) {
16295
16296            // Never consider a container that's located within the item itself
16297            if ( $.contains( this.currentItem[ 0 ], this.containers[ i ].element[ 0 ] ) ) {
16298                continue;
16299            }
16300
16301            if ( this._intersectsWith( this.containers[ i ].containerCache ) ) {
16302
16303                // If we've already found a container and it's more "inner" than this, then continue
16304                if ( innermostContainer &&
16305                        $.contains(
16306                            this.containers[ i ].element[ 0 ],
16307                            innermostContainer.element[ 0 ] ) ) {
16308                    continue;
16309                }
16310
16311                innermostContainer = this.containers[ i ];
16312                innermostIndex = i;
16313
16314            } else {
16315
16316                // container doesn't intersect. trigger "out" event if necessary
16317                if ( this.containers[ i ].containerCache.over ) {
16318                    this.containers[ i ]._trigger( "out", event, this._uiHash( this ) );
16319                    this.containers[ i ].containerCache.over = 0;
16320                }
16321            }
16322
16323        }
16324
16325        // If no intersecting containers found, return
16326        if ( !innermostContainer ) {
16327            return;
16328        }
16329
16330        // Move the item into the container if it's not there already
16331        if ( this.containers.length === 1 ) {
16332            if ( !this.containers[ innermostIndex ].containerCache.over ) {
16333                this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16334                this.containers[ innermostIndex ].containerCache.over = 1;
16335            }
16336        } else {
16337
16338            // When entering a new container, we will find the item with the least distance and
16339            // append our item near it
16340            dist = 10000;
16341            itemWithLeastDistance = null;
16342            floating = innermostContainer.floating || this._isFloating( this.currentItem );
16343            posProperty = floating ? "left" : "top";
16344            sizeProperty = floating ? "width" : "height";
16345            axis = floating ? "pageX" : "pageY";
16346
16347            for ( j = this.items.length - 1; j >= 0; j-- ) {
16348                if ( !$.contains(
16349                        this.containers[ innermostIndex ].element[ 0 ], this.items[ j ].item[ 0 ] )
16350                ) {
16351                    continue;
16352                }
16353                if ( this.items[ j ].item[ 0 ] === this.currentItem[ 0 ] ) {
16354                    continue;
16355                }
16356
16357                cur = this.items[ j ].item.offset()[ posProperty ];
16358                nearBottom = false;
16359                if ( event[ axis ] - cur > this.items[ j ][ sizeProperty ] / 2 ) {
16360                    nearBottom = true;
16361                }
16362
16363                if ( Math.abs( event[ axis ] - cur ) < dist ) {
16364                    dist = Math.abs( event[ axis ] - cur );
16365                    itemWithLeastDistance = this.items[ j ];
16366                    this.direction = nearBottom ? "up" : "down";
16367                }
16368            }
16369
16370            //Check if dropOnEmpty is enabled
16371            if ( !itemWithLeastDistance && !this.options.dropOnEmpty ) {
16372                return;
16373            }
16374
16375            if ( this.currentContainer === this.containers[ innermostIndex ] ) {
16376                if ( !this.currentContainer.containerCache.over ) {
16377                    this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash() );
16378                    this.currentContainer.containerCache.over = 1;
16379                }
16380                return;
16381            }
16382
16383            if ( itemWithLeastDistance ) {
16384                this._rearrange( event, itemWithLeastDistance, null, true );
16385            } else {
16386                this._rearrange( event, null, this.containers[ innermostIndex ].element, true );
16387            }
16388            this._trigger( "change", event, this._uiHash() );
16389            this.containers[ innermostIndex ]._trigger( "change", event, this._uiHash( this ) );
16390            this.currentContainer = this.containers[ innermostIndex ];
16391
16392            //Update the placeholder
16393            this.options.placeholder.update( this.currentContainer, this.placeholder );
16394
16395            //Update scrollParent
16396            this.scrollParent = this.placeholder.scrollParent();
16397
16398            //Update overflowOffset
16399            if ( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16400                    this.scrollParent[ 0 ].tagName !== "HTML" ) {
16401                this.overflowOffset = this.scrollParent.offset();
16402            }
16403
16404            this.containers[ innermostIndex ]._trigger( "over", event, this._uiHash( this ) );
16405            this.containers[ innermostIndex ].containerCache.over = 1;
16406        }
16407
16408    },
16409
16410    _createHelper: function( event ) {
16411
16412        var o = this.options,
16413            helper = typeof o.helper === "function" ?
16414                $( o.helper.apply( this.element[ 0 ], [ event, this.currentItem ] ) ) :
16415                ( o.helper === "clone" ? this.currentItem.clone() : this.currentItem );
16416
16417        //Add the helper to the DOM if that didn't happen already
16418        if ( !helper.parents( "body" ).length ) {
16419            this.appendTo[ 0 ].appendChild( helper[ 0 ] );
16420        }
16421
16422        if ( helper[ 0 ] === this.currentItem[ 0 ] ) {
16423            this._storedCSS = {
16424                width: this.currentItem[ 0 ].style.width,
16425                height: this.currentItem[ 0 ].style.height,
16426                position: this.currentItem.css( "position" ),
16427                top: this.currentItem.css( "top" ),
16428                left: this.currentItem.css( "left" )
16429            };
16430        }
16431
16432        if ( !helper[ 0 ].style.width || o.forceHelperSize ) {
16433            helper.width( this.currentItem.width() );
16434        }
16435        if ( !helper[ 0 ].style.height || o.forceHelperSize ) {
16436            helper.height( this.currentItem.height() );
16437        }
16438
16439        return helper;
16440
16441    },
16442
16443    _adjustOffsetFromHelper: function( obj ) {
16444        if ( typeof obj === "string" ) {
16445            obj = obj.split( " " );
16446        }
16447        if ( Array.isArray( obj ) ) {
16448            obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
16449        }
16450        if ( "left" in obj ) {
16451            this.offset.click.left = obj.left + this.margins.left;
16452        }
16453        if ( "right" in obj ) {
16454            this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
16455        }
16456        if ( "top" in obj ) {
16457            this.offset.click.top = obj.top + this.margins.top;
16458        }
16459        if ( "bottom" in obj ) {
16460            this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
16461        }
16462    },
16463
16464    _getParentOffset: function() {
16465
16466        //Get the offsetParent and cache its position
16467        this.offsetParent = this.helper.offsetParent();
16468        var po = this.offsetParent.offset();
16469
16470        // This is a special case where we need to modify a offset calculated on start, since the
16471        // following happened:
16472        // 1. The position of the helper is absolute, so it's position is calculated based on the
16473        // next positioned parent
16474        // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
16475        // the document, which means that the scroll is included in the initial calculation of the
16476        // offset of the parent, and never recalculated upon drag
16477        if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16478                $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
16479            po.left += this.scrollParent.scrollLeft();
16480            po.top += this.scrollParent.scrollTop();
16481        }
16482
16483        // This needs to be actually done for all browsers, since pageX/pageY includes
16484        // this information.
16485        if ( this.offsetParent[ 0 ] === this.document[ 0 ].body ) {
16486            po = { top: 0, left: 0 };
16487        }
16488
16489        return {
16490            top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
16491            left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
16492        };
16493
16494    },
16495
16496    _getRelativeOffset: function() {
16497
16498        if ( this.cssPosition === "relative" ) {
16499            var p = this.currentItem.position();
16500            return {
16501                top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
16502                    this.scrollParent.scrollTop(),
16503                left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
16504                    this.scrollParent.scrollLeft()
16505            };
16506        } else {
16507            return { top: 0, left: 0 };
16508        }
16509
16510    },
16511
16512    _cacheMargins: function() {
16513        this.margins = {
16514            left: ( parseInt( this.currentItem.css( "marginLeft" ), 10 ) || 0 ),
16515            top: ( parseInt( this.currentItem.css( "marginTop" ), 10 ) || 0 )
16516        };
16517    },
16518
16519    _cacheHelperProportions: function() {
16520        this.helperProportions = {
16521            width: this.helper.outerWidth(),
16522            height: this.helper.outerHeight()
16523        };
16524    },
16525
16526    _setContainment: function() {
16527
16528        var ce, co, over,
16529            o = this.options;
16530        if ( o.containment === "parent" ) {
16531            o.containment = this.helper[ 0 ].parentNode;
16532        }
16533        if ( o.containment === "document" || o.containment === "window" ) {
16534            this.containment = [
16535                0 - this.offset.relative.left - this.offset.parent.left,
16536                0 - this.offset.relative.top - this.offset.parent.top,
16537                o.containment === "document" ?
16538                    this.document.width() :
16539                    this.window.width() - this.helperProportions.width - this.margins.left,
16540                ( o.containment === "document" ?
16541                    ( this.document.height() || document.body.parentNode.scrollHeight ) :
16542                    this.window.height() || this.document[ 0 ].body.parentNode.scrollHeight
16543                ) - this.helperProportions.height - this.margins.top
16544            ];
16545        }
16546
16547        if ( !( /^(document|window|parent)$/ ).test( o.containment ) ) {
16548            ce = $( o.containment )[ 0 ];
16549            co = $( o.containment ).offset();
16550            over = ( $( ce ).css( "overflow" ) !== "hidden" );
16551
16552            this.containment = [
16553                co.left + ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) +
16554                    ( parseInt( $( ce ).css( "paddingLeft" ), 10 ) || 0 ) - this.margins.left,
16555                co.top + ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) +
16556                    ( parseInt( $( ce ).css( "paddingTop" ), 10 ) || 0 ) - this.margins.top,
16557                co.left + ( over ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
16558                    ( parseInt( $( ce ).css( "borderLeftWidth" ), 10 ) || 0 ) -
16559                    ( parseInt( $( ce ).css( "paddingRight" ), 10 ) || 0 ) -
16560                    this.helperProportions.width - this.margins.left,
16561                co.top + ( over ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
16562                    ( parseInt( $( ce ).css( "borderTopWidth" ), 10 ) || 0 ) -
16563                    ( parseInt( $( ce ).css( "paddingBottom" ), 10 ) || 0 ) -
16564                    this.helperProportions.height - this.margins.top
16565            ];
16566        }
16567
16568    },
16569
16570    _convertPositionTo: function( d, pos ) {
16571
16572        if ( !pos ) {
16573            pos = this.position;
16574        }
16575        var mod = d === "absolute" ? 1 : -1,
16576            scroll = this.cssPosition === "absolute" &&
16577                !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16578                $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16579                    this.offsetParent :
16580                    this.scrollParent,
16581            scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16582
16583        return {
16584            top: (
16585
16586                // The absolute mouse position
16587                pos.top +
16588
16589                // Only for relative positioned nodes: Relative offset from element to offset parent
16590                this.offset.relative.top * mod +
16591
16592                // The offsetParent's offset without borders (offset + border)
16593                this.offset.parent.top * mod -
16594                ( ( this.cssPosition === "fixed" ?
16595                    -this.scrollParent.scrollTop() :
16596                    ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) * mod )
16597            ),
16598            left: (
16599
16600                // The absolute mouse position
16601                pos.left +
16602
16603                // Only for relative positioned nodes: Relative offset from element to offset parent
16604                this.offset.relative.left * mod +
16605
16606                // The offsetParent's offset without borders (offset + border)
16607                this.offset.parent.left * mod   -
16608                ( ( this.cssPosition === "fixed" ?
16609                    -this.scrollParent.scrollLeft() : scrollIsRootNode ? 0 :
16610                    scroll.scrollLeft() ) * mod )
16611            )
16612        };
16613
16614    },
16615
16616    _generatePosition: function( event ) {
16617
16618        var top, left,
16619            o = this.options,
16620            pageX = event.pageX,
16621            pageY = event.pageY,
16622            scroll = this.cssPosition === "absolute" &&
16623                !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16624                $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) ?
16625                    this.offsetParent :
16626                    this.scrollParent,
16627                scrollIsRootNode = ( /(html|body)/i ).test( scroll[ 0 ].tagName );
16628
16629        // This is another very weird special case that only happens for relative elements:
16630        // 1. If the css position is relative
16631        // 2. and the scroll parent is the document or similar to the offset parent
16632        // we have to refresh the relative offset during the scroll so there are no jumps
16633        if ( this.cssPosition === "relative" && !( this.scrollParent[ 0 ] !== this.document[ 0 ] &&
16634                this.scrollParent[ 0 ] !== this.offsetParent[ 0 ] ) ) {
16635            this.offset.relative = this._getRelativeOffset();
16636        }
16637
16638        /*
16639         * - Position constraining -
16640         * Constrain the position to a mix of grid, containment.
16641         */
16642
16643        if ( this.originalPosition ) { //If we are not dragging yet, we won't check for options
16644
16645            if ( this.containment ) {
16646                if ( event.pageX - this.offset.click.left < this.containment[ 0 ] ) {
16647                    pageX = this.containment[ 0 ] + this.offset.click.left;
16648                }
16649                if ( event.pageY - this.offset.click.top < this.containment[ 1 ] ) {
16650                    pageY = this.containment[ 1 ] + this.offset.click.top;
16651                }
16652                if ( event.pageX - this.offset.click.left > this.containment[ 2 ] ) {
16653                    pageX = this.containment[ 2 ] + this.offset.click.left;
16654                }
16655                if ( event.pageY - this.offset.click.top > this.containment[ 3 ] ) {
16656                    pageY = this.containment[ 3 ] + this.offset.click.top;
16657                }
16658            }
16659
16660            if ( o.grid ) {
16661                top = this.originalPageY + Math.round( ( pageY - this.originalPageY ) /
16662                    o.grid[ 1 ] ) * o.grid[ 1 ];
16663                pageY = this.containment ?
16664                    ( ( top - this.offset.click.top >= this.containment[ 1 ] &&
16665                        top - this.offset.click.top <= this.containment[ 3 ] ) ?
16666                            top :
16667                            ( ( top - this.offset.click.top >= this.containment[ 1 ] ) ?
16668                                top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) :
16669                                top;
16670
16671                left = this.originalPageX + Math.round( ( pageX - this.originalPageX ) /
16672                    o.grid[ 0 ] ) * o.grid[ 0 ];
16673                pageX = this.containment ?
16674                    ( ( left - this.offset.click.left >= this.containment[ 0 ] &&
16675                        left - this.offset.click.left <= this.containment[ 2 ] ) ?
16676                            left :
16677                            ( ( left - this.offset.click.left >= this.containment[ 0 ] ) ?
16678                                left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) :
16679                                left;
16680            }
16681
16682        }
16683
16684        return {
16685            top: (
16686
16687                // The absolute mouse position
16688                pageY -
16689
16690                // Click offset (relative to the element)
16691                this.offset.click.top -
16692
16693                // Only for relative positioned nodes: Relative offset from element to offset parent
16694                this.offset.relative.top -
16695
16696                // The offsetParent's offset without borders (offset + border)
16697                this.offset.parent.top +
16698                ( ( this.cssPosition === "fixed" ?
16699                    -this.scrollParent.scrollTop() :
16700                    ( scrollIsRootNode ? 0 : scroll.scrollTop() ) ) )
16701            ),
16702            left: (
16703
16704                // The absolute mouse position
16705                pageX -
16706
16707                // Click offset (relative to the element)
16708                this.offset.click.left -
16709
16710                // Only for relative positioned nodes: Relative offset from element to offset parent
16711                this.offset.relative.left -
16712
16713                // The offsetParent's offset without borders (offset + border)
16714                this.offset.parent.left +
16715                ( ( this.cssPosition === "fixed" ?
16716                    -this.scrollParent.scrollLeft() :
16717                    scrollIsRootNode ? 0 : scroll.scrollLeft() ) )
16718            )
16719        };
16720
16721    },
16722
16723    _rearrange: function( event, i, a, hardRefresh ) {
16724
16725        if ( a ) {
16726            a[ 0 ].appendChild( this.placeholder[ 0 ] );
16727        } else {
16728            i.item[ 0 ].parentNode.insertBefore( this.placeholder[ 0 ],
16729                ( this.direction === "down" ? i.item[ 0 ] : i.item[ 0 ].nextSibling ) );
16730        }
16731
16732        //Various things done here to improve the performance:
16733        // 1. we create a setTimeout, that calls refreshPositions
16734        // 2. on the instance, we have a counter variable, that get's higher after every append
16735        // 3. on the local scope, we copy the counter variable, and check in the timeout,
16736        // if it's still the same
16737        // 4. this lets only the last addition to the timeout stack through
16738        this.counter = this.counter ? ++this.counter : 1;
16739        var counter = this.counter;
16740
16741        this._delay( function() {
16742            if ( counter === this.counter ) {
16743
16744                //Precompute after each DOM insertion, NOT on mousemove
16745                this.refreshPositions( !hardRefresh );
16746            }
16747        } );
16748
16749    },
16750
16751    _clear: function( event, noPropagation ) {
16752
16753        this.reverting = false;
16754
16755        // We delay all events that have to be triggered to after the point where the placeholder
16756        // has been removed and everything else normalized again
16757        var i,
16758            delayedTriggers = [];
16759
16760        // We first have to update the dom position of the actual currentItem
16761        // Note: don't do it if the current item is already removed (by a user), or it gets
16762        // reappended (see #4088)
16763        if ( !this._noFinalSort && this.currentItem.parent().length ) {
16764            this.placeholder.before( this.currentItem );
16765        }
16766        this._noFinalSort = null;
16767
16768        if ( this.helper[ 0 ] === this.currentItem[ 0 ] ) {
16769            for ( i in this._storedCSS ) {
16770                if ( this._storedCSS[ i ] === "auto" || this._storedCSS[ i ] === "static" ) {
16771                    this._storedCSS[ i ] = "";
16772                }
16773            }
16774            this.currentItem.css( this._storedCSS );
16775            this._removeClass( this.currentItem, "ui-sortable-helper" );
16776        } else {
16777            this.currentItem.show();
16778        }
16779
16780        if ( this.fromOutside && !noPropagation ) {
16781            delayedTriggers.push( function( event ) {
16782                this._trigger( "receive", event, this._uiHash( this.fromOutside ) );
16783            } );
16784        }
16785        if ( ( this.fromOutside ||
16786                this.domPosition.prev !==
16787                this.currentItem.prev().not( ".ui-sortable-helper" )[ 0 ] ||
16788                this.domPosition.parent !== this.currentItem.parent()[ 0 ] ) && !noPropagation ) {
16789
16790            // Trigger update callback if the DOM position has changed
16791            delayedTriggers.push( function( event ) {
16792                this._trigger( "update", event, this._uiHash() );
16793            } );
16794        }
16795
16796        // Check if the items Container has Changed and trigger appropriate
16797        // events.
16798        if ( this !== this.currentContainer ) {
16799            if ( !noPropagation ) {
16800                delayedTriggers.push( function( event ) {
16801                    this._trigger( "remove", event, this._uiHash() );
16802                } );
16803                delayedTriggers.push( ( function( c ) {
16804                    return function( event ) {
16805                        c._trigger( "receive", event, this._uiHash( this ) );
16806                    };
16807                } ).call( this, this.currentContainer ) );
16808                delayedTriggers.push( ( function( c ) {
16809                    return function( event ) {
16810                        c._trigger( "update", event, this._uiHash( this ) );
16811                    };
16812                } ).call( this, this.currentContainer ) );
16813            }
16814        }
16815
16816        //Post events to containers
16817        function delayEvent( type, instance, container ) {
16818            return function( event ) {
16819                container._trigger( type, event, instance._uiHash( instance ) );
16820            };
16821        }
16822        for ( i = this.containers.length - 1; i >= 0; i-- ) {
16823            if ( !noPropagation ) {
16824                delayedTriggers.push( delayEvent( "deactivate", this, this.containers[ i ] ) );
16825            }
16826            if ( this.containers[ i ].containerCache.over ) {
16827                delayedTriggers.push( delayEvent( "out", this, this.containers[ i ] ) );
16828                this.containers[ i ].containerCache.over = 0;
16829            }
16830        }
16831
16832        //Do what was originally in plugins
16833        if ( this._storedStylesheet ) {
16834            this._storedStylesheet.remove();
16835            this._storedStylesheet = null;
16836        }
16837        if ( this._storedOpacity ) {
16838            this.helper.css( "opacity", this._storedOpacity );
16839        }
16840        if ( this._storedZIndex ) {
16841            this.helper.css( "zIndex", this._storedZIndex === "auto" ? "" : this._storedZIndex );
16842        }
16843
16844        this.dragging = false;
16845
16846        if ( !noPropagation ) {
16847            this._trigger( "beforeStop", event, this._uiHash() );
16848        }
16849
16850        //$(this.placeholder[0]).remove(); would have been the jQuery way - unfortunately,
16851        // it unbinds ALL events from the original node!
16852        this.placeholder[ 0 ].parentNode.removeChild( this.placeholder[ 0 ] );
16853
16854        if ( !this.cancelHelperRemoval ) {
16855            if ( this.helper[ 0 ] !== this.currentItem[ 0 ] ) {
16856                this.helper.remove();
16857            }
16858            this.helper = null;
16859        }
16860
16861        if ( !noPropagation ) {
16862            for ( i = 0; i < delayedTriggers.length; i++ ) {
16863
16864                // Trigger all delayed events
16865                delayedTriggers[ i ].call( this, event );
16866            }
16867            this._trigger( "stop", event, this._uiHash() );
16868        }
16869
16870        this.fromOutside = false;
16871        return !this.cancelHelperRemoval;
16872
16873    },
16874
16875    _trigger: function() {
16876        if ( $.Widget.prototype._trigger.apply( this, arguments ) === false ) {
16877            this.cancel();
16878        }
16879    },
16880
16881    _uiHash: function( _inst ) {
16882        var inst = _inst || this;
16883        return {
16884            helper: inst.helper,
16885            placeholder: inst.placeholder || $( [] ),
16886            position: inst.position,
16887            originalPosition: inst.originalPosition,
16888            offset: inst.positionAbs,
16889            item: inst.currentItem,
16890            sender: _inst ? _inst.element : null
16891        };
16892    }
16893
16894} );
16895
16896
16897/*!
16898 * jQuery UI Spinner 1.14.1
16899 * https://jqueryui.com
16900 *
16901 * Copyright OpenJS Foundation and other contributors
16902 * Released under the MIT license.
16903 * https://jquery.org/license
16904 */
16905
16906//>>label: Spinner
16907//>>group: Widgets
16908//>>description: Displays buttons to easily input numbers via the keyboard or mouse.
16909//>>docs: https://api.jqueryui.com/spinner/
16910//>>demos: https://jqueryui.com/spinner/
16911//>>css.structure: ../../themes/base/core.css
16912//>>css.structure: ../../themes/base/spinner.css
16913//>>css.theme: ../../themes/base/theme.css
16914
16915
16916function spinnerModifier( fn ) {
16917    return function() {
16918        var previous = this.element.val();
16919        fn.apply( this, arguments );
16920        this._refresh();
16921        if ( previous !== this.element.val() ) {
16922            this._trigger( "change" );
16923        }
16924    };
16925}
16926
16927$.widget( "ui.spinner", {
16928    version: "1.14.1",
16929    defaultElement: "<input>",
16930    widgetEventPrefix: "spin",
16931    options: {
16932        classes: {
16933            "ui-spinner": "ui-corner-all",
16934            "ui-spinner-down": "ui-corner-br",
16935            "ui-spinner-up": "ui-corner-tr"
16936        },
16937        culture: null,
16938        icons: {
16939            down: "ui-icon-triangle-1-s",
16940            up: "ui-icon-triangle-1-n"
16941        },
16942        incremental: true,
16943        max: null,
16944        min: null,
16945        numberFormat: null,
16946        page: 10,
16947        step: 1,
16948
16949        change: null,
16950        spin: null,
16951        start: null,
16952        stop: null
16953    },
16954
16955    _create: function() {
16956
16957        // handle string values that need to be parsed
16958        this._setOption( "max", this.options.max );
16959        this._setOption( "min", this.options.min );
16960        this._setOption( "step", this.options.step );
16961
16962        // Only format if there is a value, prevents the field from being marked
16963        // as invalid in Firefox, see #9573.
16964        if ( this.value() !== "" ) {
16965
16966            // Format the value, but don't constrain.
16967            this._value( this.element.val(), true );
16968        }
16969
16970        this._draw();
16971        this._on( this._events );
16972        this._refresh();
16973
16974        // Turning off autocomplete prevents the browser from remembering the
16975        // value when navigating through history, so we re-enable autocomplete
16976        // if the page is unloaded before the widget is destroyed. #7790
16977        this._on( this.window, {
16978            beforeunload: function() {
16979                this.element.removeAttr( "autocomplete" );
16980            }
16981        } );
16982    },
16983
16984    _getCreateOptions: function() {
16985        var options = this._super();
16986        var element = this.element;
16987
16988        $.each( [ "min", "max", "step" ], function( i, option ) {
16989            var value = element.attr( option );
16990            if ( value != null && value.length ) {
16991                options[ option ] = value;
16992            }
16993        } );
16994
16995        return options;
16996    },
16997
16998    _events: {
16999        keydown: function( event ) {
17000            if ( this._start( event ) && this._keydown( event ) ) {
17001                event.preventDefault();
17002            }
17003        },
17004        keyup: "_stop",
17005        focus: function() {
17006            this.previous = this.element.val();
17007        },
17008        blur: function( event ) {
17009            this._stop();
17010            this._refresh();
17011            if ( this.previous !== this.element.val() ) {
17012                this._trigger( "change", event );
17013            }
17014        },
17015        mousewheel: function( event, delta ) {
17016            var activeElement = this.document[ 0 ].activeElement;
17017            var isActive = this.element[ 0 ] === activeElement;
17018
17019            if ( !isActive || !delta ) {
17020                return;
17021            }
17022
17023            if ( !this.spinning && !this._start( event ) ) {
17024                return false;
17025            }
17026
17027            this._spin( ( delta > 0 ? 1 : -1 ) * this.options.step, event );
17028            clearTimeout( this.mousewheelTimer );
17029            this.mousewheelTimer = this._delay( function() {
17030                if ( this.spinning ) {
17031                    this._stop( event );
17032                }
17033            }, 100 );
17034            event.preventDefault();
17035        },
17036        "mousedown .ui-spinner-button": function( event ) {
17037            var previous;
17038
17039            // We never want the buttons to have focus; whenever the user is
17040            // interacting with the spinner, the focus should be on the input.
17041            // If the input is focused then this.previous is properly set from
17042            // when the input first received focus. If the input is not focused
17043            // then we need to set this.previous based on the value before spinning.
17044            previous = this.element[ 0 ] === this.document[ 0 ].activeElement ?
17045                this.previous : this.element.val();
17046            function checkFocus() {
17047                var isActive = this.element[ 0 ] === this.document[ 0 ].activeElement;
17048                if ( !isActive ) {
17049                    this.element.trigger( "focus" );
17050                    this.previous = previous;
17051                }
17052            }
17053
17054            // Ensure focus is on (or stays on) the text field
17055            event.preventDefault();
17056            checkFocus.call( this );
17057
17058            if ( this._start( event ) === false ) {
17059                return;
17060            }
17061
17062            this._repeat( null, $( event.currentTarget )
17063                .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17064        },
17065        "mouseup .ui-spinner-button": "_stop",
17066        "mouseenter .ui-spinner-button": function( event ) {
17067
17068            // button will add ui-state-active if mouse was down while mouseleave and kept down
17069            if ( !$( event.currentTarget ).hasClass( "ui-state-active" ) ) {
17070                return;
17071            }
17072
17073            if ( this._start( event ) === false ) {
17074                return false;
17075            }
17076            this._repeat( null, $( event.currentTarget )
17077                .hasClass( "ui-spinner-up" ) ? 1 : -1, event );
17078        },
17079
17080        // TODO: do we really want to consider this a stop?
17081        // shouldn't we just stop the repeater and wait until mouseup before
17082        // we trigger the stop event?
17083        "mouseleave .ui-spinner-button": "_stop"
17084    },
17085
17086    // Support mobile enhanced option and make backcompat more sane
17087    _enhance: function() {
17088        this.uiSpinner = this.element
17089            .attr( "autocomplete", "off" )
17090            .wrap( "<span>" )
17091            .parent()
17092
17093                // Add buttons
17094                .append(
17095                    "<a></a><a></a>"
17096                );
17097    },
17098
17099    _draw: function() {
17100        this._enhance();
17101
17102        this._addClass( this.uiSpinner, "ui-spinner", "ui-widget ui-widget-content" );
17103        this._addClass( "ui-spinner-input" );
17104
17105        this.element.attr( "role", "spinbutton" );
17106
17107        // Button bindings
17108        this.buttons = this.uiSpinner.children( "a" )
17109            .attr( "tabIndex", -1 )
17110            .attr( "aria-hidden", true )
17111            .button( {
17112                classes: {
17113                    "ui-button": ""
17114                }
17115            } );
17116
17117        // TODO: Right now button does not support classes this is already updated in button PR
17118        this._removeClass( this.buttons, "ui-corner-all" );
17119
17120        this._addClass( this.buttons.first(), "ui-spinner-button ui-spinner-up" );
17121        this._addClass( this.buttons.last(), "ui-spinner-button ui-spinner-down" );
17122        this.buttons.first().button( {
17123            "icon": this.options.icons.up,
17124            "showLabel": false
17125        } );
17126        this.buttons.last().button( {
17127            "icon": this.options.icons.down,
17128            "showLabel": false
17129        } );
17130
17131        // IE 6 doesn't understand height: 50% for the buttons
17132        // unless the wrapper has an explicit height
17133        if ( this.buttons.height() > Math.ceil( this.uiSpinner.height() * 0.5 ) &&
17134                this.uiSpinner.height() > 0 ) {
17135            this.uiSpinner.height( this.uiSpinner.height() );
17136        }
17137    },
17138
17139    _keydown: function( event ) {
17140        var options = this.options,
17141            keyCode = $.ui.keyCode;
17142
17143        switch ( event.keyCode ) {
17144        case keyCode.UP:
17145            this._repeat( null, 1, event );
17146            return true;
17147        case keyCode.DOWN:
17148            this._repeat( null, -1, event );
17149            return true;
17150        case keyCode.PAGE_UP:
17151            this._repeat( null, options.page, event );
17152            return true;
17153        case keyCode.PAGE_DOWN:
17154            this._repeat( null, -options.page, event );
17155            return true;
17156        }
17157
17158        return false;
17159    },
17160
17161    _start: function( event ) {
17162        if ( !this.spinning && this._trigger( "start", event ) === false ) {
17163            return false;
17164        }
17165
17166        if ( !this.counter ) {
17167            this.counter = 1;
17168        }
17169        this.spinning = true;
17170        return true;
17171    },
17172
17173    _repeat: function( i, steps, event ) {
17174        i = i || 500;
17175
17176        clearTimeout( this.timer );
17177        this.timer = this._delay( function() {
17178            this._repeat( 40, steps, event );
17179        }, i );
17180
17181        this._spin( steps * this.options.step, event );
17182    },
17183
17184    _spin: function( step, event ) {
17185        var value = this.value() || 0;
17186
17187        if ( !this.counter ) {
17188            this.counter = 1;
17189        }
17190
17191        value = this._adjustValue( value + step * this._increment( this.counter ) );
17192
17193        if ( !this.spinning || this._trigger( "spin", event, { value: value } ) !== false ) {
17194            this._value( value );
17195            this.counter++;
17196        }
17197    },
17198
17199    _increment: function( i ) {
17200        var incremental = this.options.incremental;
17201
17202        if ( incremental ) {
17203            return typeof incremental === "function" ?
17204                incremental( i ) :
17205                Math.floor( i * i * i / 50000 - i * i / 500 + 17 * i / 200 + 1 );
17206        }
17207
17208        return 1;
17209    },
17210
17211    _precision: function() {
17212        var precision = this._precisionOf( this.options.step );
17213        if ( this.options.min !== null ) {
17214            precision = Math.max( precision, this._precisionOf( this.options.min ) );
17215        }
17216        return precision;
17217    },
17218
17219    _precisionOf: function( num ) {
17220        var str = num.toString(),
17221            decimal = str.indexOf( "." );
17222        return decimal === -1 ? 0 : str.length - decimal - 1;
17223    },
17224
17225    _adjustValue: function( value ) {
17226        var base, aboveMin,
17227            options = this.options;
17228
17229        // Make sure we're at a valid step
17230        // - find out where we are relative to the base (min or 0)
17231        base = options.min !== null ? options.min : 0;
17232        aboveMin = value - base;
17233
17234        // - round to the nearest step
17235        aboveMin = Math.round( aboveMin / options.step ) * options.step;
17236
17237        // - rounding is based on 0, so adjust back to our base
17238        value = base + aboveMin;
17239
17240        // Fix precision from bad JS floating point math
17241        value = parseFloat( value.toFixed( this._precision() ) );
17242
17243        // Clamp the value
17244        if ( options.max !== null && value > options.max ) {
17245            return options.max;
17246        }
17247        if ( options.min !== null && value < options.min ) {
17248            return options.min;
17249        }
17250
17251        return value;
17252    },
17253
17254    _stop: function( event ) {
17255        if ( !this.spinning ) {
17256            return;
17257        }
17258
17259        clearTimeout( this.timer );
17260        clearTimeout( this.mousewheelTimer );
17261        this.counter = 0;
17262        this.spinning = false;
17263        this._trigger( "stop", event );
17264    },
17265
17266    _setOption: function( key, value ) {
17267        var prevValue, first, last;
17268
17269        if ( key === "culture" || key === "numberFormat" ) {
17270            prevValue = this._parse( this.element.val() );
17271            this.options[ key ] = value;
17272            this.element.val( this._format( prevValue ) );
17273            return;
17274        }
17275
17276        if ( key === "max" || key === "min" || key === "step" ) {
17277            if ( typeof value === "string" ) {
17278                value = this._parse( value );
17279            }
17280        }
17281        if ( key === "icons" ) {
17282            first = this.buttons.first().find( ".ui-icon" );
17283            this._removeClass( first, null, this.options.icons.up );
17284            this._addClass( first, null, value.up );
17285            last = this.buttons.last().find( ".ui-icon" );
17286            this._removeClass( last, null, this.options.icons.down );
17287            this._addClass( last, null, value.down );
17288        }
17289
17290        this._super( key, value );
17291    },
17292
17293    _setOptionDisabled: function( value ) {
17294        this._super( value );
17295
17296        this._toggleClass( this.uiSpinner, null, "ui-state-disabled", !!value );
17297        this.element.prop( "disabled", !!value );
17298        this.buttons.button( value ? "disable" : "enable" );
17299    },
17300
17301    _setOptions: spinnerModifier( function( options ) {
17302        this._super( options );
17303    } ),
17304
17305    _parse: function( val ) {
17306        if ( typeof val === "string" && val !== "" ) {
17307            val = window.Globalize && this.options.numberFormat ?
17308                Globalize.parseFloat( val, 10, this.options.culture ) : +val;
17309        }
17310        return val === "" || isNaN( val ) ? null : val;
17311    },
17312
17313    _format: function( value ) {
17314        if ( value === "" ) {
17315            return "";
17316        }
17317        return window.Globalize && this.options.numberFormat ?
17318            Globalize.format( value, this.options.numberFormat, this.options.culture ) :
17319            value;
17320    },
17321
17322    _refresh: function() {
17323        this.element.attr( {
17324            "aria-valuemin": this.options.min,
17325            "aria-valuemax": this.options.max,
17326
17327            // TODO: what should we do with values that can't be parsed?
17328            "aria-valuenow": this._parse( this.element.val() )
17329        } );
17330    },
17331
17332    isValid: function() {
17333        var value = this.value();
17334
vendor: 4,519 bytes, lines 17335-17504
17335        // Null is invalid
17336        if ( value === null ) {
17337            return false;
17338        }
17339
17340        // If value gets adjusted, it's invalid
17341        return value === this._adjustValue( value );
17342    },
17343
17344    // Update the value without triggering change
17345    _value: function( value, allowAny ) {
17346        var parsed;
17347        if ( value !== "" ) {
17348            parsed = this._parse( value );
17349            if ( parsed !== null ) {
17350                if ( !allowAny ) {
17351                    parsed = this._adjustValue( parsed );
17352                }
17353                value = this._format( parsed );
17354            }
17355        }
17356        this.element.val( value );
17357        this._refresh();
17358    },
17359
17360    _destroy: function() {
17361        this.element
17362            .prop( "disabled", false )
17363            .removeAttr( "autocomplete role aria-valuemin aria-valuemax aria-valuenow" );
17364
17365        this.uiSpinner.replaceWith( this.element );
17366    },
17367
17368    stepUp: spinnerModifier( function( steps ) {
17369        this._stepUp( steps );
17370    } ),
17371    _stepUp: function( steps ) {
17372        if ( this._start() ) {
17373            this._spin( ( steps || 1 ) * this.options.step );
17374            this._stop();
17375        }
17376    },
17377
17378    stepDown: spinnerModifier( function( steps ) {
17379        this._stepDown( steps );
17380    } ),
17381    _stepDown: function( steps ) {
17382        if ( this._start() ) {
17383            this._spin( ( steps || 1 ) * -this.options.step );
17384            this._stop();
17385        }
17386    },
17387
17388    pageUp: spinnerModifier( function( pages ) {
17389        this._stepUp( ( pages || 1 ) * this.options.page );
17390    } ),
17391
17392    pageDown: spinnerModifier( function( pages ) {
17393        this._stepDown( ( pages || 1 ) * this.options.page );
17394    } ),
17395
17396    value: function( newVal ) {
17397        if ( !arguments.length ) {
17398            return this._parse( this.element.val() );
17399        }
17400        spinnerModifier( this._value ).call( this, newVal );
17401    },
17402
17403    widget: function() {
17404        return this.uiSpinner;
17405    }
17406} );
17407
17408// DEPRECATED
17409// TODO: switch return back to widget declaration at top of file when this is removed
17410if ( $.uiBackCompat === true ) {
17411
17412    // Backcompat for spinner html extension points
17413    $.widget( "ui.spinner", $.ui.spinner, {
17414        _enhance: function() {
17415            this.uiSpinner = this.element
17416                .attr( "autocomplete", "off" )
17417                .wrap( this._uiSpinnerHtml() )
17418                .parent()
17419
17420                    // Add buttons
17421                    .append( this._buttonHtml() );
17422        },
17423        _uiSpinnerHtml: function() {
17424            return "<span>";
17425        },
17426
17427        _buttonHtml: function() {
17428            return "<a></a><a></a>";
17429        }
17430    } );
17431}
17432
17433var widgetsSpinner = $.ui.spinner;
17434
17435
17436/*!
17437 * jQuery UI Tabs 1.14.1
17438 * https://jqueryui.com
17439 *
17440 * Copyright OpenJS Foundation and other contributors
17441 * Released under the MIT license.
17442 * https://jquery.org/license
17443 */
17444
17445//>>label: Tabs
17446//>>group: Widgets
17447//>>description: Transforms a set of container elements into a tab structure.
17448//>>docs: https://api.jqueryui.com/tabs/
17449//>>demos: https://jqueryui.com/tabs/
17450//>>css.structure: ../../themes/base/core.css
17451//>>css.structure: ../../themes/base/tabs.css
17452//>>css.theme: ../../themes/base/theme.css
17453
17454
17455$.widget( "ui.tabs", {
17456    version: "1.14.1",
17457    delay: 300,
17458    options: {
17459        active: null,
17460        classes: {
17461            "ui-tabs": "ui-corner-all",
17462            "ui-tabs-nav": "ui-corner-all",
17463            "ui-tabs-panel": "ui-corner-bottom",
17464            "ui-tabs-tab": "ui-corner-top"
17465        },
17466        collapsible: false,
17467        event: "click",
17468        heightStyle: "content",
17469        hide: null,
17470        show: null,
17471
17472        // Callbacks
17473        activate: null,
17474        beforeActivate: null,
17475        beforeLoad: null,
17476        load: null
17477    },
17478
17479    _isLocal: ( function() {
17480        var rhash = /#.*$/;
17481
17482        return function( anchor ) {
17483            var anchorUrl, locationUrl;
17484
17485            anchorUrl = anchor.href.replace( rhash, "" );
17486            locationUrl = location.href.replace( rhash, "" );
17487
17488            // Decoding may throw an error if the URL isn't UTF-8 (#9518)
17489            try {
17490                anchorUrl = decodeURIComponent( anchorUrl );
17491            } catch ( error ) {}
17492            try {
17493                locationUrl = decodeURIComponent( locationUrl );
17494            } catch ( error ) {}
17495
17496            return anchor.hash.length > 1 && anchorUrl === locationUrl;
17497        };
17498    } )(),
17499
17500    _create: function() {
17501        var that = this,
17502            options = this.options;
17503
17504        this.running = false;
vendor: 25,994 bytes, lines 17505-18310
17505
17506        this._addClass( "ui-tabs", "ui-widget ui-widget-content" );
17507        this._toggleClass( "ui-tabs-collapsible", null, options.collapsible );
17508
17509        this._processTabs();
17510        options.active = this._initialActive();
17511
17512        // Take disabling tabs via class attribute from HTML
17513        // into account and update option properly.
17514        if ( Array.isArray( options.disabled ) ) {
17515            options.disabled = $.uniqueSort( options.disabled.concat(
17516                $.map( this.tabs.filter( ".ui-state-disabled" ), function( li ) {
17517                    return that.tabs.index( li );
17518                } )
17519            ) ).sort();
17520        }
17521
17522        // Check for length avoids error when initializing empty list
17523        if ( this.options.active !== false && this.anchors.length ) {
17524            this.active = this._findActive( options.active );
17525        } else {
17526            this.active = $();
17527        }
17528
17529        this._refresh();
17530
17531        if ( this.active.length ) {
17532            this.load( options.active );
17533        }
17534    },
17535
17536    _initialActive: function() {
17537        var active = this.options.active,
17538            collapsible = this.options.collapsible,
17539            locationHashDecoded = decodeURIComponent( location.hash.substring( 1 ) );
17540
17541        if ( active === null ) {
17542
17543            // check the fragment identifier in the URL
17544            if ( locationHashDecoded ) {
17545                this.tabs.each( function( i, tab ) {
17546                    if ( $( tab ).attr( "aria-controls" ) === locationHashDecoded ) {
17547                        active = i;
17548                        return false;
17549                    }
17550                } );
17551            }
17552
17553            // Check for a tab marked active via a class
17554            if ( active === null ) {
17555                active = this.tabs.index( this.tabs.filter( ".ui-tabs-active" ) );
17556            }
17557
17558            // No active tab, set to false
17559            if ( active === null || active === -1 ) {
17560                active = this.tabs.length ? 0 : false;
17561            }
17562        }
17563
17564        // Handle numbers: negative, out of range
17565        if ( active !== false ) {
17566            active = this.tabs.index( this.tabs.eq( active ) );
17567            if ( active === -1 ) {
17568                active = collapsible ? false : 0;
17569            }
17570        }
17571
17572        // Don't allow collapsible: false and active: false
17573        if ( !collapsible && active === false && this.anchors.length ) {
17574            active = 0;
17575        }
17576
17577        return active;
17578    },
17579
17580    _getCreateEventData: function() {
17581        return {
17582            tab: this.active,
17583            panel: !this.active.length ? $() : this._getPanelForTab( this.active )
17584        };
17585    },
17586
17587    _tabKeydown: function( event ) {
17588        var focusedTab = $( this.document[ 0 ].activeElement ).closest( "li" ),
17589            selectedIndex = this.tabs.index( focusedTab ),
17590            goingForward = true;
17591
17592        if ( this._handlePageNav( event ) ) {
17593            return;
17594        }
17595
17596        switch ( event.keyCode ) {
17597        case $.ui.keyCode.RIGHT:
17598        case $.ui.keyCode.DOWN:
17599            selectedIndex++;
17600            break;
17601        case $.ui.keyCode.UP:
17602        case $.ui.keyCode.LEFT:
17603            goingForward = false;
17604            selectedIndex--;
17605            break;
17606        case $.ui.keyCode.END:
17607            selectedIndex = this.anchors.length - 1;
17608            break;
17609        case $.ui.keyCode.HOME:
17610            selectedIndex = 0;
17611            break;
17612        case $.ui.keyCode.SPACE:
17613
17614            // Activate only, no collapsing
17615            event.preventDefault();
17616            clearTimeout( this.activating );
17617            this._activate( selectedIndex );
17618            return;
17619        case $.ui.keyCode.ENTER:
17620
17621            // Toggle (cancel delayed activation, allow collapsing)
17622            event.preventDefault();
17623            clearTimeout( this.activating );
17624
17625            // Determine if we should collapse or activate
17626            this._activate( selectedIndex === this.options.active ? false : selectedIndex );
17627            return;
17628        default:
17629            return;
17630        }
17631
17632        // Focus the appropriate tab, based on which key was pressed
17633        event.preventDefault();
17634        clearTimeout( this.activating );
17635        selectedIndex = this._focusNextTab( selectedIndex, goingForward );
17636
17637        // Navigating with control/command key will prevent automatic activation
17638        if ( !event.ctrlKey && !event.metaKey ) {
17639
17640            // Update aria-selected immediately so that AT think the tab is already selected.
17641            // Otherwise AT may confuse the user by stating that they need to activate the tab,
17642            // but the tab will already be activated by the time the announcement finishes.
17643            focusedTab.attr( "aria-selected", "false" );
17644            this.tabs.eq( selectedIndex ).attr( "aria-selected", "true" );
17645
17646            this.activating = this._delay( function() {
17647                this.option( "active", selectedIndex );
17648            }, this.delay );
17649        }
17650    },
17651
17652    _panelKeydown: function( event ) {
17653        if ( this._handlePageNav( event ) ) {
17654            return;
17655        }
17656
17657        // Ctrl+up moves focus to the current tab
17658        if ( event.ctrlKey && event.keyCode === $.ui.keyCode.UP ) {
17659            event.preventDefault();
17660            this.active.trigger( "focus" );
17661        }
17662    },
17663
17664    // Alt+page up/down moves focus to the previous/next tab (and activates)
17665    _handlePageNav: function( event ) {
17666        if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_UP ) {
17667            this._activate( this._focusNextTab( this.options.active - 1, false ) );
17668            return true;
17669        }
17670        if ( event.altKey && event.keyCode === $.ui.keyCode.PAGE_DOWN ) {
17671            this._activate( this._focusNextTab( this.options.active + 1, true ) );
17672            return true;
17673        }
17674    },
17675
17676    _findNextTab: function( index, goingForward ) {
17677        var lastTabIndex = this.tabs.length - 1;
17678
17679        function constrain() {
17680            if ( index > lastTabIndex ) {
17681                index = 0;
17682            }
17683            if ( index < 0 ) {
17684                index = lastTabIndex;
17685            }
17686            return index;
17687        }
17688
17689        while ( $.inArray( constrain(), this.options.disabled ) !== -1 ) {
17690            index = goingForward ? index + 1 : index - 1;
17691        }
17692
17693        return index;
17694    },
17695
17696    _focusNextTab: function( index, goingForward ) {
17697        index = this._findNextTab( index, goingForward );
17698        this.tabs.eq( index ).trigger( "focus" );
17699        return index;
17700    },
17701
17702    _setOption: function( key, value ) {
17703        if ( key === "active" ) {
17704
17705            // _activate() will handle invalid values and update this.options
17706            this._activate( value );
17707            return;
17708        }
17709
17710        this._super( key, value );
17711
17712        if ( key === "collapsible" ) {
17713            this._toggleClass( "ui-tabs-collapsible", null, value );
17714
17715            // Setting collapsible: false while collapsed; open first panel
17716            if ( !value && this.options.active === false ) {
17717                this._activate( 0 );
17718            }
17719        }
17720
17721        if ( key === "event" ) {
17722            this._setupEvents( value );
17723        }
17724
17725        if ( key === "heightStyle" ) {
17726            this._setupHeightStyle( value );
17727        }
17728    },
17729
17730    refresh: function() {
17731        var options = this.options,
17732            lis = this.tablist.children( ":has(a[href])" );
17733
17734        // Get disabled tabs from class attribute from HTML
17735        // this will get converted to a boolean if needed in _refresh()
17736        options.disabled = $.map( lis.filter( ".ui-state-disabled" ), function( tab ) {
17737            return lis.index( tab );
17738        } );
17739
17740        this._processTabs();
17741
17742        // Was collapsed or no tabs
17743        if ( options.active === false || !this.anchors.length ) {
17744            options.active = false;
17745            this.active = $();
17746
17747        // was active, but active tab is gone
17748        } else if ( this.active.length && !$.contains( this.tablist[ 0 ], this.active[ 0 ] ) ) {
17749
17750            // all remaining tabs are disabled
17751            if ( this.tabs.length === options.disabled.length ) {
17752                options.active = false;
17753                this.active = $();
17754
17755            // activate previous tab
17756            } else {
17757                this._activate( this._findNextTab( Math.max( 0, options.active - 1 ), false ) );
17758            }
17759
17760        // was active, active tab still exists
17761        } else {
17762
17763            // make sure active index is correct
17764            options.active = this.tabs.index( this.active );
17765        }
17766
17767        this._refresh();
17768    },
17769
17770    _refresh: function() {
17771        this._setOptionDisabled( this.options.disabled );
17772        this._setupEvents( this.options.event );
17773        this._setupHeightStyle( this.options.heightStyle );
17774
17775        this.tabs.not( this.active ).attr( {
17776            "aria-selected": "false",
17777            "aria-expanded": "false",
17778            tabIndex: -1
17779        } );
17780        this.panels.not( this._getPanelForTab( this.active ) )
17781            .hide()
17782            .attr( {
17783                "aria-hidden": "true"
17784            } );
17785
17786        // Make sure one tab is in the tab order
17787        if ( !this.active.length ) {
17788            this.tabs.eq( 0 ).attr( "tabIndex", 0 );
17789        } else {
17790            this.active
17791                .attr( {
17792                    "aria-selected": "true",
17793                    "aria-expanded": "true",
17794                    tabIndex: 0
17795                } );
17796            this._addClass( this.active, "ui-tabs-active", "ui-state-active" );
17797            this._getPanelForTab( this.active )
17798                .show()
17799                .attr( {
17800                    "aria-hidden": "false"
17801                } );
17802        }
17803    },
17804
17805    _processTabs: function() {
17806        var that = this,
17807            prevTabs = this.tabs,
17808            prevAnchors = this.anchors,
17809            prevPanels = this.panels;
17810
17811        this.tablist = this._getList().attr( "role", "tablist" );
17812        this._addClass( this.tablist, "ui-tabs-nav",
17813            "ui-helper-reset ui-helper-clearfix ui-widget-header" );
17814
17815        // Prevent users from focusing disabled tabs via click
17816        this.tablist
17817            .on( "mousedown" + this.eventNamespace, "> li", function( event ) {
17818                if ( $( this ).is( ".ui-state-disabled" ) ) {
17819                    event.preventDefault();
17820                }
17821            } );
17822
17823        this.tabs = this.tablist.find( "> li:has(a[href])" )
17824            .attr( {
17825                role: "tab",
17826                tabIndex: -1
17827            } );
17828        this._addClass( this.tabs, "ui-tabs-tab", "ui-state-default" );
17829
17830        this.anchors = this.tabs.map( function() {
17831            return $( "a", this )[ 0 ];
17832        } )
17833            .attr( {
17834                tabIndex: -1
17835            } );
17836        this._addClass( this.anchors, "ui-tabs-anchor" );
17837
17838        this.panels = $();
17839
17840        this.anchors.each( function( i, anchor ) {
17841            var selector, panel, panelId,
17842                anchorId = $( anchor ).uniqueId().attr( "id" ),
17843                tab = $( anchor ).closest( "li" ),
17844                originalAriaControls = tab.attr( "aria-controls" );
17845
17846            // Inline tab
17847            if ( that._isLocal( anchor ) ) {
17848                selector = decodeURIComponent( anchor.hash );
17849                panelId = selector.substring( 1 );
17850                panel = that.element.find( "#" + CSS.escape( panelId ) );
17851
17852            // remote tab
17853            } else {
17854
17855                // If the tab doesn't already have aria-controls,
17856                // generate an id by using a throw-away element
17857                panelId = tab.attr( "aria-controls" ) || $( {} ).uniqueId()[ 0 ].id;
17858                selector = "#" + panelId;
17859                panel = that.element.find( selector );
17860                if ( !panel.length ) {
17861                    panel = that._createPanel( panelId );
17862                    panel.insertAfter( that.panels[ i - 1 ] || that.tablist );
17863                }
17864                panel.attr( "aria-live", "polite" );
17865            }
17866
17867            if ( panel.length ) {
17868                that.panels = that.panels.add( panel );
17869            }
17870            if ( originalAriaControls ) {
17871                tab.data( "ui-tabs-aria-controls", originalAriaControls );
17872            }
17873            tab.attr( {
17874                "aria-controls": panelId,
17875                "aria-labelledby": anchorId
17876            } );
17877            panel.attr( "aria-labelledby", anchorId );
17878        } );
17879
17880        this.panels.attr( "role", "tabpanel" );
17881        this._addClass( this.panels, "ui-tabs-panel", "ui-widget-content" );
17882
17883        // Avoid memory leaks (#10056)
17884        if ( prevTabs ) {
17885            this._off( prevTabs.not( this.tabs ) );
17886            this._off( prevAnchors.not( this.anchors ) );
17887            this._off( prevPanels.not( this.panels ) );
17888        }
17889    },
17890
17891    // Allow overriding how to find the list for rare usage scenarios (#7715)
17892    _getList: function() {
17893        return this.tablist || this.element.find( "ol, ul" ).eq( 0 );
17894    },
17895
17896    _createPanel: function( id ) {
17897        return $( "<div>" )
17898            .attr( "id", id )
17899            .data( "ui-tabs-destroy", true );
17900    },
17901
17902    _setOptionDisabled: function( disabled ) {
17903        var currentItem, li, i;
17904
17905        if ( Array.isArray( disabled ) ) {
17906            if ( !disabled.length ) {
17907                disabled = false;
17908            } else if ( disabled.length === this.anchors.length ) {
17909                disabled = true;
17910            }
17911        }
17912
17913        // Disable tabs
17914        for ( i = 0; ( li = this.tabs[ i ] ); i++ ) {
17915            currentItem = $( li );
17916            if ( disabled === true || $.inArray( i, disabled ) !== -1 ) {
17917                currentItem.attr( "aria-disabled", "true" );
17918                this._addClass( currentItem, null, "ui-state-disabled" );
17919            } else {
17920                currentItem.removeAttr( "aria-disabled" );
17921                this._removeClass( currentItem, null, "ui-state-disabled" );
17922            }
17923        }
17924
17925        this.options.disabled = disabled;
17926
17927        this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null,
17928            disabled === true );
17929    },
17930
17931    _setupEvents: function( event ) {
17932        var events = {};
17933        if ( event ) {
17934            $.each( event.split( " " ), function( index, eventName ) {
17935                events[ eventName ] = "_eventHandler";
17936            } );
17937        }
17938
17939        this._off( this.anchors.add( this.tabs ).add( this.panels ) );
17940
17941        // Always prevent the default action, even when disabled
17942        this._on( true, this.anchors, {
17943            click: function( event ) {
17944                event.preventDefault();
17945            }
17946        } );
17947        this._on( this.anchors, events );
17948        this._on( this.tabs, { keydown: "_tabKeydown" } );
17949        this._on( this.panels, { keydown: "_panelKeydown" } );
17950
17951        this._focusable( this.tabs );
17952        this._hoverable( this.tabs );
17953    },
17954
17955    _setupHeightStyle: function( heightStyle ) {
17956        var maxHeight,
17957            parent = this.element.parent();
17958
17959        if ( heightStyle === "fill" ) {
17960            maxHeight = parent.height();
17961            maxHeight -= this.element.outerHeight() - this.element.height();
17962
17963            this.element.siblings( ":visible" ).each( function() {
17964                var elem = $( this ),
17965                    position = elem.css( "position" );
17966
17967                if ( position === "absolute" || position === "fixed" ) {
17968                    return;
17969                }
17970                maxHeight -= elem.outerHeight( true );
17971            } );
17972
17973            this.element.children().not( this.panels ).each( function() {
17974                maxHeight -= $( this ).outerHeight( true );
17975            } );
17976
17977            this.panels.each( function() {
17978                $( this ).height( Math.max( 0, maxHeight -
17979                    $( this ).innerHeight() + $( this ).height() ) );
17980            } )
17981                .css( "overflow", "auto" );
17982        } else if ( heightStyle === "auto" ) {
17983            maxHeight = 0;
17984            this.panels.each( function() {
17985                maxHeight = Math.max( maxHeight, $( this ).height( "" ).height() );
17986            } ).height( maxHeight );
17987        }
17988    },
17989
17990    _eventHandler: function( event ) {
17991        var options = this.options,
17992            active = this.active,
17993            anchor = $( event.currentTarget ),
17994            tab = anchor.closest( "li" ),
17995            clickedIsActive = tab[ 0 ] === active[ 0 ],
17996            collapsing = clickedIsActive && options.collapsible,
17997            toShow = collapsing ? $() : this._getPanelForTab( tab ),
17998            toHide = !active.length ? $() : this._getPanelForTab( active ),
17999            eventData = {
18000                oldTab: active,
18001                oldPanel: toHide,
18002                newTab: collapsing ? $() : tab,
18003                newPanel: toShow
18004            };
18005
18006        event.preventDefault();
18007
18008        if ( tab.hasClass( "ui-state-disabled" ) ||
18009
18010                // tab is already loading
18011                tab.hasClass( "ui-tabs-loading" ) ||
18012
18013                // can't switch durning an animation
18014                this.running ||
18015
18016                // click on active header, but not collapsible
18017                ( clickedIsActive && !options.collapsible ) ||
18018
18019                // allow canceling activation
18020                ( this._trigger( "beforeActivate", event, eventData ) === false ) ) {
18021            return;
18022        }
18023
18024        options.active = collapsing ? false : this.tabs.index( tab );
18025
18026        this.active = clickedIsActive ? $() : tab;
18027        if ( this.xhr ) {
18028            this.xhr.abort();
18029        }
18030
18031        if ( !toHide.length && !toShow.length ) {
18032            $.error( "jQuery UI Tabs: Mismatching fragment identifier." );
18033        }
18034
18035        if ( toShow.length ) {
18036            this.load( this.tabs.index( tab ), event );
18037        }
18038        this._toggle( event, eventData );
18039    },
18040
18041    // Handles show/hide for selecting tabs
18042    _toggle: function( event, eventData ) {
18043        var that = this,
18044            toShow = eventData.newPanel,
18045            toHide = eventData.oldPanel;
18046
18047        this.running = true;
18048
18049        function complete() {
18050            that.running = false;
18051            that._trigger( "activate", event, eventData );
18052        }
18053
18054        function show() {
18055            that._addClass( eventData.newTab.closest( "li" ), "ui-tabs-active", "ui-state-active" );
18056
18057            if ( toShow.length && that.options.show ) {
18058                that._show( toShow, that.options.show, complete );
18059            } else {
18060                toShow.show();
18061                complete();
18062            }
18063        }
18064
18065        // Start out by hiding, then showing, then completing
18066        if ( toHide.length && this.options.hide ) {
18067            this._hide( toHide, this.options.hide, function() {
18068                that._removeClass( eventData.oldTab.closest( "li" ),
18069                    "ui-tabs-active", "ui-state-active" );
18070                show();
18071            } );
18072        } else {
18073            this._removeClass( eventData.oldTab.closest( "li" ),
18074                "ui-tabs-active", "ui-state-active" );
18075            toHide.hide();
18076            show();
18077        }
18078
18079        toHide.attr( "aria-hidden", "true" );
18080        eventData.oldTab.attr( {
18081            "aria-selected": "false",
18082            "aria-expanded": "false"
18083        } );
18084
18085        // If we're switching tabs, remove the old tab from the tab order.
18086        // If we're opening from collapsed state, remove the previous tab from the tab order.
18087        // If we're collapsing, then keep the collapsing tab in the tab order.
18088        if ( toShow.length && toHide.length ) {
18089            eventData.oldTab.attr( "tabIndex", -1 );
18090        } else if ( toShow.length ) {
18091            this.tabs.filter( function() {
18092                return $( this ).attr( "tabIndex" ) === 0;
18093            } )
18094                .attr( "tabIndex", -1 );
18095        }
18096
18097        toShow.attr( "aria-hidden", "false" );
18098        eventData.newTab.attr( {
18099            "aria-selected": "true",
18100            "aria-expanded": "true",
18101            tabIndex: 0
18102        } );
18103    },
18104
18105    _activate: function( index ) {
18106        var anchor,
18107            active = this._findActive( index );
18108
18109        // Trying to activate the already active panel
18110        if ( active[ 0 ] === this.active[ 0 ] ) {
18111            return;
18112        }
18113
18114        // Trying to collapse, simulate a click on the current active header
18115        if ( !active.length ) {
18116            active = this.active;
18117        }
18118
18119        anchor = active.find( ".ui-tabs-anchor" )[ 0 ];
18120        this._eventHandler( {
18121            target: anchor,
18122            currentTarget: anchor,
18123            preventDefault: $.noop
18124        } );
18125    },
18126
18127    _findActive: function( index ) {
18128        return index === false ? $() : this.tabs.eq( index );
18129    },
18130
18131    _getIndex: function( index ) {
18132
18133        // meta-function to give users option to provide a href string instead of a numerical index.
18134        if ( typeof index === "string" ) {
18135            index = this.anchors.index( this.anchors.filter( "[href$='" +
18136                CSS.escape( index ) + "']" ) );
18137        }
18138
18139        return index;
18140    },
18141
18142    _destroy: function() {
18143        if ( this.xhr ) {
18144            this.xhr.abort();
18145        }
18146
18147        this.tablist
18148            .removeAttr( "role" )
18149            .off( this.eventNamespace );
18150
18151        this.anchors
18152            .removeAttr( "role tabIndex" )
18153            .removeUniqueId();
18154
18155        this.tabs.add( this.panels ).each( function() {
18156            if ( $.data( this, "ui-tabs-destroy" ) ) {
18157                $( this ).remove();
18158            } else {
18159                $( this ).removeAttr( "role tabIndex " +
18160                    "aria-live aria-busy aria-selected aria-labelledby aria-hidden aria-expanded" );
18161            }
18162        } );
18163
18164        this.tabs.each( function() {
18165            var li = $( this ),
18166                prev = li.data( "ui-tabs-aria-controls" );
18167            if ( prev ) {
18168                li
18169                    .attr( "aria-controls", prev )
18170                    .removeData( "ui-tabs-aria-controls" );
18171            } else {
18172                li.removeAttr( "aria-controls" );
18173            }
18174        } );
18175
18176        this.panels.show();
18177
18178        if ( this.options.heightStyle !== "content" ) {
18179            this.panels.css( "height", "" );
18180        }
18181    },
18182
18183    enable: function( index ) {
18184        var disabled = this.options.disabled;
18185        if ( disabled === false ) {
18186            return;
18187        }
18188
18189        if ( index === undefined ) {
18190            disabled = false;
18191        } else {
18192            index = this._getIndex( index );
18193            if ( Array.isArray( disabled ) ) {
18194                disabled = $.map( disabled, function( num ) {
18195                    return num !== index ? num : null;
18196                } );
18197            } else {
18198                disabled = $.map( this.tabs, function( li, num ) {
18199                    return num !== index ? num : null;
18200                } );
18201            }
18202        }
18203        this._setOptionDisabled( disabled );
18204    },
18205
18206    disable: function( index ) {
18207        var disabled = this.options.disabled;
18208        if ( disabled === true ) {
18209            return;
18210        }
18211
18212        if ( index === undefined ) {
18213            disabled = true;
18214        } else {
18215            index = this._getIndex( index );
18216            if ( $.inArray( index, disabled ) !== -1 ) {
18217                return;
18218            }
18219            if ( Array.isArray( disabled ) ) {
18220                disabled = $.merge( [ index ], disabled ).sort();
18221            } else {
18222                disabled = [ index ];
18223            }
18224        }
18225        this._setOptionDisabled( disabled );
18226    },
18227
18228    load: function( index, event ) {
18229        index = this._getIndex( index );
18230        var that = this,
18231            tab = this.tabs.eq( index ),
18232            anchor = tab.find( ".ui-tabs-anchor" ),
18233            panel = this._getPanelForTab( tab ),
18234            eventData = {
18235                tab: tab,
18236                panel: panel
18237            },
18238            complete = function( jqXHR, status ) {
18239                if ( status === "abort" ) {
18240                    that.panels.stop( false, true );
18241                }
18242
18243                that._removeClass( tab, "ui-tabs-loading" );
18244                panel.removeAttr( "aria-busy" );
18245
18246                if ( jqXHR === that.xhr ) {
18247                    delete that.xhr;
18248                }
18249            };
18250
18251        // Not remote
18252        if ( this._isLocal( anchor[ 0 ] ) ) {
18253            return;
18254        }
18255
18256        this.xhr = $.ajax( this._ajaxSettings( anchor, event, eventData ) );
18257
18258        if ( this.xhr.statusText !== "canceled" ) {
18259            this._addClass( tab, "ui-tabs-loading" );
18260            panel.attr( "aria-busy", "true" );
18261
18262            this.xhr
18263                .done( function( response, status, jqXHR ) {
18264                    panel.html( response );
18265                    that._trigger( "load", event, eventData );
18266
18267                    complete( jqXHR, status );
18268                } )
18269                .fail( function( jqXHR, status ) {
18270                    complete( jqXHR, status );
18271                } );
18272        }
18273    },
18274
18275    _ajaxSettings: function( anchor, event, eventData ) {
18276        var that = this;
18277        return {
18278            url: anchor.attr( "href" ),
18279            beforeSend: function( jqXHR, settings ) {
18280                return that._trigger( "beforeLoad", event,
18281                    $.extend( { jqXHR: jqXHR, ajaxSettings: settings }, eventData ) );
18282            }
18283        };
18284    },
18285
18286    _getPanelForTab: function( tab ) {
18287        var id = $( tab ).attr( "aria-controls" );
18288        return this.element.find( "#" + CSS.escape( id ) );
18289    }
18290} );
18291
18292// DEPRECATED
18293// TODO: Switch return back to widget declaration at top of file when this is removed
18294if ( $.uiBackCompat === true ) {
18295
18296    // Backcompat for ui-tab class (now ui-tabs-tab)
18297    $.widget( "ui.tabs", $.ui.tabs, {
18298        _processTabs: function() {
18299            this._superApply( arguments );
18300            this._addClass( this.tabs, "ui-tab" );
18301        }
18302    } );
18303}
18304
18305var widgetsTabs = $.ui.tabs;
18306
18307
18308
18309
18310} );

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.