/*! jQuery UI - v1.12.1 - 2016-09-14
* http://jqueryui.com
* 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-1-7.js, keycode.js, labels.js, scroll-parent.js, tabbable.js, unique-id.js, widgets/accordion.js, widgets/autocomplete.js, widgets/button.js, widgets/checkboxradio.js, widgets/controlgroup.js, widgets/datepicker.js, widgets/dialog.js, widgets/draggable.js, widgets/droppable.js, widgets/menu.js, widgets/mouse.js, widgets/progressbar.js, widgets/resizable.js, widgets/selectable.js, widgets/selectmenu.js, widgets/slider.js, widgets/sortable.js, widgets/spinner.js, widgets/tabs.js, widgets/tooltip.js
* Copyright jQuery Foundation and other contributors; Licensed MIT */

(function( factory ) {
    if ( typeof define === "function" && define.amd ) {

        // AMD. Register as an anonymous module.
        define([ "jquery" ], factory );
    } else {

        // Browser globals
        factory( jQuery );
    }
}(function( $ ) {

$.ui = $.ui || {};

var version = $.ui.version = "1.12.1";


/*!
 * jQuery UI Widget 1.12.1
 * http://jqueryui.com
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

//>>label: Widget
//>>group: Core
//>>description: Provides a factory for creating stateful widgets with a common API.
//>>docs: http://api.jqueryui.com/jQuery.widget/
//>>demos: http://jqueryui.com/widget/



var widgetUuid = 0;
var widgetSlice = Array.prototype.slice;

$.cleanData = ( function( orig ) {
    return function( elems ) {
        var events, elem, i;
        for ( i = 0; ( elem = elems[ i ] ) != null; i++ ) {
            try {

                // Only trigger remove when necessary to save time
                events = $._data( elem, "events" );
                if ( events && events.remove ) {
                    $( elem ).triggerHandler( "remove" );
                }

            // Http://bugs.jquery.com/ticket/8235
            } catch ( e ) {}
        }
        orig( elems );
    };
} )( $.cleanData );

$.widget = function( name, base, prototype ) {
    var existingConstructor, constructor, basePrototype;

    // ProxiedPrototype allows the provided prototype to remain unmodified
    // so that it can be used as a mixin for multiple widgets (#8876)
    var proxiedPrototype = {};

    var namespace = name.split( "." )[ 0 ];
    name = name.split( "." )[ 1 ];
    var fullName = namespace + "-" + name;

    if ( !prototype ) {
        prototype = base;
        base = $.Widget;
    }

    if ( $.isArray( prototype ) ) {
        prototype = $.extend.apply( null, [ {} ].concat( prototype ) );
    }

    // Create selector for plugin
    $.expr[ ":" ][ fullName.toLowerCase() ] = function( elem ) {
        return !!$.data( elem, fullName );
    };

    $[ namespace ] = $[ namespace ] || {};
    existingConstructor = $[ namespace ][ name ];
    constructor = $[ namespace ][ name ] = function( options, element ) {

        // Allow instantiation without "new" keyword
        if ( !this._createWidget ) {
            return new constructor( options, element );
        }

        // Allow instantiation without initializing for simple inheritance
        // must use "new" keyword (the code above always passes args)
        if ( arguments.length ) {
            this._createWidget( options, element );
        }
    };

    // Extend with the existing constructor to carry over any static properties
    $.extend( constructor, existingConstructor, {
        version: prototype.version,

        // Copy the object used to create the prototype in case we need to
        // redefine the widget later
        _proto: $.extend( {}, prototype ),

        // Track widgets that inherit from this widget in case this widget is
        // redefined after a widget inherits from it
        _childConstructors: []
    } );

    basePrototype = new base();

    // We need to make the options hash a property directly on the new instance
    // otherwise we'll modify the options hash on the prototype that we're
    // inheriting from
    basePrototype.options = $.widget.extend( {}, basePrototype.options );
    $.each( prototype, function( prop, value ) {
        if ( !$.isFunction( value ) ) {
            proxiedPrototype[ prop ] = value;
            return;
        }
        proxiedPrototype[ prop ] = ( function() {
            function _super() {
                return base.prototype[ prop ].apply( this, arguments );
            }

            function _superApply( args ) {
                return base.prototype[ prop ].apply( this, args );
            }

            return function() {
                var __super = this._super;
                var __superApply = this._superApply;
                var returnValue;

                this._super = _super;
                this._superApply = _superApply;

                returnValue = value.apply( this, arguments );

                this._super = __super;
                this._superApply = __superApply;

                return returnValue;
            };
        } )();
    } );
    constructor.prototype = $.widget.extend( basePrototype, {

        // TODO: remove support for widgetEventPrefix
        // always use the name + a colon as the prefix, e.g., draggable:start
        // don't prefix for widgets that aren't DOM-based
        widgetEventPrefix: existingConstructor ? ( basePrototype.widgetEventPrefix || name ) : name
    }, proxiedPrototype, {
        constructor: constructor,
        namespace: namespace,
        widgetName: name,
        widgetFullName: fullName
    } );

    // If this widget is being redefined then we need to find all widgets that
    // are inheriting from it and redefine all of them so that they inherit from
    // the new version of this widget. We're essentially trying to replace one
    // level in the prototype chain.
    if ( existingConstructor ) {
        $.each( existingConstructor._childConstructors, function( i, child ) {
            var childPrototype = child.prototype;

            // Redefine the child widget using the same prototype that was
            // originally used, but inherit from the new version of the base
            $.widget( childPrototype.namespace + "." + childPrototype.widgetName, constructor,
                child._proto );
        } );

        // Remove the list of existing child constructors from the old constructor
        // so the old child constructors can be garbage collected
        delete existingConstructor._childConstructors;
    } else {
        base._childConstructors.push( constructor );
    }

    $.widget.bridge( name, constructor );

    return constructor;
};

$.widget.extend = function( target ) {
    var input = widgetSlice.call( arguments, 1 );
    var inputIndex = 0;
    var inputLength = input.length;
    var key;
    var value;

    for ( ; inputIndex < inputLength; inputIndex++ ) {
        for ( key in input[ inputIndex ] ) {
            value = input[ inputIndex ][ key ];
            if ( input[ inputIndex ].hasOwnProperty( key ) && value !== undefined ) {

                // Clone objects
                if ( $.isPlainObject( value ) ) {
                    target[ key ] = $.isPlainObject( target[ key ] ) ?
                        $.widget.extend( {}, target[ key ], value ) :

                        // Don't extend strings, arrays, etc. with objects
                        $.widget.extend( {}, value );

                // Copy everything else by reference
                } else {
                    target[ key ] = value;
                }
            }
        }
    }
    return target;
};

$.widget.bridge = function( name, object ) {
    var fullName = object.prototype.widgetFullName || name;
    $.fn[ name ] = function( options ) {
        var isMethodCall = typeof options === "string";
        var args = widgetSlice.call( arguments, 1 );
        var returnValue = this;

        if ( isMethodCall ) {

            // If this is an empty collection, we need to have the instance method
            // return undefined instead of the jQuery instance
            if ( !this.length && options === "instance" ) {
                returnValue = undefined;
            } else {
                this.each( function() {
                    var methodValue;
                    var instance = $.data( this, fullName );

                    if ( options === "instance" ) {
                        returnValue = instance;
                        return false;
                    }

                    if ( !instance ) {
                        return $.error( "cannot call methods on " + name +
                            " prior to initialization; " +
                            "attempted to call method '" + options + "'" );
                    }

                    if ( !$.isFunction( instance[ options ] ) || options.charAt( 0 ) === "_" ) {
                        return $.error( "no such method '" + options + "' for " + name +
                            " widget instance" );
                    }

                    methodValue = instance[ options ].apply( instance, args );

                    if ( methodValue !== instance && methodValue !== undefined ) {
                        returnValue = methodValue && methodValue.jquery ?
                            returnValue.pushStack( methodValue.get() ) :
                            methodValue;
                        return false;
                    }
                } );
            }
        } else {

            // Allow multiple hashes to be passed on init
            if ( args.length ) {
                options = $.widget.extend.apply( null, [ options ].concat( args ) );
            }

            this.each( function() {
                var instance = $.data( this, fullName );
                if ( instance ) {
                    instance.option( options || {} );
                    if ( instance._init ) {
                        instance._init();
                    }
                } else {
                    $.data( this, fullName, new object( options, this ) );
                }
            } );
        }

        return returnValue;
    };
};

$.Widget = function( /* options, element */ ) {};
$.Widget._childConstructors = [];

$.Widget.prototype = {
    widgetName: "widget",
    widgetEventPrefix: "",
    defaultElement: "<div>",

    options: {
        classes: {},
        disabled: false,

        // Callbacks
        create: null
    },

    _createWidget: function( options, element ) {
        element = $( element || this.defaultElement || this )[ 0 ];
        this.element = $( element );
        this.uuid = widgetUuid++;
        this.eventNamespace = "." + this.widgetName + this.uuid;

        this.bindings = $();
        this.hoverable = $();
        this.focusable = $();
        this.classesElementLookup = {};

        if ( element !== this ) {
            $.data( element, this.widgetFullName, this );
            this._on( true, this.element, {
                remove: function( event ) {
                    if ( event.target === element ) {
                        this.destroy();
                    }
                }
            } );
            this.document = $( element.style ?

                // Element within the document
                element.ownerDocument :

                // Element is window or document
                element.document || element );
            this.window = $( this.document[ 0 ].defaultView || this.document[ 0 ].parentWindow );
        }

        this.options = $.widget.extend( {},
            this.options,
            this._getCreateOptions(),
            options );

        this._create();

        if ( this.options.disabled ) {
            this._setOptionDisabled( this.options.disabled );
        }

        this._trigger( "create", null, this._getCreateEventData() );
        this._init();
    },

    _getCreateOptions: function() {
        return {};
    },

    _getCreateEventData: $.noop,

    _create: $.noop,

    _init: $.noop,

    destroy: function() {
        var that = this;

        this._destroy();
        $.each( this.classesElementLookup, function( key, value ) {
            that._removeClass( value, key );
        } );

        // We can probably remove the unbind calls in 2.0
        // all event bindings should go through this._on()
        this.element
            .off( this.eventNamespace )
            .removeData( this.widgetFullName );
        this.widget()
            .off( this.eventNamespace )
            .removeAttr( "aria-disabled" );

        // Clean up events and states
        this.bindings.off( this.eventNamespace );
    },

    _destroy: $.noop,

    widget: function() {
        return this.element;
    },

    option: function( key, value ) {
        var options = key;
        var parts;
        var curOption;
        var i;

        if ( arguments.length === 0 ) {

            // Don't return a reference to the internal hash
            return $.widget.extend( {}, this.options );
        }

        if ( typeof key === "string" ) {

            // Handle nested keys, e.g., "foo.bar" => { foo: { bar: ___ } }
            options = {};
            parts = key.split( "." );
            key = parts.shift();
            if ( parts.length ) {
                curOption = options[ key ] = $.widget.extend( {}, this.options[ key ] );
                for ( i = 0; i < parts.length - 1; i++ ) {
                    curOption[ parts[ i ] ] = curOption[ parts[ i ] ] || {};
                    curOption = curOption[ parts[ i ] ];
                }
                key = parts.pop();
                if ( arguments.length === 1 ) {
                    return curOption[ key ] === undefined ? null : curOption[ key ];
                }
                curOption[ key ] = value;
            } else {
                if ( arguments.length === 1 ) {
                    return this.options[ key ] === undefined ? null : this.options[ key ];
                }
                options[ key ] = value;
            }
        }

        this._setOptions( options );

        return this;
    },

    _setOptions: function( options ) {
        var key;

        for ( key in options ) {
            this._setOption( key, options[ key ] );
        }

        return this;
    },

    _setOption: function( key, value ) {
        if ( key === "classes" ) {
            this._setOptionClasses( value );
        }

        this.options[ key ] = value;

        if ( key === "disabled" ) {
            this._setOptionDisabled( value );
        }

        return this;
    },

    _setOptionClasses: function( value ) {
        var classKey, elements, currentElements;

        for ( classKey in value ) {
            currentElements = this.classesElementLookup[ classKey ];
            if ( value[ classKey ] === this.options.classes[ classKey ] ||
                    !currentElements ||
                    !currentElements.length ) {
                continue;
            }

            // We are doing this to create a new jQuery object because the _removeClass() call
            // on the next line is going to destroy the reference to the current elements being
            // tracked. We need to save a copy of this collection so that we can add the new classes
            // below.
            elements = $( currentElements.get() );
            this._removeClass( currentElements, classKey );

            // We don't use _addClass() here, because that uses this.options.classes
            // for generating the string of classes. We want to use the value passed in from
            // _setOption(), this is the new value of the classes option which was passed to
            // _setOption(). We pass this value directly to _classes().
            elements.addClass( this._classes( {
                element: elements,
                keys: classKey,
                classes: value,
                add: true
            } ) );
        }
    },

    _setOptionDisabled: function( value ) {
        this._toggleClass( this.widget(), this.widgetFullName + "-disabled", null, !!value );

        // If the widget is becoming disabled, then nothing is interactive
        if ( value ) {
            this._removeClass( this.hoverable, null, "ui-state-hover" );
            this._removeClass( this.focusable, null, "ui-state-focus" );
        }
    },

    enable: function() {
        return this._setOptions( { disabled: false } );
    },

    disable: function() {
        return this._setOptions( { disabled: true } );
    },

    _classes: function( options ) {
        var full = [];
        var that = this;

        options = $.extend( {
            element: this.element,
            classes: this.options.classes || {}
        }, options );

        function processClassString( classes, checkOption ) {
            var current, i;
            for ( i = 0; i < classes.length; i++ ) {
                current = that.classesElementLookup[ classes[ i ] ] || $();
                if ( options.add ) {
                    current = $( $.unique( current.get().concat( options.element.get() ) ) );
                } else {
                    current = $( current.not( options.element ).get() );
                }
                that.classesElementLookup[ classes[ i ] ] = current;
                full.push( classes[ i ] );
                if ( checkOption && options.classes[ classes[ i ] ] ) {
                    full.push( options.classes[ classes[ i ] ] );
                }
            }
        }

        this._on( options.element, {
            "remove": "_untrackClassesElement"
        } );

        if ( options.keys ) {
            processClassString( options.keys.match( /\S+/g ) || [], true );
        }
        if ( options.extra ) {
            processClassString( options.extra.match( /\S+/g ) || [] );
        }

        return full.join( " " );
    },

    _untrackClassesElement: function( event ) {
        var that = this;
        $.each( that.classesElementLookup, function( key, value ) {
            if ( $.inArray( event.target, value ) !== -1 ) {
                that.classesElementLookup[ key ] = $( value.not( event.target ).get() );
            }
        } );
    },

    _removeClass: function( element, keys, extra ) {
        return this._toggleClass( element, keys, extra, false );
    },

    _addClass: function( element, keys, extra ) {
        return this._toggleClass( element, keys, extra, true );
    },

    _toggleClass: function( element, keys, extra, add ) {
        add = ( typeof add === "boolean" ) ? add : extra;
        var shift = ( typeof element === "string" || element === null ),
            options = {
                extra: shift ? keys : extra,
                keys: shift ? element : keys,
                element: shift ? this.element : element,
                add: add
            };
        options.element.toggleClass( this._classes( options ), add );
        return this;
    },

    _on: function( suppressDisabledCheck, element, handlers ) {
        var delegateElement;
        var instance = this;

        // No suppressDisabledCheck flag, shuffle arguments
        if ( typeof suppressDisabledCheck !== "boolean" ) {
            handlers = element;
            element = suppressDisabledCheck;
            suppressDisabledCheck = false;
        }

        // No element argument, shuffle and use this.element
        if ( !handlers ) {
            handlers = element;
            element = this.element;
            delegateElement = this.widget();
        } else {
            element = delegateElement = $( element );
            this.bindings = this.bindings.add( element );
        }

        $.each( handlers, function( event, handler ) {
            function handlerProxy() {

                // Allow widgets to customize the disabled handling
                // - disabled as an array instead of boolean
                // - disabled class as method for disabling individual parts
                if ( !suppressDisabledCheck &&
                        ( instance.options.disabled === true ||
                        $( this ).hasClass( "ui-state-disabled" ) ) ) {
                    return;
                }
                return ( typeof handler === "string" ? instance[ handler ] : handler )
                    .apply( instance, arguments );
            }

            // Copy the guid so direct unbinding works
            if ( typeof handler !== "string" ) {
                handlerProxy.guid = handler.guid =
                    handler.guid || handlerProxy.guid || $.guid++;
            }

            var match = event.match( /^([\w:-]*)\s*(.*)$/ );
            var eventName = match[ 1 ] + instance.eventNamespace;
            var selector = match[ 2 ];

            if ( selector ) {
                delegateElement.on( eventName, selector, handlerProxy );
            } else {
                element.on( eventName, handlerProxy );
            }
        } );
    },

    _off: function( element, eventName ) {
        eventName = ( eventName || "" ).split( " " ).join( this.eventNamespace + " " ) +
            this.eventNamespace;
        element.off( eventName ).off( eventName );

        // Clear the stack to avoid memory leaks (#10056)
        this.bindings = $( this.bindings.not( element ).get() );
        this.focusable = $( this.focusable.not( element ).get() );
        this.hoverable = $( this.hoverable.not( element ).get() );
    },

    _delay: function( handler, delay ) {
        function handlerProxy() {
            return ( typeof handler === "string" ? instance[ handler ] : handler )
                .apply( instance, arguments );
        }
        var instance = this;
        return setTimeout( handlerProxy, delay || 0 );
    },

    _hoverable: function( element ) {
        this.hoverable = this.hoverable.add( element );
        this._on( element, {
            mouseenter: function( event ) {
                this._addClass( $( event.currentTarget ), null, "ui-state-hover" );
            },
            mouseleave: function( event ) {
                this._removeClass( $( event.currentTarget ), null, "ui-state-hover" );
            }
        } );
    },

    _focusable: function( element ) {
        this.focusable = this.focusable.add( element );
        this._on( element, {
            focusin: function( event ) {
                this._addClass( $( event.currentTarget ), null, "ui-state-focus" );
            },
            focusout: function( event ) {
                this._removeClass( $( event.currentTarget ), null, "ui-state-focus" );
            }
        } );
    },

    _trigger: function( type, event, data ) {
        var prop, orig;
        var callback = this.options[ type ];

        data = data || {};
        event = $.Event( event );
        event.type = ( type === this.widgetEventPrefix ?
            type :
            this.widgetEventPrefix + type ).toLowerCase();

        // The original event may come from any element
        // so we need to reset the target on the new event
        event.target = this.element[ 0 ];

        // Copy original event properties over to the new event
        orig = event.originalEvent;
        if ( orig ) {
            for ( prop in orig ) {
                if ( !( prop in event ) ) {
                    event[ prop ] = orig[ prop ];
                }
            }
        }

        this.element.trigger( event, data );
        return !( $.isFunction( callback ) &&
            callback.apply( this.element[ 0 ], [ event ].concat( data ) ) === false ||
            event.isDefaultPrevented() );
    }
};

$.each( { show: "fadeIn", hide: "fadeOut" }, function( method, defaultEffect ) {
    $.Widget.prototype[ "_" + method ] = function( element, options, callback ) {
        if ( typeof options === "string" ) {
            options = { effect: options };
        }

        var hasOptions;
        var effectName = !options ?
            method :
            options === true || typeof options === "number" ?
                defaultEffect :
                options.effect || defaultEffect;

        options = options || {};
        if ( typeof options === "number" ) {
            options = { duration: options };
        }

        hasOptions = !$.isEmptyObject( options );
        options.complete = callback;

        if ( options.delay ) {
            element.delay( options.delay );
        }

        if ( hasOptions && $.effects && $.effects.effect[ effectName ] ) {
            element[ method ]( options );
        } else if ( effectName !== method && element[ effectName ] ) {
            element[ effectName ]( options.duration, options.easing, callback );
        } else {
            element.queue( function( next ) {
                $( this )[ method ]();
                if ( callback ) {
                    callback.call( element[ 0 ] );
                }
                next();
            } );
        }
    };
} );

var widget = $.widget;



// This file is deprecated
var ie = $.ui.ie = !!/msie [\w.]+/.exec( navigator.userAgent.toLowerCase() );

/*!
 * jQuery UI Mouse 1.12.1
 * http://jqueryui.com
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

//>>label: Mouse
//>>group: Widgets
//>>description: Abstracts mouse-based interactions to assist in creating certain widgets.
//>>docs: http://api.jqueryui.com/mouse/



var mouseHandled = false;
$( document ).on( "mouseup", function() {
    mouseHandled = false;
} );

var widgetsMouse = $.widget( "ui.mouse", {
    version: "1.12.1",
    options: {
        cancel: "input, textarea, button, select, option",
        distance: 1,
        delay: 0
    },
    _mouseInit: function() {
        var that = this;

        this.element
            .on( "mousedown." + this.widgetName, function( event ) {
                return that._mouseDown( event );
            } )
            .on( "click." + this.widgetName, function( event ) {
                if ( true === $.data( event.target, that.widgetName + ".preventClickEvent" ) ) {
                    $.removeData( event.target, that.widgetName + ".preventClickEvent" );
                    event.stopImmediatePropagation();
                    return false;
                }
            } );

        this.started = false;
    },

    // TODO: make sure destroying one instance of mouse doesn't mess with
    // other instances of mouse
    _mouseDestroy: function() {
        this.element.off( "." + this.widgetName );
        if ( this._mouseMoveDelegate ) {
            this.document
                .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
                .off( "mouseup." + this.widgetName, this._mouseUpDelegate );
        }
    },

    _mouseDown: function( event ) {

        // don't let more than one widget handle mouseStart
        if ( mouseHandled ) {
            return;
        }

        this._mouseMoved = false;

        // We may have missed mouseup (out of window)
        ( this._mouseStarted && this._mouseUp( event ) );

        this._mouseDownEvent = event;

        var that = this,
            btnIsLeft = ( event.which === 1 ),

            // event.target.nodeName works around a bug in IE 8 with
            // disabled inputs (#7620)
            elIsCancel = ( typeof this.options.cancel === "string" && event.target.nodeName ?
                $( event.target ).closest( this.options.cancel ).length : false );
        if ( !btnIsLeft || elIsCancel || !this._mouseCapture( event ) ) {
            return true;
        }

        this.mouseDelayMet = !this.options.delay;
        if ( !this.mouseDelayMet ) {
            this._mouseDelayTimer = setTimeout( function() {
                that.mouseDelayMet = true;
            }, this.options.delay );
        }

        if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
            this._mouseStarted = ( this._mouseStart( event ) !== false );
            if ( !this._mouseStarted ) {
                event.preventDefault();
                return true;
            }
        }

        // Click event may never have fired (Gecko & Opera)
        if ( true === $.data( event.target, this.widgetName + ".preventClickEvent" ) ) {
            $.removeData( event.target, this.widgetName + ".preventClickEvent" );
        }

        // These delegates are required to keep context
        this._mouseMoveDelegate = function( event ) {
            return that._mouseMove( event );
        };
        this._mouseUpDelegate = function( event ) {
            return that._mouseUp( event );
        };

        this.document
            .on( "mousemove." + this.widgetName, this._mouseMoveDelegate )
            .on( "mouseup." + this.widgetName, this._mouseUpDelegate );

        event.preventDefault();

        mouseHandled = true;
        return true;
    },

    _mouseMove: function( event ) {

        // Only check for mouseups outside the document if you've moved inside the document
        // at least once. This prevents the firing of mouseup in the case of IE<9, which will
        // fire a mousemove event if content is placed under the cursor. See #7778
        // Support: IE <9
        if ( this._mouseMoved ) {

            // IE mouseup check - mouseup happened when mouse was out of window
            if ( $.ui.ie && ( !document.documentMode || document.documentMode < 9 ) &&
                    !event.button ) {
                return this._mouseUp( event );

            // Iframe mouseup check - mouseup occurred in another document
            } else if ( !event.which ) {

                // Support: Safari <=8 - 9
                // Safari sets which to 0 if you press any of the following keys
                // during a drag (#14461)
                if ( event.originalEvent.altKey || event.originalEvent.ctrlKey ||
                        event.originalEvent.metaKey || event.originalEvent.shiftKey ) {
                    this.ignoreMissingWhich = true;
                } else if ( !this.ignoreMissingWhich ) {
                    return this._mouseUp( event );
                }
            }
        }

        if ( event.which || event.button ) {
            this._mouseMoved = true;
        }

        if ( this._mouseStarted ) {
            this._mouseDrag( event );
            return event.preventDefault();
        }

        if ( this._mouseDistanceMet( event ) && this._mouseDelayMet( event ) ) {
            this._mouseStarted =
                ( this._mouseStart( this._mouseDownEvent, event ) !== false );
            ( this._mouseStarted ? this._mouseDrag( event ) : this._mouseUp( event ) );
        }

        return !this._mouseStarted;
    },

    _mouseUp: function( event ) {
        this.document
            .off( "mousemove." + this.widgetName, this._mouseMoveDelegate )
            .off( "mouseup." + this.widgetName, this._mouseUpDelegate );

        if ( this._mouseStarted ) {
            this._mouseStarted = false;

            if ( event.target === this._mouseDownEvent.target ) {
                $.data( event.target, this.widgetName + ".preventClickEvent", true );
            }

            this._mouseStop( event );
        }

        if ( this._mouseDelayTimer ) {
            clearTimeout( this._mouseDelayTimer );
            delete this._mouseDelayTimer;
        }

        this.ignoreMissingWhich = false;
        mouseHandled = false;
        event.preventDefault();
    },

    _mouseDistanceMet: function( event ) {
        return ( Math.max(
                Math.abs( this._mouseDownEvent.pageX - event.pageX ),
                Math.abs( this._mouseDownEvent.pageY - event.pageY )
            ) >= this.options.distance
        );
    },

    _mouseDelayMet: function( /* event */ ) {
        return this.mouseDelayMet;
    },

    // These are placeholder methods, to be overriden by extending plugin
    _mouseStart: function( /* event */ ) {},
    _mouseDrag: function( /* event */ ) {},
    _mouseStop: function( /* event */ ) {},
    _mouseCapture: function( /* event */ ) { return true; }
} );




