/*! jQuery UI - v1.12.1 - 2019-11-20
* http://jqueryui.com
* Includes: widget.js, data.js, disable-selection.js, scroll-parent.js, widgets/draggable.js, widgets/droppable.js, widgets/resizable.js, widgets/mouse.js
* Copyright jQuery Foundation and other contributors; Licensed MIT @preserve*/

(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;


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

//>>label: :data Selector
//>>group: Core
//>>description: Selects elements which have data stored under the specified key.
//>>docs: http://api.jqueryui.com/data-selector/


var data = $.extend( $.expr[ ":" ], {
  data: $.expr.createPseudo ?
    $.expr.createPseudo( function( dataName ) {
      return function( elem ) {
        return !!$.data( elem, dataName );
      };
    } ) :

    // Support: jQuery <1.8
    function( elem, i, match ) {
      return !!$.data( elem, match[ 3 ] );
    }
} );

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

//>>label: disableSelection
//>>group: Core
//>>description: Disable selection of text content within the set of matched elements.
//>>docs: http://api.jqueryui.com/disableSelection/

// This file is deprecated


var disableSelection = $.fn.extend( {
  disableSelection: ( function() {
    var eventType = "onselectstart" in document.createElement( "div" ) ?
      "selectstart" :
      "mousedown";

    return function() {
      return this.on( eventType + ".ui-disableSelection", function( event ) {
        event.preventDefault();
      } );
    };
  } )(),

  enableSelection: function() {
    return this.off( ".ui-disableSelection" );
  }
} );


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

//>>label: scrollParent
//>>group: Core
//>>description: Get the closest ancestor element that is scrollable.
//>>docs: http://api.jqueryui.com/scrollParent/



var scrollParent = $.fn.scrollParent = function( includeHidden ) {
  var position = this.css( "position" ),
    excludeStaticParent = position === "absolute",
    overflowRegex = includeHidden ? /(auto|scroll|hidden)/ : /(auto|scroll)/,
    scrollParent = this.parents().filter( function() {
      var parent = $( this );
      if ( excludeStaticParent && parent.css( "position" ) === "static" ) {
        return false;
      }
      return overflowRegex.test( parent.css( "overflow" ) + parent.css( "overflow-y" ) +
        parent.css( "overflow-x" ) );
    } ).eq( 0 );

  return position === "fixed" || !scrollParent.length ?
    $( this[ 0 ].ownerDocument || document ) :
    scrollParent;
};




// 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 safeActiveElement = $.ui.safeActiveElement = function( document ) {
  var activeElement;

  // Support: IE 9 only
  // IE9 throws an "Unspecified error" accessing document.activeElement from an <iframe>
  try {
    activeElement = document.activeElement;
  } catch ( error ) {
    activeElement = document.body;
  }

  // Support: IE 9 - 11 only
  // IE may return null instead of an element
  // Interestingly, this only seems to occur when NOT in an iframe
  if ( !activeElement ) {
    activeElement = document.body;
  }

  // Support: IE 11 only
  // IE11 returns a seemingly empty object in some cases when accessing
  // document.activeElement from an <iframe>
  if ( !activeElement.nodeName ) {
    activeElement = document.body;
  }

  return activeElement;
};



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 Droppable 1.12.1
 * http://jqueryui.com
 *
 * Copyright jQuery Foundation and other contributors
 * Released under the MIT license.
 * http://jquery.org/license
 */

//>>label: Droppable
//>>group: Interactions
//>>description: Enables drop targets for draggable elements.
//>>docs: http://api.jqueryui.com/droppable/
//>>demos: http://jqueryui.com/droppable/



$.widget( "ui.droppable", {
  version: "1.12.1",
  widgetEventPrefix: "drop",
  options: {
    accept: "*",
    addClasses: true,
    greedy: false,
    scope: "default",
    tolerance: "intersect",

    // Callbacks
    activate: null,
    deactivate: null,
    drop: null,
    out: null,
    over: null
  },
  _create: function() {

    var proportions,
      o = this.options,
      accept = o.accept;

    this.isover = false;
    this.isout = true;

    this.accept = $.isFunction( accept ) ? accept : function( d ) {
      return d.is( accept );
    };

    this.proportions = function( /* valueToWrite */ ) {
      if ( arguments.length ) {

        // Store the droppable's proportions
        proportions = arguments[ 0 ];
      } else {

        // Retrieve or derive the droppable's proportions
        return proportions ?
          proportions :
          proportions = {
            width: this.element[ 0 ].offsetWidth,
            height: this.element[ 0 ].offsetHeight
          };
      }
    };

    this._addToManager( o.scope );

    o.addClasses && this._addClass( "ui-droppable" );

  },

  _addToManager: function( scope ) {

    // Add the reference and positions to the manager
    $.ui.ddmanager.droppables[ scope ] = $.ui.ddmanager.droppables[ scope ] || [];
    $.ui.ddmanager.droppables[ scope ].push( this );
  },

  _splice: function( drop ) {
    var i = 0;
    for ( ; i < drop.length; i++ ) {
      if ( drop[ i ] === this ) {
        drop.splice( i, 1 );
      }
    }
  },

  _destroy: function() {
    var drop = $.ui.ddmanager.droppables[ this.options.scope ];

    this._splice( drop );
  },

  _setOption: function( key, value ) {

    if ( key === "accept" ) {
      this.accept = $.isFunction( value ) ? value : function( d ) {
        return d.is( value );
      };
    } else if ( key === "scope" ) {
      var drop = $.ui.ddmanager.droppables[ this.options.scope ];

      this._splice( drop );
      this._addToManager( value );
    }

    this._super( key, value );
  },

  _activate: function( event ) {
    var draggable = $.ui.ddmanager.current;

    this._addActiveClass();
    if ( draggable ) {
      this._trigger( "activate", event, this.ui( draggable ) );
    }
  },

  _deactivate: function( event ) {
    var draggable = $.ui.ddmanager.current;

    this._removeActiveClass();
    if ( draggable ) {
      this._trigger( "deactivate", event, this.ui( draggable ) );
    }
  },

  _over: function( event ) {

    var draggable = $.ui.ddmanager.current;

    // Bail if draggable and droppable are same element
    if ( !draggable || ( draggable.currentItem ||
        draggable.element )[ 0 ] === this.element[ 0 ] ) {
      return;
    }

    if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
        draggable.element ) ) ) {
      this._addHoverClass();
      this._trigger( "over", event, this.ui( draggable ) );
    }

  },

  _out: function( event ) {

    var draggable = $.ui.ddmanager.current;

    // Bail if draggable and droppable are same element
    if ( !draggable || ( draggable.currentItem ||
        draggable.element )[ 0 ] === this.element[ 0 ] ) {
      return;
    }

    if ( this.accept.call( this.element[ 0 ], ( draggable.currentItem ||
        draggable.element ) ) ) {
      this._removeHoverClass();
      this._trigger( "out", event, this.ui( draggable ) );
    }

  },

  _drop: function( event, custom ) {

    var draggable = custom || $.ui.ddmanager.current,
      childrenIntersection = false;

    // Bail if draggable and droppable are same element
    if ( !draggable || ( draggable.currentItem ||
        draggable.element )[ 0 ] === this.element[ 0 ] ) {
      return false;
    }

    this.element
      .find( ":data(ui-droppable)" )
      .not( ".ui-draggable-dragging" )
      .each( function() {
        var inst = $( this ).droppable( "instance" );
        if (
          inst.options.greedy &&
          !inst.options.disabled &&
          inst.options.scope === draggable.options.scope &&
          inst.accept.call(
            inst.element[ 0 ], ( draggable.currentItem || draggable.element )
          ) &&
          intersect(
            draggable,
            $.extend( inst, { offset: inst.element.offset() } ),
            inst.options.tolerance, event
          )
        ) {
          childrenIntersection = true;
          return false; }
      } );
    if ( childrenIntersection ) {
      return false;
    }

    if ( this.accept.call( this.element[ 0 ],
        ( draggable.currentItem || draggable.element ) ) ) {
      this._removeActiveClass();
      this._removeHoverClass();

      this._trigger( "drop", event, this.ui( draggable ) );
      return this.element;
    }

    return false;

  },

  ui: function( c ) {
    return {
      draggable: ( c.currentItem || c.element ),
      helper: c.helper,
      position: c.position,
      offset: c.positionAbs
    };
  },

  // Extension points just to make backcompat sane and avoid duplicating logic
  // TODO: Remove in 1.13 along with call to it below
  _addHoverClass: function() {
    this._addClass( "ui-droppable-hover" );
  },

  _removeHoverClass: function() {
    this._removeClass( "ui-droppable-hover" );
  },

  _addActiveClass: function() {
    this._addClass( "ui-droppable-active" );
  },

  _removeActiveClass: function() {
    this._removeClass( "ui-droppable-active" );
  }
} );