// $.ui.plugin is deprecated. Use $.widget() extensions instead.
var plugin = $.ui.plugin = {
    add: function( module, option, set ) {
        var i,
            proto = $.ui[ module ].prototype;
        for ( i in set ) {
            proto.plugins[ i ] = proto.plugins[ i ] || [];
            proto.plugins[ i ].push( [ option, set[ i ] ] );
        }
    },
    call: function( instance, name, args, allowDisconnected ) {
        var i,
            set = instance.plugins[ name ];

        if ( !set ) {
            return;
        }

        if ( !allowDisconnected && ( !instance.element[ 0 ].parentNode ||
                instance.element[ 0 ].parentNode.nodeType === 11 ) ) {
            return;
        }

        for ( i = 0; i < set.length; i++ ) {
            if ( instance.options[ set[ i ][ 0 ] ] ) {
                set[ i ][ 1 ].apply( instance.element, args );
            }
        }
    }
};



var safeBlur = $.ui.safeBlur = function( element ) {

    // Support: IE9 - 10 only
    // If the <body> is blurred, IE will switch windows, see #9420
    if ( element && element.nodeName.toLowerCase() !== "body" ) {
        $( element ).trigger( "blur" );
    }
};


/*!
 * jQuery UI Draggable 1.12.1
 * http://jqueryui.com
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

//>>label: Draggable
//>>group: Interactions
//>>description: Enables dragging functionality for any element.
//>>docs: http://api.jqueryui.com/draggable/
//>>demos: http://jqueryui.com/draggable/
//>>css.structure: ../../themes/base/draggable.css



$.widget( "ui.draggable", $.ui.mouse, {
    version: "1.12.1",
    widgetEventPrefix: "drag",
    options: {
        addClasses: true,
        appendTo: "parent",
        axis: false,
        connectToSortable: false,
        containment: false,
        cursor: "auto",
        cursorAt: false,
        grid: false,
        handle: false,
        helper: "original",
        iframeFix: false,
        opacity: false,
        refreshPositions: false,
        revert: false,
        revertDuration: 500,
        scope: "default",
        scroll: true,
        scrollSensitivity: 20,
        scrollSpeed: 20,
        snap: false,
        snapMode: "both",
        snapTolerance: 20,
        stack: false,
        zIndex: false,

        // Callbacks
        drag: null,
        start: null,
        stop: null
    },
    _create: function() {

        if ( this.options.helper === "original" ) {
            this._setPositionRelative();
        }
        if ( this.options.addClasses ) {
            this._addClass( "ui-draggable" );
        }
        this._setHandleClassName();

        this._mouseInit();
    },

    _setOption: function( key, value ) {
        this._super( key, value );
        if ( key === "handle" ) {
            this._removeHandleClassName();
            this._setHandleClassName();
        }
    },

    _destroy: function() {
        if ( ( this.helper || this.element ).is( ".ui-draggable-dragging" ) ) {
            this.destroyOnClear = true;
            return;
        }
        this._removeHandleClassName();
        this._mouseDestroy();
    },

    _mouseCapture: function( event ) {
        var o = this.options;

        // Among others, prevent a drag on a resizable-handle
        if ( this.helper || o.disabled ||
                $( event.target ).closest( ".ui-resizable-handle" ).length > 0 ) {
            return false;
        }

        //Quit if we're not on a valid handle
        this.handle = this._getHandle( event );
        if ( !this.handle ) {
            return false;
        }

        this._blurActiveElement( event );

        this._blockFrames( o.iframeFix === true ? "iframe" : o.iframeFix );

        return true;

    },

    _blockFrames: function( selector ) {
        this.iframeBlocks = this.document.find( selector ).map( function() {
            var iframe = $( this );

            return $( "<div>" )
                .css( "position", "absolute" )
                .appendTo( iframe.parent() )
                .outerWidth( iframe.outerWidth() )
                .outerHeight( iframe.outerHeight() )
                .offset( iframe.offset() )[ 0 ];
        } );
    },

    _unblockFrames: function() {
        if ( this.iframeBlocks ) {
            this.iframeBlocks.remove();
            delete this.iframeBlocks;
        }
    },

    _blurActiveElement: function( event ) {
        var activeElement = $.ui.safeActiveElement( this.document[ 0 ] ),
            target = $( event.target );

        // Don't blur if the event occurred on an element that is within
        // the currently focused element
        // See #10527, #12472
        if ( target.closest( activeElement ).length ) {
            return;
        }

        // Blur any element that currently has focus, see #4261
        $.ui.safeBlur( activeElement );
    },

    _mouseStart: function( event ) {

        var o = this.options;

        //Create and append the visible helper
        this.helper = this._createHelper( event );

        this._addClass( this.helper, "ui-draggable-dragging" );

        //Cache the helper size
        this._cacheHelperProportions();

        //If ddmanager is used for droppables, set the global draggable
        if ( $.ui.ddmanager ) {
            $.ui.ddmanager.current = this;
        }

        /*
         * - Position generation -
         * This block generates everything position related - it's the core of draggables.
         */

        //Cache the margins of the original element
        this._cacheMargins();

        //Store the helper's css position
        this.cssPosition = this.helper.css( "position" );
        this.scrollParent = this.helper.scrollParent( true );
        this.offsetParent = this.helper.offsetParent();
        this.hasFixedAncestor = this.helper.parents().filter( function() {
                return $( this ).css( "position" ) === "fixed";
            } ).length > 0;

        //The element's absolute position on the page minus margins
        this.positionAbs = this.element.offset();
        this._refreshOffsets( event );

        //Generate the original position
        this.originalPosition = this.position = this._generatePosition( event, false );
        this.originalPageX = event.pageX;
        this.originalPageY = event.pageY;

        //Adjust the mouse offset relative to the helper if "cursorAt" is supplied
        ( o.cursorAt && this._adjustOffsetFromHelper( o.cursorAt ) );

        //Set a containment if given in the options
        this._setContainment();

        //Trigger event + callbacks
        if ( this._trigger( "start", event ) === false ) {
            this._clear();
            return false;
        }

        //Recache the helper size
        this._cacheHelperProportions();

        //Prepare the droppable offsets
        if ( $.ui.ddmanager && !o.dropBehaviour ) {
            $.ui.ddmanager.prepareOffsets( this, event );
        }

        // Execute the drag once - this causes the helper not to be visible before getting its
        // correct position
        this._mouseDrag( event, true );

        // If the ddmanager is used for droppables, inform the manager that dragging has started
        // (see #5003)
        if ( $.ui.ddmanager ) {
            $.ui.ddmanager.dragStart( this, event );
        }

        return true;
    },

    _refreshOffsets: function( event ) {
        this.offset = {
            top: this.positionAbs.top - this.margins.top,
            left: this.positionAbs.left - this.margins.left,
            scroll: false,
            parent: this._getParentOffset(),
            relative: this._getRelativeOffset()
        };

        this.offset.click = {
            left: event.pageX - this.offset.left,
            top: event.pageY - this.offset.top
        };
    },

    _mouseDrag: function( event, noPropagation ) {

        // reset any necessary cached properties (see #5009)
        if ( this.hasFixedAncestor ) {
            this.offset.parent = this._getParentOffset();
        }

        //Compute the helpers position
        this.position = this._generatePosition( event, true );
        this.positionAbs = this._convertPositionTo( "absolute" );

        //Call plugins and callbacks and use the resulting position if something is returned
        if ( !noPropagation ) {
            var ui = this._uiHash();
            if ( this._trigger( "drag", event, ui ) === false ) {
                this._mouseUp( new $.Event( "mouseup", event ) );
                return false;
            }
            this.position = ui.position;
        }

        this.helper[ 0 ].style.left = this.position.left + "px";
        this.helper[ 0 ].style.top = this.position.top + "px";

        if ( $.ui.ddmanager ) {
            $.ui.ddmanager.drag( this, event );
        }

        return false;
    },

    _mouseStop: function( event ) {

        //If we are using droppables, inform the manager about the drop
        var that = this,
            dropped = false;
        if ( $.ui.ddmanager && !this.options.dropBehaviour ) {
            dropped = $.ui.ddmanager.drop( this, event );
        }

        //if a drop comes from outside (a sortable)
        if ( this.dropped ) {
            dropped = this.dropped;
            this.dropped = false;
        }

        if ( ( this.options.revert === "invalid" && !dropped ) ||
                ( this.options.revert === "valid" && dropped ) ||
                this.options.revert === true || ( $.isFunction( this.options.revert ) &&
                this.options.revert.call( this.element, dropped ) )
        ) {
            $( this.helper ).animate(
                this.originalPosition,
                parseInt( this.options.revertDuration, 10 ),
                function() {
                    if ( that._trigger( "stop", event ) !== false ) {
                        that._clear();
                    }
                }
            );
        } else {
            if ( this._trigger( "stop", event ) !== false ) {
                this._clear();
            }
        }

        return false;
    },

    _mouseUp: function( event ) {
        this._unblockFrames();

        // If the ddmanager is used for droppables, inform the manager that dragging has stopped
        // (see #5003)
        if ( $.ui.ddmanager ) {
            $.ui.ddmanager.dragStop( this, event );
        }

        // Only need to focus if the event occurred on the draggable itself, see #10527
        if ( this.handleElement.is( event.target ) ) {

            // The interaction is over; whether or not the click resulted in a drag,
            // focus the element
            this.element.trigger( "focus" );
        }

        return $.ui.mouse.prototype._mouseUp.call( this, event );
    },

    cancel: function() {

        if ( this.helper.is( ".ui-draggable-dragging" ) ) {
            this._mouseUp( new $.Event( "mouseup", { target: this.element[ 0 ] } ) );
        } else {
            this._clear();
        }

        return this;

    },

    _getHandle: function( event ) {
        return this.options.handle ?
            !!$( event.target ).closest( this.element.find( this.options.handle ) ).length :
            true;
    },

    _setHandleClassName: function() {
        this.handleElement = this.options.handle ?
            this.element.find( this.options.handle ) : this.element;
        this._addClass( this.handleElement, "ui-draggable-handle" );
    },

    _removeHandleClassName: function() {
        this._removeClass( this.handleElement, "ui-draggable-handle" );
    },

    _createHelper: function( event ) {

        var o = this.options,
            helperIsFunction = $.isFunction( o.helper ),
            helper = helperIsFunction ?
                $( o.helper.apply( this.element[ 0 ], [ event ] ) ) :
                ( o.helper === "clone" ?
                    this.element.clone().removeAttr( "id" ) :
                    this.element );

        if ( !helper.parents( "body" ).length ) {
            helper.appendTo( ( o.appendTo === "parent" ?
                this.element[ 0 ].parentNode :
                o.appendTo ) );
        }

        // Http://bugs.jqueryui.com/ticket/9446
        // a helper function can return the original element
        // which wouldn't have been set to relative in _create
        if ( helperIsFunction && helper[ 0 ] === this.element[ 0 ] ) {
            this._setPositionRelative();
        }

        if ( helper[ 0 ] !== this.element[ 0 ] &&
                !( /(fixed|absolute)/ ).test( helper.css( "position" ) ) ) {
            helper.css( "position", "absolute" );
        }

        return helper;

    },

    _setPositionRelative: function() {
        if ( !( /^(?:r|a|f)/ ).test( this.element.css( "position" ) ) ) {
            this.element[ 0 ].style.position = "relative";
        }
    },

    _adjustOffsetFromHelper: function( obj ) {
        if ( typeof obj === "string" ) {
            obj = obj.split( " " );
        }
        if ( $.isArray( obj ) ) {
            obj = { left: +obj[ 0 ], top: +obj[ 1 ] || 0 };
        }
        if ( "left" in obj ) {
            this.offset.click.left = obj.left + this.margins.left;
        }
        if ( "right" in obj ) {
            this.offset.click.left = this.helperProportions.width - obj.right + this.margins.left;
        }
        if ( "top" in obj ) {
            this.offset.click.top = obj.top + this.margins.top;
        }
        if ( "bottom" in obj ) {
            this.offset.click.top = this.helperProportions.height - obj.bottom + this.margins.top;
        }
    },

    _isRootNode: function( element ) {
        return ( /(html|body)/i ).test( element.tagName ) || element === this.document[ 0 ];
    },

    _getParentOffset: function() {

        //Get the offsetParent and cache its position
        var po = this.offsetParent.offset(),
            document = this.document[ 0 ];

        // This is a special case where we need to modify a offset calculated on start, since the
        // following happened:
        // 1. The position of the helper is absolute, so it's position is calculated based on the
        // next positioned parent
        // 2. The actual offset parent is a child of the scroll parent, and the scroll parent isn't
        // the document, which means that the scroll is included in the initial calculation of the
        // offset of the parent, and never recalculated upon drag
        if ( this.cssPosition === "absolute" && this.scrollParent[ 0 ] !== document &&
                $.contains( this.scrollParent[ 0 ], this.offsetParent[ 0 ] ) ) {
            po.left += this.scrollParent.scrollLeft();
            po.top += this.scrollParent.scrollTop();
        }

        if ( this._isRootNode( this.offsetParent[ 0 ] ) ) {
            po = { top: 0, left: 0 };
        }

        return {
            top: po.top + ( parseInt( this.offsetParent.css( "borderTopWidth" ), 10 ) || 0 ),
            left: po.left + ( parseInt( this.offsetParent.css( "borderLeftWidth" ), 10 ) || 0 )
        };

    },

    _getRelativeOffset: function() {
        if ( this.cssPosition !== "relative" ) {
            return { top: 0, left: 0 };
        }

        var p = this.element.position(),
            scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );

        return {
            top: p.top - ( parseInt( this.helper.css( "top" ), 10 ) || 0 ) +
                ( !scrollIsRootNode ? this.scrollParent.scrollTop() : 0 ),
            left: p.left - ( parseInt( this.helper.css( "left" ), 10 ) || 0 ) +
                ( !scrollIsRootNode ? this.scrollParent.scrollLeft() : 0 )
        };

    },

    _cacheMargins: function() {
        this.margins = {
            left: ( parseInt( this.element.css( "marginLeft" ), 10 ) || 0 ),
            top: ( parseInt( this.element.css( "marginTop" ), 10 ) || 0 ),
            right: ( parseInt( this.element.css( "marginRight" ), 10 ) || 0 ),
            bottom: ( parseInt( this.element.css( "marginBottom" ), 10 ) || 0 )
        };
    },

    _cacheHelperProportions: function() {
        this.helperProportions = {
            width: this.helper.outerWidth(),
            height: this.helper.outerHeight()
        };
    },

    _setContainment: function() {

        var isUserScrollable, c, ce,
            o = this.options,
            document = this.document[ 0 ];

        this.relativeContainer = null;

        if ( !o.containment ) {
            this.containment = null;
            return;
        }

        if ( o.containment === "window" ) {
            this.containment = [
                $( window ).scrollLeft() - this.offset.relative.left - this.offset.parent.left,
                $( window ).scrollTop() - this.offset.relative.top - this.offset.parent.top,
                $( window ).scrollLeft() + $( window ).width() -
                    this.helperProportions.width - this.margins.left,
                $( window ).scrollTop() +
                    ( $( window ).height() || document.body.parentNode.scrollHeight ) -
                    this.helperProportions.height - this.margins.top
            ];
            return;
        }

        if ( o.containment === "document" ) {
            this.containment = [
                0,
                0,
                $( document ).width() - this.helperProportions.width - this.margins.left,
                ( $( document ).height() || document.body.parentNode.scrollHeight ) -
                    this.helperProportions.height - this.margins.top
            ];
            return;
        }

        if ( o.containment.constructor === Array ) {
            this.containment = o.containment;
            return;
        }

        if ( o.containment === "parent" ) {
            o.containment = this.helper[ 0 ].parentNode;
        }

        c = $( o.containment );
        ce = c[ 0 ];

        if ( !ce ) {
            return;
        }

        isUserScrollable = /(scroll|auto)/.test( c.css( "overflow" ) );

        this.containment = [
            ( parseInt( c.css( "borderLeftWidth" ), 10 ) || 0 ) +
                ( parseInt( c.css( "paddingLeft" ), 10 ) || 0 ),
            ( parseInt( c.css( "borderTopWidth" ), 10 ) || 0 ) +
                ( parseInt( c.css( "paddingTop" ), 10 ) || 0 ),
            ( isUserScrollable ? Math.max( ce.scrollWidth, ce.offsetWidth ) : ce.offsetWidth ) -
                ( parseInt( c.css( "borderRightWidth" ), 10 ) || 0 ) -
                ( parseInt( c.css( "paddingRight" ), 10 ) || 0 ) -
                this.helperProportions.width -
                this.margins.left -
                this.margins.right,
            ( isUserScrollable ? Math.max( ce.scrollHeight, ce.offsetHeight ) : ce.offsetHeight ) -
                ( parseInt( c.css( "borderBottomWidth" ), 10 ) || 0 ) -
                ( parseInt( c.css( "paddingBottom" ), 10 ) || 0 ) -
                this.helperProportions.height -
                this.margins.top -
                this.margins.bottom
        ];
        this.relativeContainer = c;
    },

    _convertPositionTo: function( d, pos ) {

        if ( !pos ) {
            pos = this.position;
        }

        var mod = d === "absolute" ? 1 : -1,
            scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] );

        return {
            top: (

                // The absolute mouse position
                pos.top +

                // Only for relative positioned nodes: Relative offset from element to offset parent
                this.offset.relative.top * mod +

                // The offsetParent's offset without borders (offset + border)
                this.offset.parent.top * mod -
                ( ( this.cssPosition === "fixed" ?
                    -this.offset.scroll.top :
                    ( scrollIsRootNode ? 0 : this.offset.scroll.top ) ) * mod )
            ),
            left: (

                // The absolute mouse position
                pos.left +

                // Only for relative positioned nodes: Relative offset from element to offset parent
                this.offset.relative.left * mod +

                // The offsetParent's offset without borders (offset + border)
                this.offset.parent.left * mod   -
                ( ( this.cssPosition === "fixed" ?
                    -this.offset.scroll.left :
                    ( scrollIsRootNode ? 0 : this.offset.scroll.left ) ) * mod )
            )
        };

    },

    _generatePosition: function( event, constrainPosition ) {

        var containment, co, top, left,
            o = this.options,
            scrollIsRootNode = this._isRootNode( this.scrollParent[ 0 ] ),
            pageX = event.pageX,
            pageY = event.pageY;

        // Cache the scroll
        if ( !scrollIsRootNode || !this.offset.scroll ) {
            this.offset.scroll = {
                top: this.scrollParent.scrollTop(),
                left: this.scrollParent.scrollLeft()
            };
        }

        /*
         * - Position constraining -
         * Constrain the position to a mix of grid, containment.
         */

        // If we are not dragging yet, we won't check for options
        if ( constrainPosition ) {
            if ( this.containment ) {
                if ( this.relativeContainer ) {
                    co = this.relativeContainer.offset();
                    containment = [
                        this.containment[ 0 ] + co.left,
                        this.containment[ 1 ] + co.top,
                        this.containment[ 2 ] + co.left,
                        this.containment[ 3 ] + co.top
                    ];
                } else {
                    containment = this.containment;
                }

                if ( event.pageX - this.offset.click.left < containment[ 0 ] ) {
                    pageX = containment[ 0 ] + this.offset.click.left;
                }
                if ( event.pageY - this.offset.click.top < containment[ 1 ] ) {
                    pageY = containment[ 1 ] + this.offset.click.top;
                }
                if ( event.pageX - this.offset.click.left > containment[ 2 ] ) {
                    pageX = containment[ 2 ] + this.offset.click.left;
                }
                if ( event.pageY - this.offset.click.top > containment[ 3 ] ) {
                    pageY = containment[ 3 ] + this.offset.click.top;
                }
            }

            if ( o.grid ) {

                //Check for grid elements set to 0 to prevent divide by 0 error causing invalid
                // argument errors in IE (see ticket #6950)
                top = o.grid[ 1 ] ? this.originalPageY + Math.round( ( pageY -
                    this.originalPageY ) / o.grid[ 1 ] ) * o.grid[ 1 ] : this.originalPageY;
                pageY = containment ? ( ( top - this.offset.click.top >= containment[ 1 ] ||
                    top - this.offset.click.top > containment[ 3 ] ) ?
                        top :
                        ( ( top - this.offset.click.top >= containment[ 1 ] ) ?
                            top - o.grid[ 1 ] : top + o.grid[ 1 ] ) ) : top;

                left = o.grid[ 0 ] ? this.originalPageX +
                    Math.round( ( pageX - this.originalPageX ) / o.grid[ 0 ] ) * o.grid[ 0 ] :
                    this.originalPageX;
                pageX = containment ? ( ( left - this.offset.click.left >= containment[ 0 ] ||
                    left - this.offset.click.left > containment[ 2 ] ) ?
                        left :
                        ( ( left - this.offset.click.left >= containment[ 0 ] ) ?
                            left - o.grid[ 0 ] : left + o.grid[ 0 ] ) ) : left;
            }

            if ( o.axis === "y" ) {
                pageX = this.originalPageX;
            }

            if ( o.axis === "x" ) {
                pageY = this.originalPageY;
            }
        }

        return {
            top: (

                // The absolute mouse position
                pageY -

                // Click offset (relative to the element)
                this.offset.click.top -

                // Only for relative positioned nodes: Relative offset from element to offset parent
                this.offset.relative.top -

                // The offsetParent's offset without borders (offset + border)
                this.offset.parent.top +
                ( this.cssPosition === "fixed" ?
                    -this.offset.scroll.top :
                    ( scrollIsRootNode ? 0 : this.offset.scroll.top ) )
            ),
            left: (

                // The absolute mouse position
                pageX -

                // Click offset (relative to the element)
                this.offset.click.left -

                // Only for relative positioned nodes: Relative offset from element to offset parent
                this.offset.relative.left -

                // The offsetParent's offset without borders (offset + border)
                this.offset.parent.left +
                ( this.cssPosition === "fixed" ?
                    -this.offset.scroll.left :
                    ( scrollIsRootNode ? 0 : this.offset.scroll.left ) )
            )
        };

    },

    _clear: function() {
        this._removeClass( this.helper, "ui-draggable-dragging" );
        if ( this.helper[ 0 ] !== this.element[ 0 ] && !this.cancelHelperRemoval ) {
            this.helper.remove();
        }
        this.helper = null;
        this.cancelHelperRemoval = false;
        if ( this.destroyOnClear ) {
            this.destroy();
        }
    },

    // From now on bulk stuff - mainly helpers

    _trigger: function( type, event, ui ) {
        ui = ui || this._uiHash();
        $.ui.plugin.call( this, type, [ event, ui, this ], true );

        // Absolute position and offset (see #6884 ) have to be recalculated after plugins
        if ( /^(drag|start|stop)/.test( type ) ) {
            this.positionAbs = this._convertPositionTo( "absolute" );
            ui.offset = this.positionAbs;
        }
        return $.Widget.prototype._trigger.call( this, type, event, ui );
    },

    plugins: {},

    _uiHash: function() {
        return {
            helper: this.helper,
            position: this.position,
            originalPosition: this.originalPosition,
            offset: this.positionAbs
        };
    }

} );

$.ui.plugin.add( "draggable", "connectToSortable", {
    start: function( event, ui, draggable ) {
        var uiSortable = $.extend( {}, ui, {
            item: draggable.element
        } );

        draggable.sortables = [];
        $( draggable.options.connectToSortable ).each( function() {
            var sortable = $( this ).sortable( "instance" );

            if ( sortable && !sortable.options.disabled ) {
                draggable.sortables.push( sortable );

                // RefreshPositions is called at drag start to refresh the containerCache
                // which is used in drag. This ensures it's initialized and synchronized
                // with any changes that might have happened on the page since initialization.
                sortable.refreshPositions();
                sortable._trigger( "activate", event, uiSortable );
            }
        } );
    },
    stop: function( event, ui, draggable ) {
        var uiSortable = $.extend( {}, ui, {
            item: draggable.element
        } );

        draggable.cancelHelperRemoval = false;

        $.each( draggable.sortables, function() {
            var sortable = this;

            if ( sortable.isOver ) {
                sortable.isOver = 0;

                // Allow this sortable to handle removing the helper
                draggable.cancelHelperRemoval = true;
                sortable.cancelHelperRemoval = false;

                // Use _storedCSS To restore properties in the sortable,
                // as this also handles revert (#9675) since the draggable
                // may have modified them in unexpected ways (#8809)
                sortable._storedCSS = {
                    position: sortable.placeholder.css( "position" ),
                    top: sortable.placeholder.css( "top" ),
                    left: sortable.placeholder.css( "left" )
                };

                sortable._mouseStop( event );

                // Once drag has ended, the sortable should return to using
                // its original helper, not the shared helper from draggable
                sortable.options.helper = sortable.options._helper;
            } else {

                // Prevent this Sortable from removing the helper.
                // However, don't set the draggable to remove the helper
                // either as another connected Sortable may yet handle the removal.
                sortable.cancelHelperRemoval = true;

                sortable._trigger( "deactivate", event, uiSortable );
            }
        } );
    },
    drag: function( event, ui, draggable ) {
        $.each( draggable.sortables, function() {
            var innermostIntersecting = false,
                sortable = this;

            // Copy over variables that sortable's _intersectsWith uses
            sortable.positionAbs = draggable.positionAbs;
            sortable.helperProportions = draggable.helperProportions;
            sortable.offset.click = draggable.offset.click;

            if ( sortable._intersectsWith( sortable.containerCache ) ) {
                innermostIntersecting = true;

                $.each( draggable.sortables, function() {

                    // Copy over variables that sortable's _intersectsWith uses
                    this.positionAbs = draggable.positionAbs;
                    this.helperProportions = draggable.helperProportions;
                    this.offset.click = draggable.offset.click;

                    if ( this !== sortable &&
                            this._intersectsWith( this.containerCache ) &&
                            $.contains( sortable.element[ 0 ], this.element[ 0 ] ) ) {
                        innermostIntersecting = false;
                    }

                    return innermostIntersecting;
                } );
            }

            if ( innermostIntersecting ) {

                // If it intersects, we use a little isOver variable and set it once,
                // so that the move-in stuff gets fired only once.
                if ( !sortable.isOver ) {
                    sortable.isOver = 1;

                    // Store draggable's parent in case we need to reappend to it later.
                    draggable._parent = ui.helper.parent();

                    sortable.currentItem = ui.helper
                        .appendTo( sortable.element )
                        .data( "ui-sortable-item", true );

                    // Store helper option to later restore it
                    sortable.options._helper = sortable.options.helper;

                    sortable.options.helper = function() {
                        return ui.helper[ 0 ];
                    };

                    // Fire the start events of the sortable with our passed browser event,
                    // and our own helper (so it doesn't create a new one)
                    event.target = sortable.currentItem[ 0 ];
                    sortable._mouseCapture( event, true );
                    sortable._mouseStart( event, true, true );

                    // Because the browser event is way off the new appended portlet,
                    // modify necessary variables to reflect the changes
                    sortable.offset.click.top = draggable.offset.click.top;
                    sortable.offset.click.left = draggable.offset.click.left;
                    sortable.offset.parent.left -= draggable.offset.parent.left -
                        sortable.offset.parent.left;
                    sortable.offset.parent.top -= draggable.offset.parent.top -
                        sortable.offset.parent.top;

                    draggable._trigger( "toSortable", event );

                    // Inform draggable that the helper is in a valid drop zone,
                    // used solely in the revert option to handle "valid/invalid".
                    draggable.dropped = sortable.element;

                    // Need to refreshPositions of all sortables in the case that
                    // adding to one sortable changes the location of the other sortables (#9675)
                    $.each( draggable.sortables, function() {
                        this.refreshPositions();
                    } );

                    // Hack so receive/update callbacks work (mostly)
                    draggable.currentItem = draggable.element;
                    sortable.fromOutside = draggable;
                }

                if ( sortable.currentItem ) {
                    sortable._mouseDrag( event );

                    // Copy the sortable's position because the draggable's can potentially reflect
                    // a relative position, while sortable is always absolute, which the dragged
                    // element has now become. (#8809)
                    ui.position = sortable.position;
                }
            } else {

                // If it doesn't intersect with the sortable, and it intersected before,
                // we fake the drag stop of the sortable, but make sure it doesn't remove
                // the helper by using cancelHelperRemoval.
                if ( sortable.isOver ) {

                    sortable.isOver = 0;
                    sortable.cancelHelperRemoval = true;

                    // Calling sortable's mouseStop would trigger a revert,
                    // so revert must be temporarily false until after mouseStop is called.
                    sortable.options._revert = sortable.options.revert;
                    sortable.options.revert = false;

                    sortable._trigger( "out", event, sortable._uiHash( sortable ) );
                    sortable._mouseStop( event, true );

                    // Restore sortable behaviors that were modfied
                    // when the draggable entered the sortable area (#9481)
                    sortable.options.revert = sortable.options._revert;
                    sortable.options.helper = sortable.options._helper;

                    if ( sortable.placeholder ) {
                        sortable.placeholder.remove();
                    }

                    // Restore and recalculate the draggable's offset considering the sortable
                    // may have modified them in unexpected ways. (#8809, #10669)
                    ui.helper.appendTo( draggable._parent );
                    draggable._refreshOffsets( event );
                    ui.position = draggable._generatePosition( event, true );

                    draggable._trigger( "fromSortable", event );

                    // Inform draggable that the helper is no longer in a valid drop zone
                    draggable.dropped = false;

                    // Need to refreshPositions of all sortables just in case removing
                    // from one sortable changes the location of other sortables (#9675)
                    $.each( draggable.sortables, function() {
                        this.refreshPositions();
                    } );
                }
            }
        } );
    }
} );