var intersect = $.ui.intersect = ( function() {
  function isOverAxis( x, reference, size ) {
    return ( x >= reference ) && ( x < ( reference + size ) );
  }

  return function( draggable, droppable, toleranceMode, event ) {

    if ( !droppable.offset ) {
      return false;
    }

    var x1 = ( draggable.positionAbs ||
        draggable.position.absolute ).left + draggable.margins.left,
      y1 = ( draggable.positionAbs ||
        draggable.position.absolute ).top + draggable.margins.top,
      x2 = x1 + draggable.helperProportions.width,
      y2 = y1 + draggable.helperProportions.height,
      l = droppable.offset.left,
      t = droppable.offset.top,
      r = l + droppable.proportions().width,
      b = t + droppable.proportions().height;

    switch ( toleranceMode ) {
    case "fit":
      return ( l <= x1 && x2 <= r && t <= y1 && y2 <= b );
    case "intersect":
      return ( l < x1 + ( draggable.helperProportions.width / 2 ) && // Right Half
        x2 - ( draggable.helperProportions.width / 2 ) < r && // Left Half
        t < y1 + ( draggable.helperProportions.height / 2 ) && // Bottom Half
        y2 - ( draggable.helperProportions.height / 2 ) < b ); // Top Half
    case "pointer":
      return isOverAxis( event.pageY, t, droppable.proportions().height ) &&
        isOverAxis( event.pageX, l, droppable.proportions().width );
    case "touch":
      return (
        ( y1 >= t && y1 <= b ) || // Top edge touching
        ( y2 >= t && y2 <= b ) || // Bottom edge touching
        ( y1 < t && y2 > b ) // Surrounded vertically
      ) && (
        ( x1 >= l && x1 <= r ) || // Left edge touching
        ( x2 >= l && x2 <= r ) || // Right edge touching
        ( x1 < l && x2 > r ) // Surrounded horizontally
      );
    default:
      return false;
    }
  };
} )();