$.ui.plugin.add( "draggable", "cursor", {
    start: function( event, ui, instance ) {
        var t = $( "body" ),
            o = instance.options;

        if ( t.css( "cursor" ) ) {
            o._cursor = t.css( "cursor" );
        }
        t.css( "cursor", o.cursor );
    },
    stop: function( event, ui, instance ) {
        var o = instance.options;
        if ( o._cursor ) {
            $( "body" ).css( "cursor", o._cursor );
        }
    }
} );

$.ui.plugin.add( "draggable", "opacity", {
    start: function( event, ui, instance ) {
        var t = $( ui.helper ),
            o = instance.options;
        if ( t.css( "opacity" ) ) {
            o._opacity = t.css( "opacity" );
        }
        t.css( "opacity", o.opacity );
    },
    stop: function( event, ui, instance ) {
        var o = instance.options;
        if ( o._opacity ) {
            $( ui.helper ).css( "opacity", o._opacity );
        }
    }
} );

$.ui.plugin.add( "draggable", "scroll", {
    start: function( event, ui, i ) {
        if ( !i.scrollParentNotHidden ) {
            i.scrollParentNotHidden = i.helper.scrollParent( false );
        }

        if ( i.scrollParentNotHidden[ 0 ] !== i.document[ 0 ] &&
                i.scrollParentNotHidden[ 0 ].tagName !== "HTML" ) {
            i.overflowOffset = i.scrollParentNotHidden.offset();
        }
    },
    drag: function( event, ui, i  ) {

        var o = i.options,
            scrolled = false,
            scrollParent = i.scrollParentNotHidden[ 0 ],
            document = i.document[ 0 ];

        if ( scrollParent !== document && scrollParent.tagName !== "HTML" ) {
            if ( !o.axis || o.axis !== "x" ) {
                if ( ( i.overflowOffset.top + scrollParent.offsetHeight ) - event.pageY <
                        o.scrollSensitivity ) {
                    scrollParent.scrollTop = scrolled = scrollParent.scrollTop + o.scrollSpeed;
                } else if ( event.pageY - i.overflowOffset.top < o.scrollSensitivity ) {
                    scrollParent.scrollTop = scrolled = scrollParent.scrollTop - o.scrollSpeed;
                }
            }

            if ( !o.axis || o.axis !== "y" ) {
                if ( ( i.overflowOffset.left + scrollParent.offsetWidth ) - event.pageX <
                        o.scrollSensitivity ) {
                    scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft + o.scrollSpeed;
                } else if ( event.pageX - i.overflowOffset.left < o.scrollSensitivity ) {
                    scrollParent.scrollLeft = scrolled = scrollParent.scrollLeft - o.scrollSpeed;
                }
            }

        } else {

            if ( !o.axis || o.axis !== "x" ) {
                if ( event.pageY - $( document ).scrollTop() < o.scrollSensitivity ) {
                    scrolled = $( document ).scrollTop( $( document ).scrollTop() - o.scrollSpeed );
                } else if ( $( window ).height() - ( event.pageY - $( document ).scrollTop() ) <
                        o.scrollSensitivity ) {
                    scrolled = $( document ).scrollTop( $( document ).scrollTop() + o.scrollSpeed );
                }
            }

            if ( !o.axis || o.axis !== "y" ) {
                if ( event.pageX - $( document ).scrollLeft() < o.scrollSensitivity ) {
                    scrolled = $( document ).scrollLeft(
                        $( document ).scrollLeft() - o.scrollSpeed
                    );
                } else if ( $( window ).width() - ( event.pageX - $( document ).scrollLeft() ) <
                        o.scrollSensitivity ) {
                    scrolled = $( document ).scrollLeft(
                        $( document ).scrollLeft() + o.scrollSpeed
                    );
                }
            }

        }

        if ( scrolled !== false && $.ui.ddmanager && !o.dropBehaviour ) {
            $.ui.ddmanager.prepareOffsets( i, event );
        }

    }
} );

$.ui.plugin.add( "draggable", "snap", {
    start: function( event, ui, i ) {

        var o = i.options;

        i.snapElements = [];

        $( o.snap.constructor !== String ? ( o.snap.items || ":data(ui-draggable)" ) : o.snap )
            .each( function() {
                var $t = $( this ),
                    $o = $t.offset();
                if ( this !== i.element[ 0 ] ) {
                    i.snapElements.push( {
                        item: this,
                        width: $t.outerWidth(), height: $t.outerHeight(),
                        top: $o.top, left: $o.left
                    } );
                }
            } );

    },
    drag: function( event, ui, inst ) {

        var ts, bs, ls, rs, l, r, t, b, i, first,
            o = inst.options,
            d = o.snapTolerance,
            x1 = ui.offset.left, x2 = x1 + inst.helperProportions.width,
            y1 = ui.offset.top, y2 = y1 + inst.helperProportions.height;

        for ( i = inst.snapElements.length - 1; i >= 0; i-- ) {

            l = inst.snapElements[ i ].left - inst.margins.left;
            r = l + inst.snapElements[ i ].width;
            t = inst.snapElements[ i ].top - inst.margins.top;
            b = t + inst.snapElements[ i ].height;

            if ( x2 < l - d || x1 > r + d || y2 < t - d || y1 > b + d ||
                    !$.contains( inst.snapElements[ i ].item.ownerDocument,
                    inst.snapElements[ i ].item ) ) {
                if ( inst.snapElements[ i ].snapping ) {
                    ( inst.options.snap.release &&
                        inst.options.snap.release.call(
                            inst.element,
                            event,
                            $.extend( inst._uiHash(), { snapItem: inst.snapElements[ i ].item } )
                        ) );
                }
                inst.snapElements[ i ].snapping = false;
                continue;
            }

            if ( o.snapMode !== "inner" ) {
                ts = Math.abs( t - y2 ) <= d;
                bs = Math.abs( b - y1 ) <= d;
                ls = Math.abs( l - x2 ) <= d;
                rs = Math.abs( r - x1 ) <= d;
                if ( ts ) {
                    ui.position.top = inst._convertPositionTo( "relative", {
                        top: t - inst.helperProportions.height,
                        left: 0
                    } ).top;
                }
                if ( bs ) {
                    ui.position.top = inst._convertPositionTo( "relative", {
                        top: b,
                        left: 0
                    } ).top;
                }
                if ( ls ) {
                    ui.position.left = inst._convertPositionTo( "relative", {
                        top: 0,
                        left: l - inst.helperProportions.width
                    } ).left;
                }
                if ( rs ) {
                    ui.position.left = inst._convertPositionTo( "relative", {
                        top: 0,
                        left: r
                    } ).left;
                }
            }

            first = ( ts || bs || ls || rs );

            if ( o.snapMode !== "outer" ) {
                ts = Math.abs( t - y1 ) <= d;
                bs = Math.abs( b - y2 ) <= d;
                ls = Math.abs( l - x1 ) <= d;
                rs = Math.abs( r - x2 ) <= d;
                if ( ts ) {
                    ui.position.top = inst._convertPositionTo( "relative", {
                        top: t,
                        left: 0
                    } ).top;
                }
                if ( bs ) {
                    ui.position.top = inst._convertPositionTo( "relative", {
                        top: b - inst.helperProportions.height,
                        left: 0
                    } ).top;
                }
                if ( ls ) {
                    ui.position.left = inst._convertPositionTo( "relative", {
                        top: 0,
                        left: l
                    } ).left;
                }
                if ( rs ) {
                    ui.position.left = inst._convertPositionTo( "relative", {
                        top: 0,
                        left: r - inst.helperProportions.width
                    } ).left;
                }
            }

            if ( !inst.snapElements[ i ].snapping && ( ts || bs || ls || rs || first ) ) {
                ( inst.options.snap.snap &&
                    inst.options.snap.snap.call(
                        inst.element,
                        event,
                        $.extend( inst._uiHash(), {
                            snapItem: inst.snapElements[ i ].item
                        } ) ) );
            }
            inst.snapElements[ i ].snapping = ( ts || bs || ls || rs || first );

        }

    }
} );