/*
  This manager tracks offsets of draggables and droppables
*/
$.ui.ddmanager = {
  current: null,
  droppables: { "default": [] },
  prepareOffsets: function( t, event ) {

    var i, j,
      m = $.ui.ddmanager.droppables[ t.options.scope ] || [],
      type = event ? event.type : null, // workaround for #2317
      list = ( t.currentItem || t.element ).find( ":data(ui-droppable)" ).addBack();

    droppablesLoop: for ( i = 0; i < m.length; i++ ) {

      // No disabled and non-accepted
      if ( m[ i ].options.disabled || ( t && !m[ i ].accept.call( m[ i ].element[ 0 ],
          ( t.currentItem || t.element ) ) ) ) {
        continue;
      }

      // Filter out elements in the current dragged item
      for ( j = 0; j < list.length; j++ ) {
        if ( list[ j ] === m[ i ].element[ 0 ] ) {
          m[ i ].proportions().height = 0;
          continue droppablesLoop;
        }
      }

      m[ i ].visible = m[ i ].element.css( "display" ) !== "none";
      if ( !m[ i ].visible ) {
        continue;
      }

      // Activate the droppable if used directly from draggables
      if ( type === "mousedown" ) {
        m[ i ]._activate.call( m[ i ], event );
      }

      m[ i ].offset = m[ i ].element.offset();
      m[ i ].proportions( {
        width: m[ i ].element[ 0 ].offsetWidth,
        height: m[ i ].element[ 0 ].offsetHeight
      } );

    }

  },
  drop: function( draggable, event ) {

    var dropped = false;

    // Create a copy of the droppables in case the list changes during the drop (#9116)
    $.each( ( $.ui.ddmanager.droppables[ draggable.options.scope ] || [] ).slice(), function() {

      if ( !this.options ) {
        return;
      }
      if ( !this.options.disabled && this.visible &&
          intersect( draggable, this, this.options.tolerance, event ) ) {
        dropped = this._drop.call( this, event ) || dropped;
      }

      if ( !this.options.disabled && this.visible && this.accept.call( this.element[ 0 ],
          ( draggable.currentItem || draggable.element ) ) ) {
        this.isout = true;
        this.isover = false;
        this._deactivate.call( this, event );
      }

    } );
    return dropped;

  },
  dragStart: function( draggable, event ) {

    // Listen for scrolling so that if the dragging causes scrolling the position of the
    // droppables can be recalculated (see #5003)
    draggable.element.parentsUntil( "body" ).on( "scroll.droppable", function() {
      if ( !draggable.options.refreshPositions ) {
        $.ui.ddmanager.prepareOffsets( draggable, event );
      }
    } );
  },
  drag: function( draggable, event ) {

    // If you have a highly dynamic page, you might try this option. It renders positions
    // every time you move the mouse.
    if ( draggable.options.refreshPositions ) {
      $.ui.ddmanager.prepareOffsets( draggable, event );
    }

    // Run through all droppables and check their positions based on specific tolerance options
    $.each( $.ui.ddmanager.droppables[ draggable.options.scope ] || [], function() {

      if ( this.options.disabled || this.greedyChild || !this.visible ) {
        return;
      }

      var parentInstance, scope, parent,
        intersects = intersect( draggable, this, this.options.tolerance, event ),
        c = !intersects && this.isover ?
          "isout" :
          ( intersects && !this.isover ? "isover" : null );
      if ( !c ) {
        return;
      }

      if ( this.options.greedy ) {

        // find droppable parents with same scope
        scope = this.options.scope;
        parent = this.element.parents( ":data(ui-droppable)" ).filter( function() {
          return $( this ).droppable( "instance" ).options.scope === scope;
        } );

        if ( parent.length ) {
          parentInstance = $( parent[ 0 ] ).droppable( "instance" );
          parentInstance.greedyChild = ( c === "isover" );
        }
      }

      // We just moved into a greedy child
      if ( parentInstance && c === "isover" ) {
        parentInstance.isover = false;
        parentInstance.isout = true;
        parentInstance._out.call( parentInstance, event );
      }

      this[ c ] = true;
      this[ c === "isout" ? "isover" : "isout" ] = false;
      this[ c === "isover" ? "_over" : "_out" ].call( this, event );

      // We just moved out of a greedy child
      if ( parentInstance && c === "isout" ) {
        parentInstance.isout = false;
        parentInstance.isover = true;
        parentInstance._over.call( parentInstance, event );
      }
    } );

  },
  dragStop: function( draggable, event ) {
    draggable.element.parentsUntil( "body" ).off( "scroll.droppable" );

    // Call prepareOffsets one final time since IE does not fire return scroll events when
    // overflow was caused by drag (see #5003)
    if ( !draggable.options.refreshPositions ) {
      $.ui.ddmanager.prepareOffsets( draggable, event );
    }
  }
};

// DEPRECATED
// TODO: switch return back to widget declaration at top of file when this is removed
if ( $.uiBackCompat !== false ) {

  // Backcompat for activeClass and hoverClass options
  $.widget( "ui.droppable", $.ui.droppable, {
    options: {
      hoverClass: false,
      activeClass: false
    },
    _addActiveClass: function() {
      this._super();
      if ( this.options.activeClass ) {
        this.element.addClass( this.options.activeClass );
      }
    },
    _removeActiveClass: function() {
      this._super();
      if ( this.options.activeClass ) {
        this.element.removeClass( this.options.activeClass );
      }
    },
    _addHoverClass: function() {
      this._super();
      if ( this.options.hoverClass ) {
        this.element.addClass( this.options.hoverClass );
      }
    },
    _removeHoverClass: function() {
      this._super();
      if ( this.options.hoverClass ) {
        this.element.removeClass( this.options.hoverClass );
      }
    }
  } );
}

var widgetsDroppable = $.ui.droppable;


/*!
 * 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;




}));