$.ui.plugin.add( "draggable", "stack", {
    start: function( event, ui, instance ) {
        var min,
            o = instance.options,
            group = $.makeArray( $( o.stack ) ).sort( function( a, b ) {
                return ( parseInt( $( a ).css( "zIndex" ), 10 ) || 0 ) -
                    ( parseInt( $( b ).css( "zIndex" ), 10 ) || 0 );
            } );

        if ( !group.length ) { return; }

        min = parseInt( $( group[ 0 ] ).css( "zIndex" ), 10 ) || 0;
        $( group ).each( function( i ) {
            $( this ).css( "zIndex", min + i );
        } );
        this.css( "zIndex", ( min + group.length ) );
    }
} );

$.ui.plugin.add( "draggable", "zIndex", {
    start: function( event, ui, instance ) {
        var t = $( ui.helper ),
            o = instance.options;

        if ( t.css( "zIndex" ) ) {
            o._zIndex = t.css( "zIndex" );
        }
        t.css( "zIndex", o.zIndex );
    },
    stop: function( event, ui, instance ) {
        var o = instance.options;

        if ( o._zIndex ) {
            $( ui.helper ).css( "zIndex", o._zIndex );
        }
    }
} );

var widgetsDraggable = $.ui.draggable;


/*!
 * jQuery UI Resizable 1.12.1
 * http://jqueryui.com
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

//>>label: Resizable
//>>group: Interactions
//>>description: Enables resize functionality for any element.
//>>docs: http://api.jqueryui.com/resizable/
//>>demos: http://jqueryui.com/resizable/
//>>css.structure: ../../themes/base/core.css
//>>css.structure: ../../themes/base/resizable.css
//>>css.theme: ../../themes/base/theme.css



$.widget( "ui.resizable", $.ui.mouse, {
    version: "1.12.1",
    widgetEventPrefix: "resize",
    options: {
        alsoResize: false,
        animate: false,
        animateDuration: "slow",
        animateEasing: "swing",
        aspectRatio: false,
        autoHide: false,
        classes: {
            "ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
        },
        containment: false,
        ghost: false,
        grid: false,
        handles: "e,s,se",
        helper: false,
        maxHeight: null,
        maxWidth: null,
        minHeight: 10,
        minWidth: 10,

        // See #7960
        zIndex: 90,

        // Callbacks
        resize: null,
        start: null,
        stop: null
    },

    _num: function( value ) {
        return parseFloat( value ) || 0;
    },

    _isNumber: function( value ) {
        return !isNaN( parseFloat( value ) );
    },

    _hasScroll: function( el, a ) {

        if ( $( el ).css( "overflow" ) === "hidden" ) {
            return false;
        }

        var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
            has = false;

        if ( el[ scroll ] > 0 ) {
            return true;
        }

        // TODO: determine which cases actually cause this to happen
        // if the element doesn't have the scroll set, see if it's possible to
        // set the scroll
        el[ scroll ] = 1;
        has = ( el[ scroll ] > 0 );
        el[ scroll ] = 0;
        return has;
    },

    _create: function() {

        var margins,
            o = this.options,
            that = this;
        this._addClass( "ui-resizable" );

        $.extend( this, {
            _aspectRatio: !!( o.aspectRatio ),
            aspectRatio: o.aspectRatio,
            originalElement: this.element,
            _proportionallyResizeElements: [],
            _helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
        } );

        // Wrap the element if it cannot hold child nodes
        if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {

            this.element.wrap(
                $( "<div class='ui-wrapper' style='overflow: hidden;'></div>" ).css( {
                    position: this.element.css( "position" ),
                    width: this.element.outerWidth(),
                    height: this.element.outerHeight(),
                    top: this.element.css( "top" ),
                    left: this.element.css( "left" )
                } )
            );

            this.element = this.element.parent().data(
                "ui-resizable", this.element.resizable( "instance" )
            );

            this.elementIsWrapper = true;

            margins = {
                marginTop: this.originalElement.css( "marginTop" ),
                marginRight: this.originalElement.css( "marginRight" ),
                marginBottom: this.originalElement.css( "marginBottom" ),
                marginLeft: this.originalElement.css( "marginLeft" )
            };

            this.element.css( margins );
            this.originalElement.css( "margin", 0 );

            // support: Safari
            // Prevent Safari textarea resize
            this.originalResizeStyle = this.originalElement.css( "resize" );
            this.originalElement.css( "resize", "none" );

            this._proportionallyResizeElements.push( this.originalElement.css( {
                position: "static",
                zoom: 1,
                display: "block"
            } ) );

            // Support: IE9
            // avoid IE jump (hard set the margin)
            this.originalElement.css( margins );

            this._proportionallyResize();
        }

        this._setupHandles();

        if ( o.autoHide ) {
            $( this.element )
                .on( "mouseenter", function() {
                    if ( o.disabled ) {
                        return;
                    }
                    that._removeClass( "ui-resizable-autohide" );
                    that._handles.show();
                } )
                .on( "mouseleave", function() {
                    if ( o.disabled ) {
                        return;
                    }
                    if ( !that.resizing ) {
                        that._addClass( "ui-resizable-autohide" );
                        that._handles.hide();
                    }
                } );
        }

        this._mouseInit();
    },

    _destroy: function() {

        this._mouseDestroy();

        var wrapper,
            _destroy = function( exp ) {
                $( exp )
                    .removeData( "resizable" )
                    .removeData( "ui-resizable" )
                    .off( ".resizable" )
                    .find( ".ui-resizable-handle" )
                        .remove();
            };

        // TODO: Unwrap at same DOM position
        if ( this.elementIsWrapper ) {
            _destroy( this.element );
            wrapper = this.element;
            this.originalElement.css( {
                position: wrapper.css( "position" ),
                width: wrapper.outerWidth(),
                height: wrapper.outerHeight(),
                top: wrapper.css( "top" ),
                left: wrapper.css( "left" )
            } ).insertAfter( wrapper );
            wrapper.remove();
        }

        this.originalElement.css( "resize", this.originalResizeStyle );
        _destroy( this.originalElement );

        return this;
    },

    _setOption: function( key, value ) {
        this._super( key, value );

        switch ( key ) {
        case "handles":
            this._removeHandles();
            this._setupHandles();
            break;
        default:
            break;
        }
    },

    _setupHandles: function() {
        var o = this.options, handle, i, n, hname, axis, that = this;
        this.handles = o.handles ||
            ( !$( ".ui-resizable-handle", this.element ).length ?
                "e,s,se" : {
                    n: ".ui-resizable-n",
                    e: ".ui-resizable-e",
                    s: ".ui-resizable-s",
                    w: ".ui-resizable-w",
                    se: ".ui-resizable-se",
                    sw: ".ui-resizable-sw",
                    ne: ".ui-resizable-ne",
                    nw: ".ui-resizable-nw"
                } );

        this._handles = $();
        if ( this.handles.constructor === String ) {

            if ( this.handles === "all" ) {
                this.handles = "n,e,s,w,se,sw,ne,nw";
            }

            n = this.handles.split( "," );
            this.handles = {};

            for ( i = 0; i < n.length; i++ ) {

                handle = $.trim( n[ i ] );
                hname = "ui-resizable-" + handle;
                axis = $( "<div>" );
                this._addClass( axis, "ui-resizable-handle " + hname );

                axis.css( { zIndex: o.zIndex } );

                this.handles[ handle ] = ".ui-resizable-" + handle;
                this.element.append( axis );
            }

        }

        this._renderAxis = function( target ) {

            var i, axis, padPos, padWrapper;

            target = target || this.element;

            for ( i in this.handles ) {

                if ( this.handles[ i ].constructor === String ) {
                    this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
                } else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
                    this.handles[ i ] = $( this.handles[ i ] );
                    this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
                }

                if ( this.elementIsWrapper &&
                        this.originalElement[ 0 ]
                            .nodeName
                            .match( /^(textarea|input|select|button)$/i ) ) {
                    axis = $( this.handles[ i ], this.element );

                    padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
                        axis.outerHeight() :
                        axis.outerWidth();

                    padPos = [ "padding",
                        /ne|nw|n/.test( i ) ? "Top" :
                        /se|sw|s/.test( i ) ? "Bottom" :
                        /^e$/.test( i ) ? "Right" : "Left" ].join( "" );

                    target.css( padPos, padWrapper );

                    this._proportionallyResize();
                }

                this._handles = this._handles.add( this.handles[ i ] );
            }
        };

        // TODO: make renderAxis a prototype function
        this._renderAxis( this.element );

        this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
        this._handles.disableSelection();

        this._handles.on( "mouseover", function() {
            if ( !that.resizing ) {
                if ( this.className ) {
                    axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
                }
                that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
            }
        } );

        if ( o.autoHide ) {
            this._handles.hide();
            this._addClass( "ui-resizable-autohide" );
        }
    },

    _removeHandles: function() {
        this._handles.remove();
    },

    _mouseCapture: function( event ) {
        var i, handle,
            capture = false;

        for ( i in this.handles ) {
            handle = $( this.handles[ i ] )[ 0 ];
            if ( handle === event.target || $.contains( handle, event.target ) ) {
                capture = true;
            }
        }

        return !this.options.disabled && capture;
    },

    _mouseStart: function( event ) {

        var curleft, curtop, cursor,
            o = this.options,
            el = this.element;

        this.resizing = true;

        this._renderProxy();

        curleft = this._num( this.helper.css( "left" ) );
        curtop = this._num( this.helper.css( "top" ) );

        if ( o.containment ) {
            curleft += $( o.containment ).scrollLeft() || 0;
            curtop += $( o.containment ).scrollTop() || 0;
        }

        this.offset = this.helper.offset();
        this.position = { left: curleft, top: curtop };

        this.size = this._helper ? {
                width: this.helper.width(),
                height: this.helper.height()
            } : {
                width: el.width(),
                height: el.height()
            };

        this.originalSize = this._helper ? {
                width: el.outerWidth(),
                height: el.outerHeight()
            } : {
                width: el.width(),
                height: el.height()
            };

        this.sizeDiff = {
            width: el.outerWidth() - el.width(),
            height: el.outerHeight() - el.height()
        };

        this.originalPosition = { left: curleft, top: curtop };
        this.originalMousePosition = { left: event.pageX, top: event.pageY };

        this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
            o.aspectRatio :
            ( ( this.originalSize.width / this.originalSize.height ) || 1 );

        cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
        $( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );

        this._addClass( "ui-resizable-resizing" );
        this._propagate( "start", event );
        return true;
    },

    _mouseDrag: function( event ) {

        var data, props,
            smp = this.originalMousePosition,
            a = this.axis,
            dx = ( event.pageX - smp.left ) || 0,
            dy = ( event.pageY - smp.top ) || 0,
            trigger = this._change[ a ];

        this._updatePrevProperties();

        if ( !trigger ) {
            return false;
        }

        data = trigger.apply( this, [ event, dx, dy ] );

        this._updateVirtualBoundaries( event.shiftKey );
        if ( this._aspectRatio || event.shiftKey ) {
            data = this._updateRatio( data, event );
        }

        data = this._respectSize( data, event );

        this._updateCache( data );

        this._propagate( "resize", event );

        props = this._applyChanges();

        if ( !this._helper && this._proportionallyResizeElements.length ) {
            this._proportionallyResize();
        }

        if ( !$.isEmptyObject( props ) ) {
            this._updatePrevProperties();
            this._trigger( "resize", event, this.ui() );
            this._applyChanges();
        }

        return false;
    },

    _mouseStop: function( event ) {

        this.resizing = false;
        var pr, ista, soffseth, soffsetw, s, left, top,
            o = this.options, that = this;

        if ( this._helper ) {

            pr = this._proportionallyResizeElements;
            ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
            soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
            soffsetw = ista ? 0 : that.sizeDiff.width;

            s = {
                width: ( that.helper.width()  - soffsetw ),
                height: ( that.helper.height() - soffseth )
            };
            left = ( parseFloat( that.element.css( "left" ) ) +
                ( that.position.left - that.originalPosition.left ) ) || null;
            top = ( parseFloat( that.element.css( "top" ) ) +
                ( that.position.top - that.originalPosition.top ) ) || null;

            if ( !o.animate ) {
                this.element.css( $.extend( s, { top: top, left: left } ) );
            }

            that.helper.height( that.size.height );
            that.helper.width( that.size.width );

            if ( this._helper && !o.animate ) {
                this._proportionallyResize();
            }
        }

        $( "body" ).css( "cursor", "auto" );

        this._removeClass( "ui-resizable-resizing" );

        this._propagate( "stop", event );

        if ( this._helper ) {
            this.helper.remove();
        }

        return false;

    },

    _updatePrevProperties: function() {
        this.prevPosition = {
            top: this.position.top,
            left: this.position.left
        };
        this.prevSize = {
            width: this.size.width,
            height: this.size.height
        };
    },

    _applyChanges: function() {
        var props = {};

        if ( this.position.top !== this.prevPosition.top ) {
            props.top = this.position.top + "px";
        }
        if ( this.position.left !== this.prevPosition.left ) {
            props.left = this.position.left + "px";
        }
        if ( this.size.width !== this.prevSize.width ) {
            props.width = this.size.width + "px";
        }
        if ( this.size.height !== this.prevSize.height ) {
            props.height = this.size.height + "px";
        }

        this.helper.css( props );

        return props;
    },

    _updateVirtualBoundaries: function( forceAspectRatio ) {
        var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
            o = this.options;

        b = {
            minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
            maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
            minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
            maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
        };

        if ( this._aspectRatio || forceAspectRatio ) {
            pMinWidth = b.minHeight * this.aspectRatio;
            pMinHeight = b.minWidth / this.aspectRatio;
            pMaxWidth = b.maxHeight * this.aspectRatio;
            pMaxHeight = b.maxWidth / this.aspectRatio;

            if ( pMinWidth > b.minWidth ) {
                b.minWidth = pMinWidth;
            }
            if ( pMinHeight > b.minHeight ) {
                b.minHeight = pMinHeight;
            }
            if ( pMaxWidth < b.maxWidth ) {
                b.maxWidth = pMaxWidth;
            }
            if ( pMaxHeight < b.maxHeight ) {
                b.maxHeight = pMaxHeight;
            }
        }
        this._vBoundaries = b;
    },

    _updateCache: function( data ) {
        this.offset = this.helper.offset();
        if ( this._isNumber( data.left ) ) {
            this.position.left = data.left;
        }
        if ( this._isNumber( data.top ) ) {
            this.position.top = data.top;
        }
        if ( this._isNumber( data.height ) ) {
            this.size.height = data.height;
        }
        if ( this._isNumber( data.width ) ) {
            this.size.width = data.width;
        }
    },

    _updateRatio: function( data ) {

        var cpos = this.position,
            csize = this.size,
            a = this.axis;

        if ( this._isNumber( data.height ) ) {
            data.width = ( data.height * this.aspectRatio );
        } else if ( this._isNumber( data.width ) ) {
            data.height = ( data.width / this.aspectRatio );
        }

        if ( a === "sw" ) {
            data.left = cpos.left + ( csize.width - data.width );
            data.top = null;
        }
        if ( a === "nw" ) {
            data.top = cpos.top + ( csize.height - data.height );
            data.left = cpos.left + ( csize.width - data.width );
        }

        return data;
    },

    _respectSize: function( data ) {

        var o = this._vBoundaries,
            a = this.axis,
            ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
            ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
            isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
            isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
            dw = this.originalPosition.left + this.originalSize.width,
            dh = this.originalPosition.top + this.originalSize.height,
            cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
        if ( isminw ) {
            data.width = o.minWidth;
        }
        if ( isminh ) {
            data.height = o.minHeight;
        }
        if ( ismaxw ) {
            data.width = o.maxWidth;
        }
        if ( ismaxh ) {
            data.height = o.maxHeight;
        }

        if ( isminw && cw ) {
            data.left = dw - o.minWidth;
        }
        if ( ismaxw && cw ) {
            data.left = dw - o.maxWidth;
        }
        if ( isminh && ch ) {
            data.top = dh - o.minHeight;
        }
        if ( ismaxh && ch ) {
            data.top = dh - o.maxHeight;
        }

        // Fixing jump error on top/left - bug #2330
        if ( !data.width && !data.height && !data.left && data.top ) {
            data.top = null;
        } else if ( !data.width && !data.height && !data.top && data.left ) {
            data.left = null;
        }

        return data;
    },

    _getPaddingPlusBorderDimensions: function( element ) {
        var i = 0,
            widths = [],
            borders = [
                element.css( "borderTopWidth" ),
                element.css( "borderRightWidth" ),
                element.css( "borderBottomWidth" ),
                element.css( "borderLeftWidth" )
            ],
            paddings = [
                element.css( "paddingTop" ),
                element.css( "paddingRight" ),
                element.css( "paddingBottom" ),
                element.css( "paddingLeft" )
            ];

        for ( ; i < 4; i++ ) {
            widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
            widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
        }

        return {
            height: widths[ 0 ] + widths[ 2 ],
            width: widths[ 1 ] + widths[ 3 ]
        };
    },

    _proportionallyResize: function() {

        if ( !this._proportionallyResizeElements.length ) {
            return;
        }

        var prel,
            i = 0,
            element = this.helper || this.element;

        for ( ; i < this._proportionallyResizeElements.length; i++ ) {

            prel = this._proportionallyResizeElements[ i ];

            // TODO: Seems like a bug to cache this.outerDimensions
            // considering that we are in a loop.
            if ( !this.outerDimensions ) {
                this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
            }

            prel.css( {
                height: ( element.height() - this.outerDimensions.height ) || 0,
                width: ( element.width() - this.outerDimensions.width ) || 0
            } );

        }

    },

    _renderProxy: function() {

        var el = this.element, o = this.options;
        this.elementOffset = el.offset();

        if ( this._helper ) {

            this.helper = this.helper || $( "<div style='overflow:hidden;'></div>" );

            this._addClass( this.helper, this._helper );
            this.helper.css( {
                width: this.element.outerWidth(),
                height: this.element.outerHeight(),
                position: "absolute",
                left: this.elementOffset.left + "px",
                top: this.elementOffset.top + "px",
                zIndex: ++o.zIndex //TODO: Don't modify option
            } );

            this.helper
                .appendTo( "body" )
                .disableSelection();

        } else {
            this.helper = this.element;
        }

    },

    _change: {
        e: function( event, dx ) {
            return { width: this.originalSize.width + dx };
        },
        w: function( event, dx ) {
            var cs = this.originalSize, sp = this.originalPosition;
            return { left: sp.left + dx, width: cs.width - dx };
        },
        n: function( event, dx, dy ) {
            var cs = this.originalSize, sp = this.originalPosition;
            return { top: sp.top + dy, height: cs.height - dy };
        },
        s: function( event, dx, dy ) {
            return { height: this.originalSize.height + dy };
        },
        se: function( event, dx, dy ) {
            return $.extend( this._change.s.apply( this, arguments ),
                this._change.e.apply( this, [ event, dx, dy ] ) );
        },
        sw: function( event, dx, dy ) {
            return $.extend( this._change.s.apply( this, arguments ),
                this._change.w.apply( this, [ event, dx, dy ] ) );
        },
        ne: function( event, dx, dy ) {
            return $.extend( this._change.n.apply( this, arguments ),
                this._change.e.apply( this, [ event, dx, dy ] ) );
        },
        nw: function( event, dx, dy ) {
            return $.extend( this._change.n.apply( this, arguments ),
                this._change.w.apply( this, [ event, dx, dy ] ) );
        }
    },

    _propagate: function( n, event ) {
        $.ui.plugin.call( this, n, [ event, this.ui() ] );
        ( n !== "resize" && this._trigger( n, event, this.ui() ) );
    },

    plugins: {},

    ui: function() {
        return {
            originalElement: this.originalElement,
            element: this.element,
            helper: this.helper,
            position: this.position,
            size: this.size,
            originalSize: this.originalSize,
            originalPosition: this.originalPosition
        };
    }

} );

/*
 * Resizable Extensions
 */

$.ui.plugin.add( "resizable", "animate", {

    stop: function( event ) {
        var that = $( this ).resizable( "instance" ),
            o = that.options,
            pr = that._proportionallyResizeElements,
            ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
            soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
            soffsetw = ista ? 0 : that.sizeDiff.width,
            style = {
                width: ( that.size.width - soffsetw ),
                height: ( that.size.height - soffseth )
            },
            left = ( parseFloat( that.element.css( "left" ) ) +
                ( that.position.left - that.originalPosition.left ) ) || null,
            top = ( parseFloat( that.element.css( "top" ) ) +
                ( that.position.top - that.originalPosition.top ) ) || null;

        that.element.animate(
            $.extend( style, top && left ? { top: top, left: left } : {} ), {
                duration: o.animateDuration,
                easing: o.animateEasing,
                step: function() {

                    var data = {
                        width: parseFloat( that.element.css( "width" ) ),
                        height: parseFloat( that.element.css( "height" ) ),
                        top: parseFloat( that.element.css( "top" ) ),
                        left: parseFloat( that.element.css( "left" ) )
                    };

                    if ( pr && pr.length ) {
                        $( pr[ 0 ] ).css( { width: data.width, height: data.height } );
                    }

                    // Propagating resize, and updating values for each animation step
                    that._updateCache( data );
                    that._propagate( "resize", event );

                }
            }
        );
    }

} );

$.ui.plugin.add( "resizable", "containment", {

    start: function() {
        var element, p, co, ch, cw, width, height,
            that = $( this ).resizable( "instance" ),
            o = that.options,
            el = that.element,
            oc = o.containment,
            ce = ( oc instanceof $ ) ?
                oc.get( 0 ) :
                ( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;

        if ( !ce ) {
            return;
        }

        that.containerElement = $( ce );

        if ( /document/.test( oc ) || oc === document ) {
            that.containerOffset = {
                left: 0,
                top: 0
            };
            that.containerPosition = {
                left: 0,
                top: 0
            };

            that.parentData = {
                element: $( document ),
                left: 0,
                top: 0,
                width: $( document ).width(),
                height: $( document ).height() || document.body.parentNode.scrollHeight
            };
        } else {
            element = $( ce );
            p = [];
            $( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
                p[ i ] = that._num( element.css( "padding" + name ) );
            } );

            that.containerOffset = element.offset();
            that.containerPosition = element.position();
            that.containerSize = {
                height: ( element.innerHeight() - p[ 3 ] ),
                width: ( element.innerWidth() - p[ 1 ] )
            };

            co = that.containerOffset;
            ch = that.containerSize.height;
            cw = that.containerSize.width;
            width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
            height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;

            that.parentData = {
                element: ce,
                left: co.left,
                top: co.top,
                width: width,
                height: height
            };
        }
    },

    resize: function( event ) {
        var woset, hoset, isParent, isOffsetRelative,
            that = $( this ).resizable( "instance" ),
            o = that.options,
            co = that.containerOffset,
            cp = that.position,
            pRatio = that._aspectRatio || event.shiftKey,
            cop = {
                top: 0,
                left: 0
            },
            ce = that.containerElement,
            continueResize = true;

        if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
            cop = co;
        }

        if ( cp.left < ( that._helper ? co.left : 0 ) ) {
            that.size.width = that.size.width +
                ( that._helper ?
                    ( that.position.left - co.left ) :
                    ( that.position.left - cop.left ) );

            if ( pRatio ) {
                that.size.height = that.size.width / that.aspectRatio;
                continueResize = false;
            }
            that.position.left = o.helper ? co.left : 0;
        }

        if ( cp.top < ( that._helper ? co.top : 0 ) ) {
            that.size.height = that.size.height +
                ( that._helper ?
                    ( that.position.top - co.top ) :
                    that.position.top );

            if ( pRatio ) {
                that.size.width = that.size.height * that.aspectRatio;
                continueResize = false;
            }
            that.position.top = that._helper ? co.top : 0;
        }

        isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
        isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );

        if ( isParent && isOffsetRelative ) {
            that.offset.left = that.parentData.left + that.position.left;
            that.offset.top = that.parentData.top + that.position.top;
        } else {
            that.offset.left = that.element.offset().left;
            that.offset.top = that.element.offset().top;
        }

        woset = Math.abs( that.sizeDiff.width +
            ( that._helper ?
                that.offset.left - cop.left :
                ( that.offset.left - co.left ) ) );

        hoset = Math.abs( that.sizeDiff.height +
            ( that._helper ?
                that.offset.top - cop.top :
                ( that.offset.top - co.top ) ) );

        if ( woset + that.size.width >= that.parentData.width ) {
            that.size.width = that.parentData.width - woset;
            if ( pRatio ) {
                that.size.height = that.size.width / that.aspectRatio;
                continueResize = false;
            }
        }

        if ( hoset + that.size.height >= that.parentData.height ) {
            that.size.height = that.parentData.height - hoset;
            if ( pRatio ) {
                that.size.width = that.size.height * that.aspectRatio;
                continueResize = false;
            }
        }

        if ( !continueResize ) {
            that.position.left = that.prevPosition.left;
            that.position.top = that.prevPosition.top;
            that.size.width = that.prevSize.width;
            that.size.height = that.prevSize.height;
        }
    },

    stop: function() {
        var that = $( this ).resizable( "instance" ),
            o = that.options,
            co = that.containerOffset,
            cop = that.containerPosition,
            ce = that.containerElement,
            helper = $( that.helper ),
            ho = helper.offset(),
            w = helper.outerWidth() - that.sizeDiff.width,
            h = helper.outerHeight() - that.sizeDiff.height;

        if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
            $( this ).css( {
                left: ho.left - cop.left - co.left,
                width: w,
                height: h
            } );
        }

        if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
            $( this ).css( {
                left: ho.left - cop.left - co.left,
                width: w,
                height: h
            } );
        }
    }
} );

$.ui.plugin.add( "resizable", "alsoResize", {

    start: function() {
        var that = $( this ).resizable( "instance" ),
            o = that.options;

        $( o.alsoResize ).each( function() {
            var el = $( this );
            el.data( "ui-resizable-alsoresize", {
                width: parseFloat( el.width() ), height: parseFloat( el.height() ),
                left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
            } );
        } );
    },

    resize: function( event, ui ) {
        var that = $( this ).resizable( "instance" ),
            o = that.options,
            os = that.originalSize,
            op = that.originalPosition,
            delta = {
                height: ( that.size.height - os.height ) || 0,
                width: ( that.size.width - os.width ) || 0,
                top: ( that.position.top - op.top ) || 0,
                left: ( that.position.left - op.left ) || 0
            };

            $( o.alsoResize ).each( function() {
                var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
                    css = el.parents( ui.originalElement[ 0 ] ).length ?
                            [ "width", "height" ] :
                            [ "width", "height", "top", "left" ];

                $.each( css, function( i, prop ) {
                    var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
                    if ( sum && sum >= 0 ) {
                        style[ prop ] = sum || null;
                    }
                } );

                el.css( style );
            } );
    },

    stop: function() {
        $( this ).removeData( "ui-resizable-alsoresize" );
    }
} );

$.ui.plugin.add( "resizable", "ghost", {

    start: function() {

        var that = $( this ).resizable( "instance" ), cs = that.size;

        that.ghost = that.originalElement.clone();
        that.ghost.css( {
            opacity: 0.25,
            display: "block",
            position: "relative",
            height: cs.height,
            width: cs.width,
            margin: 0,
            left: 0,
            top: 0
        } );

        that._addClass( that.ghost, "ui-resizable-ghost" );

        // DEPRECATED
        // TODO: remove after 1.12
        if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) {

            // Ghost option
            that.ghost.addClass( this.options.ghost );
        }

        that.ghost.appendTo( that.helper );

    },

    resize: function() {
        var that = $( this ).resizable( "instance" );
        if ( that.ghost ) {
            that.ghost.css( {
                position: "relative",
                height: that.size.height,
                width: that.size.width
            } );
        }
    },

    stop: function() {
        var that = $( this ).resizable( "instance" );
        if ( that.ghost && that.helper ) {
            that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
        }
    }

} );

$.ui.plugin.add( "resizable", "grid", {

    resize: function() {
        var outerDimensions,
            that = $( this ).resizable( "instance" ),
            o = that.options,
            cs = that.size,
            os = that.originalSize,
            op = that.originalPosition,
            a = that.axis,
            grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
            gridX = ( grid[ 0 ] || 1 ),
            gridY = ( grid[ 1 ] || 1 ),
            ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
            oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
            newWidth = os.width + ox,
            newHeight = os.height + oy,
            isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
            isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
            isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
            isMinHeight = o.minHeight && ( o.minHeight > newHeight );

        o.grid = grid;

        if ( isMinWidth ) {
            newWidth += gridX;
        }
        if ( isMinHeight ) {
            newHeight += gridY;
        }
        if ( isMaxWidth ) {
            newWidth -= gridX;
        }
        if ( isMaxHeight ) {
            newHeight -= gridY;
        }

        if ( /^(se|s|e)$/.test( a ) ) {
            that.size.width = newWidth;
            that.size.height = newHeight;
        } else if ( /^(ne)$/.test( a ) ) {
            that.size.width = newWidth;
            that.size.height = newHeight;
            that.position.top = op.top - oy;
        } else if ( /^(sw)$/.test( a ) ) {
            that.size.width = newWidth;
            that.size.height = newHeight;
            that.position.left = op.left - ox;
        } else {
            if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
                outerDimensions = that._getPaddingPlusBorderDimensions( this );
            }

            if ( newHeight - gridY > 0 ) {
                that.size.height = newHeight;
                that.position.top = op.top - oy;
            } else {
                newHeight = gridY - outerDimensions.height;
                that.size.height = newHeight;
                that.position.top = op.top + os.height - newHeight;
            }
            if ( newWidth - gridX > 0 ) {
                that.size.width = newWidth;
                that.position.left = op.left - ox;
            } else {
                newWidth = gridX - outerDimensions.width;
                that.size.width = newWidth;
                that.position.left = op.left + os.width - newWidth;
            }
        }
    }

} );

var widgetsResizable = $.ui.resizable;


}));