ru-se.com

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs

resizable.js (29924B)


      1 /*!
      2  * jQuery UI Resizable 1.12.1
      3  * http://jqueryui.com
      4  *
      5  * Copyright jQuery Foundation and other contributors
      6  * Released under the MIT license.
      7  * http://jquery.org/license
      8  */
      9 
     10 //>>label: Resizable
     11 //>>group: Interactions
     12 //>>description: Enables resize functionality for any element.
     13 //>>docs: http://api.jqueryui.com/resizable/
     14 //>>demos: http://jqueryui.com/resizable/
     15 //>>css.structure: ../../themes/base/core.css
     16 //>>css.structure: ../../themes/base/resizable.css
     17 //>>css.theme: ../../themes/base/theme.css
     18 
     19 ( function( factory ) {
     20 	if ( typeof define === "function" && define.amd ) {
     21 
     22 		// AMD. Register as an anonymous module.
     23 		define( [
     24 			"jquery",
     25 			"./mouse",
     26 			"./core"
     27 		], factory );
     28 	} else {
     29 
     30 		// Browser globals
     31 		factory( jQuery );
     32 	}
     33 }( function( $ ) {
     34 
     35 $.widget( "ui.resizable", $.ui.mouse, {
     36 	version: "1.12.1",
     37 	widgetEventPrefix: "resize",
     38 	options: {
     39 		alsoResize: false,
     40 		animate: false,
     41 		animateDuration: "slow",
     42 		animateEasing: "swing",
     43 		aspectRatio: false,
     44 		autoHide: false,
     45 		classes: {
     46 			"ui-resizable-se": "ui-icon ui-icon-gripsmall-diagonal-se"
     47 		},
     48 		containment: false,
     49 		ghost: false,
     50 		grid: false,
     51 		handles: "e,s,se",
     52 		helper: false,
     53 		maxHeight: null,
     54 		maxWidth: null,
     55 		minHeight: 10,
     56 		minWidth: 10,
     57 
     58 		// See #7960
     59 		zIndex: 90,
     60 
     61 		// Callbacks
     62 		resize: null,
     63 		start: null,
     64 		stop: null
     65 	},
     66 
     67 	_num: function( value ) {
     68 		return parseFloat( value ) || 0;
     69 	},
     70 
     71 	_isNumber: function( value ) {
     72 		return !isNaN( parseFloat( value ) );
     73 	},
     74 
     75 	_hasScroll: function( el, a ) {
     76 
     77 		if ( $( el ).css( "overflow" ) === "hidden" ) {
     78 			return false;
     79 		}
     80 
     81 		var scroll = ( a && a === "left" ) ? "scrollLeft" : "scrollTop",
     82 			has = false;
     83 
     84 		if ( el[ scroll ] > 0 ) {
     85 			return true;
     86 		}
     87 
     88 		// TODO: determine which cases actually cause this to happen
     89 		// if the element doesn't have the scroll set, see if it's possible to
     90 		// set the scroll
     91 		el[ scroll ] = 1;
     92 		has = ( el[ scroll ] > 0 );
     93 		el[ scroll ] = 0;
     94 		return has;
     95 	},
     96 
     97 	_create: function() {
     98 
     99 		var margins,
    100 			o = this.options,
    101 			that = this;
    102 		this._addClass( "ui-resizable" );
    103 
    104 		$.extend( this, {
    105 			_aspectRatio: !!( o.aspectRatio ),
    106 			aspectRatio: o.aspectRatio,
    107 			originalElement: this.element,
    108 			_proportionallyResizeElements: [],
    109 			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
    110 		} );
    111 
    112 		// Wrap the element if it cannot hold child nodes
    113 		if ( this.element[ 0 ].nodeName.match( /^(canvas|textarea|input|select|button|img)$/i ) ) {
    114 
    115 			this.element.wrap(
    116 				$( "<div class='ui-wrapper' style='overflow: hidden;'></div>" ).css( {
    117 					position: this.element.css( "position" ),
    118 					width: this.element.outerWidth(),
    119 					height: this.element.outerHeight(),
    120 					top: this.element.css( "top" ),
    121 					left: this.element.css( "left" )
    122 				} )
    123 			);
    124 
    125 			this.element = this.element.parent().data(
    126 				"ui-resizable", this.element.resizable( "instance" )
    127 			);
    128 
    129 			this.elementIsWrapper = true;
    130 
    131 			margins = {
    132 				marginTop: this.originalElement.css( "marginTop" ),
    133 				marginRight: this.originalElement.css( "marginRight" ),
    134 				marginBottom: this.originalElement.css( "marginBottom" ),
    135 				marginLeft: this.originalElement.css( "marginLeft" )
    136 			};
    137 
    138 			this.element.css( margins );
    139 			this.originalElement.css( "margin", 0 );
    140 
    141 			// support: Safari
    142 			// Prevent Safari textarea resize
    143 			this.originalResizeStyle = this.originalElement.css( "resize" );
    144 			this.originalElement.css( "resize", "none" );
    145 
    146 			this._proportionallyResizeElements.push( this.originalElement.css( {
    147 				position: "static",
    148 				zoom: 1,
    149 				display: "block"
    150 			} ) );
    151 
    152 			// Support: IE9
    153 			// avoid IE jump (hard set the margin)
    154 			this.originalElement.css( margins );
    155 
    156 			this._proportionallyResize();
    157 		}
    158 
    159 		this._setupHandles();
    160 
    161 		if ( o.autoHide ) {
    162 			$( this.element )
    163 				.on( "mouseenter", function() {
    164 					if ( o.disabled ) {
    165 						return;
    166 					}
    167 					that._removeClass( "ui-resizable-autohide" );
    168 					that._handles.show();
    169 				} )
    170 				.on( "mouseleave", function() {
    171 					if ( o.disabled ) {
    172 						return;
    173 					}
    174 					if ( !that.resizing ) {
    175 						that._addClass( "ui-resizable-autohide" );
    176 						that._handles.hide();
    177 					}
    178 				} );
    179 		}
    180 
    181 		this._mouseInit();
    182 	},
    183 
    184 	_destroy: function() {
    185 
    186 		this._mouseDestroy();
    187 
    188 		var wrapper,
    189 			_destroy = function( exp ) {
    190 				$( exp )
    191 					.removeData( "resizable" )
    192 					.removeData( "ui-resizable" )
    193 					.off( ".resizable" )
    194 					.find( ".ui-resizable-handle" )
    195 						.remove();
    196 			};
    197 
    198 		// TODO: Unwrap at same DOM position
    199 		if ( this.elementIsWrapper ) {
    200 			_destroy( this.element );
    201 			wrapper = this.element;
    202 			this.originalElement.css( {
    203 				position: wrapper.css( "position" ),
    204 				width: wrapper.outerWidth(),
    205 				height: wrapper.outerHeight(),
    206 				top: wrapper.css( "top" ),
    207 				left: wrapper.css( "left" )
    208 			} ).insertAfter( wrapper );
    209 			wrapper.remove();
    210 		}
    211 
    212 		this.originalElement.css( "resize", this.originalResizeStyle );
    213 		_destroy( this.originalElement );
    214 
    215 		return this;
    216 	},
    217 
    218 	_setOption: function( key, value ) {
    219 		this._super( key, value );
    220 
    221 		switch ( key ) {
    222 		case "handles":
    223 			this._removeHandles();
    224 			this._setupHandles();
    225 			break;
    226 		default:
    227 			break;
    228 		}
    229 	},
    230 
    231 	_setupHandles: function() {
    232 		var o = this.options, handle, i, n, hname, axis, that = this;
    233 		this.handles = o.handles ||
    234 			( !$( ".ui-resizable-handle", this.element ).length ?
    235 				"e,s,se" : {
    236 					n: ".ui-resizable-n",
    237 					e: ".ui-resizable-e",
    238 					s: ".ui-resizable-s",
    239 					w: ".ui-resizable-w",
    240 					se: ".ui-resizable-se",
    241 					sw: ".ui-resizable-sw",
    242 					ne: ".ui-resizable-ne",
    243 					nw: ".ui-resizable-nw"
    244 				} );
    245 
    246 		this._handles = $();
    247 		if ( this.handles.constructor === String ) {
    248 
    249 			if ( this.handles === "all" ) {
    250 				this.handles = "n,e,s,w,se,sw,ne,nw";
    251 			}
    252 
    253 			n = this.handles.split( "," );
    254 			this.handles = {};
    255 
    256 			for ( i = 0; i < n.length; i++ ) {
    257 
    258 				handle = $.trim( n[ i ] );
    259 				hname = "ui-resizable-" + handle;
    260 				axis = $( "<div>" );
    261 				this._addClass( axis, "ui-resizable-handle " + hname );
    262 
    263 				axis.css( { zIndex: o.zIndex } );
    264 
    265 				this.handles[ handle ] = ".ui-resizable-" + handle;
    266 				this.element.append( axis );
    267 			}
    268 
    269 		}
    270 
    271 		this._renderAxis = function( target ) {
    272 
    273 			var i, axis, padPos, padWrapper;
    274 
    275 			target = target || this.element;
    276 
    277 			for ( i in this.handles ) {
    278 
    279 				if ( this.handles[ i ].constructor === String ) {
    280 					this.handles[ i ] = this.element.children( this.handles[ i ] ).first().show();
    281 				} else if ( this.handles[ i ].jquery || this.handles[ i ].nodeType ) {
    282 					this.handles[ i ] = $( this.handles[ i ] );
    283 					this._on( this.handles[ i ], { "mousedown": that._mouseDown } );
    284 				}
    285 
    286 				if ( this.elementIsWrapper &&
    287 						this.originalElement[ 0 ]
    288 							.nodeName
    289 							.match( /^(textarea|input|select|button)$/i ) ) {
    290 					axis = $( this.handles[ i ], this.element );
    291 
    292 					padWrapper = /sw|ne|nw|se|n|s/.test( i ) ?
    293 						axis.outerHeight() :
    294 						axis.outerWidth();
    295 
    296 					padPos = [ "padding",
    297 						/ne|nw|n/.test( i ) ? "Top" :
    298 						/se|sw|s/.test( i ) ? "Bottom" :
    299 						/^e$/.test( i ) ? "Right" : "Left" ].join( "" );
    300 
    301 					target.css( padPos, padWrapper );
    302 
    303 					this._proportionallyResize();
    304 				}
    305 
    306 				this._handles = this._handles.add( this.handles[ i ] );
    307 			}
    308 		};
    309 
    310 		// TODO: make renderAxis a prototype function
    311 		this._renderAxis( this.element );
    312 
    313 		this._handles = this._handles.add( this.element.find( ".ui-resizable-handle" ) );
    314 		this._handles.disableSelection();
    315 
    316 		this._handles.on( "mouseover", function() {
    317 			if ( !that.resizing ) {
    318 				if ( this.className ) {
    319 					axis = this.className.match( /ui-resizable-(se|sw|ne|nw|n|e|s|w)/i );
    320 				}
    321 				that.axis = axis && axis[ 1 ] ? axis[ 1 ] : "se";
    322 			}
    323 		} );
    324 
    325 		if ( o.autoHide ) {
    326 			this._handles.hide();
    327 			this._addClass( "ui-resizable-autohide" );
    328 		}
    329 	},
    330 
    331 	_removeHandles: function() {
    332 		this._handles.remove();
    333 	},
    334 
    335 	_mouseCapture: function( event ) {
    336 		var i, handle,
    337 			capture = false;
    338 
    339 		for ( i in this.handles ) {
    340 			handle = $( this.handles[ i ] )[ 0 ];
    341 			if ( handle === event.target || $.contains( handle, event.target ) ) {
    342 				capture = true;
    343 			}
    344 		}
    345 
    346 		return !this.options.disabled && capture;
    347 	},
    348 
    349 	_mouseStart: function( event ) {
    350 
    351 		var curleft, curtop, cursor,
    352 			o = this.options,
    353 			el = this.element;
    354 
    355 		this.resizing = true;
    356 
    357 		this._renderProxy();
    358 
    359 		curleft = this._num( this.helper.css( "left" ) );
    360 		curtop = this._num( this.helper.css( "top" ) );
    361 
    362 		if ( o.containment ) {
    363 			curleft += $( o.containment ).scrollLeft() || 0;
    364 			curtop += $( o.containment ).scrollTop() || 0;
    365 		}
    366 
    367 		this.offset = this.helper.offset();
    368 		this.position = { left: curleft, top: curtop };
    369 
    370 		this.size = this._helper ? {
    371 				width: this.helper.width(),
    372 				height: this.helper.height()
    373 			} : {
    374 				width: el.width(),
    375 				height: el.height()
    376 			};
    377 
    378 		this.originalSize = this._helper ? {
    379 				width: el.outerWidth(),
    380 				height: el.outerHeight()
    381 			} : {
    382 				width: el.width(),
    383 				height: el.height()
    384 			};
    385 
    386 		this.sizeDiff = {
    387 			width: el.outerWidth() - el.width(),
    388 			height: el.outerHeight() - el.height()
    389 		};
    390 
    391 		this.originalPosition = { left: curleft, top: curtop };
    392 		this.originalMousePosition = { left: event.pageX, top: event.pageY };
    393 
    394 		this.aspectRatio = ( typeof o.aspectRatio === "number" ) ?
    395 			o.aspectRatio :
    396 			( ( this.originalSize.width / this.originalSize.height ) || 1 );
    397 
    398 		cursor = $( ".ui-resizable-" + this.axis ).css( "cursor" );
    399 		$( "body" ).css( "cursor", cursor === "auto" ? this.axis + "-resize" : cursor );
    400 
    401 		this._addClass( "ui-resizable-resizing" );
    402 		this._propagate( "start", event );
    403 		return true;
    404 	},
    405 
    406 	_mouseDrag: function( event ) {
    407 
    408 		var data, props,
    409 			smp = this.originalMousePosition,
    410 			a = this.axis,
    411 			dx = ( event.pageX - smp.left ) || 0,
    412 			dy = ( event.pageY - smp.top ) || 0,
    413 			trigger = this._change[ a ];
    414 
    415 		this._updatePrevProperties();
    416 
    417 		if ( !trigger ) {
    418 			return false;
    419 		}
    420 
    421 		data = trigger.apply( this, [ event, dx, dy ] );
    422 
    423 		this._updateVirtualBoundaries( event.shiftKey );
    424 		if ( this._aspectRatio || event.shiftKey ) {
    425 			data = this._updateRatio( data, event );
    426 		}
    427 
    428 		data = this._respectSize( data, event );
    429 
    430 		this._updateCache( data );
    431 
    432 		this._propagate( "resize", event );
    433 
    434 		props = this._applyChanges();
    435 
    436 		if ( !this._helper && this._proportionallyResizeElements.length ) {
    437 			this._proportionallyResize();
    438 		}
    439 
    440 		if ( !$.isEmptyObject( props ) ) {
    441 			this._updatePrevProperties();
    442 			this._trigger( "resize", event, this.ui() );
    443 			this._applyChanges();
    444 		}
    445 
    446 		return false;
    447 	},
    448 
    449 	_mouseStop: function( event ) {
    450 
    451 		this.resizing = false;
    452 		var pr, ista, soffseth, soffsetw, s, left, top,
    453 			o = this.options, that = this;
    454 
    455 		if ( this._helper ) {
    456 
    457 			pr = this._proportionallyResizeElements;
    458 			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName );
    459 			soffseth = ista && this._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height;
    460 			soffsetw = ista ? 0 : that.sizeDiff.width;
    461 
    462 			s = {
    463 				width: ( that.helper.width()  - soffsetw ),
    464 				height: ( that.helper.height() - soffseth )
    465 			};
    466 			left = ( parseFloat( that.element.css( "left" ) ) +
    467 				( that.position.left - that.originalPosition.left ) ) || null;
    468 			top = ( parseFloat( that.element.css( "top" ) ) +
    469 				( that.position.top - that.originalPosition.top ) ) || null;
    470 
    471 			if ( !o.animate ) {
    472 				this.element.css( $.extend( s, { top: top, left: left } ) );
    473 			}
    474 
    475 			that.helper.height( that.size.height );
    476 			that.helper.width( that.size.width );
    477 
    478 			if ( this._helper && !o.animate ) {
    479 				this._proportionallyResize();
    480 			}
    481 		}
    482 
    483 		$( "body" ).css( "cursor", "auto" );
    484 
    485 		this._removeClass( "ui-resizable-resizing" );
    486 
    487 		this._propagate( "stop", event );
    488 
    489 		if ( this._helper ) {
    490 			this.helper.remove();
    491 		}
    492 
    493 		return false;
    494 
    495 	},
    496 
    497 	_updatePrevProperties: function() {
    498 		this.prevPosition = {
    499 			top: this.position.top,
    500 			left: this.position.left
    501 		};
    502 		this.prevSize = {
    503 			width: this.size.width,
    504 			height: this.size.height
    505 		};
    506 	},
    507 
    508 	_applyChanges: function() {
    509 		var props = {};
    510 
    511 		if ( this.position.top !== this.prevPosition.top ) {
    512 			props.top = this.position.top + "px";
    513 		}
    514 		if ( this.position.left !== this.prevPosition.left ) {
    515 			props.left = this.position.left + "px";
    516 		}
    517 		if ( this.size.width !== this.prevSize.width ) {
    518 			props.width = this.size.width + "px";
    519 		}
    520 		if ( this.size.height !== this.prevSize.height ) {
    521 			props.height = this.size.height + "px";
    522 		}
    523 
    524 		this.helper.css( props );
    525 
    526 		return props;
    527 	},
    528 
    529 	_updateVirtualBoundaries: function( forceAspectRatio ) {
    530 		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
    531 			o = this.options;
    532 
    533 		b = {
    534 			minWidth: this._isNumber( o.minWidth ) ? o.minWidth : 0,
    535 			maxWidth: this._isNumber( o.maxWidth ) ? o.maxWidth : Infinity,
    536 			minHeight: this._isNumber( o.minHeight ) ? o.minHeight : 0,
    537 			maxHeight: this._isNumber( o.maxHeight ) ? o.maxHeight : Infinity
    538 		};
    539 
    540 		if ( this._aspectRatio || forceAspectRatio ) {
    541 			pMinWidth = b.minHeight * this.aspectRatio;
    542 			pMinHeight = b.minWidth / this.aspectRatio;
    543 			pMaxWidth = b.maxHeight * this.aspectRatio;
    544 			pMaxHeight = b.maxWidth / this.aspectRatio;
    545 
    546 			if ( pMinWidth > b.minWidth ) {
    547 				b.minWidth = pMinWidth;
    548 			}
    549 			if ( pMinHeight > b.minHeight ) {
    550 				b.minHeight = pMinHeight;
    551 			}
    552 			if ( pMaxWidth < b.maxWidth ) {
    553 				b.maxWidth = pMaxWidth;
    554 			}
    555 			if ( pMaxHeight < b.maxHeight ) {
    556 				b.maxHeight = pMaxHeight;
    557 			}
    558 		}
    559 		this._vBoundaries = b;
    560 	},
    561 
    562 	_updateCache: function( data ) {
    563 		this.offset = this.helper.offset();
    564 		if ( this._isNumber( data.left ) ) {
    565 			this.position.left = data.left;
    566 		}
    567 		if ( this._isNumber( data.top ) ) {
    568 			this.position.top = data.top;
    569 		}
    570 		if ( this._isNumber( data.height ) ) {
    571 			this.size.height = data.height;
    572 		}
    573 		if ( this._isNumber( data.width ) ) {
    574 			this.size.width = data.width;
    575 		}
    576 	},
    577 
    578 	_updateRatio: function( data ) {
    579 
    580 		var cpos = this.position,
    581 			csize = this.size,
    582 			a = this.axis;
    583 
    584 		if ( this._isNumber( data.height ) ) {
    585 			data.width = ( data.height * this.aspectRatio );
    586 		} else if ( this._isNumber( data.width ) ) {
    587 			data.height = ( data.width / this.aspectRatio );
    588 		}
    589 
    590 		if ( a === "sw" ) {
    591 			data.left = cpos.left + ( csize.width - data.width );
    592 			data.top = null;
    593 		}
    594 		if ( a === "nw" ) {
    595 			data.top = cpos.top + ( csize.height - data.height );
    596 			data.left = cpos.left + ( csize.width - data.width );
    597 		}
    598 
    599 		return data;
    600 	},
    601 
    602 	_respectSize: function( data ) {
    603 
    604 		var o = this._vBoundaries,
    605 			a = this.axis,
    606 			ismaxw = this._isNumber( data.width ) && o.maxWidth && ( o.maxWidth < data.width ),
    607 			ismaxh = this._isNumber( data.height ) && o.maxHeight && ( o.maxHeight < data.height ),
    608 			isminw = this._isNumber( data.width ) && o.minWidth && ( o.minWidth > data.width ),
    609 			isminh = this._isNumber( data.height ) && o.minHeight && ( o.minHeight > data.height ),
    610 			dw = this.originalPosition.left + this.originalSize.width,
    611 			dh = this.originalPosition.top + this.originalSize.height,
    612 			cw = /sw|nw|w/.test( a ), ch = /nw|ne|n/.test( a );
    613 		if ( isminw ) {
    614 			data.width = o.minWidth;
    615 		}
    616 		if ( isminh ) {
    617 			data.height = o.minHeight;
    618 		}
    619 		if ( ismaxw ) {
    620 			data.width = o.maxWidth;
    621 		}
    622 		if ( ismaxh ) {
    623 			data.height = o.maxHeight;
    624 		}
    625 
    626 		if ( isminw && cw ) {
    627 			data.left = dw - o.minWidth;
    628 		}
    629 		if ( ismaxw && cw ) {
    630 			data.left = dw - o.maxWidth;
    631 		}
    632 		if ( isminh && ch ) {
    633 			data.top = dh - o.minHeight;
    634 		}
    635 		if ( ismaxh && ch ) {
    636 			data.top = dh - o.maxHeight;
    637 		}
    638 
    639 		// Fixing jump error on top/left - bug #2330
    640 		if ( !data.width && !data.height && !data.left && data.top ) {
    641 			data.top = null;
    642 		} else if ( !data.width && !data.height && !data.top && data.left ) {
    643 			data.left = null;
    644 		}
    645 
    646 		return data;
    647 	},
    648 
    649 	_getPaddingPlusBorderDimensions: function( element ) {
    650 		var i = 0,
    651 			widths = [],
    652 			borders = [
    653 				element.css( "borderTopWidth" ),
    654 				element.css( "borderRightWidth" ),
    655 				element.css( "borderBottomWidth" ),
    656 				element.css( "borderLeftWidth" )
    657 			],
    658 			paddings = [
    659 				element.css( "paddingTop" ),
    660 				element.css( "paddingRight" ),
    661 				element.css( "paddingBottom" ),
    662 				element.css( "paddingLeft" )
    663 			];
    664 
    665 		for ( ; i < 4; i++ ) {
    666 			widths[ i ] = ( parseFloat( borders[ i ] ) || 0 );
    667 			widths[ i ] += ( parseFloat( paddings[ i ] ) || 0 );
    668 		}
    669 
    670 		return {
    671 			height: widths[ 0 ] + widths[ 2 ],
    672 			width: widths[ 1 ] + widths[ 3 ]
    673 		};
    674 	},
    675 
    676 	_proportionallyResize: function() {
    677 
    678 		if ( !this._proportionallyResizeElements.length ) {
    679 			return;
    680 		}
    681 
    682 		var prel,
    683 			i = 0,
    684 			element = this.helper || this.element;
    685 
    686 		for ( ; i < this._proportionallyResizeElements.length; i++ ) {
    687 
    688 			prel = this._proportionallyResizeElements[ i ];
    689 
    690 			// TODO: Seems like a bug to cache this.outerDimensions
    691 			// considering that we are in a loop.
    692 			if ( !this.outerDimensions ) {
    693 				this.outerDimensions = this._getPaddingPlusBorderDimensions( prel );
    694 			}
    695 
    696 			prel.css( {
    697 				height: ( element.height() - this.outerDimensions.height ) || 0,
    698 				width: ( element.width() - this.outerDimensions.width ) || 0
    699 			} );
    700 
    701 		}
    702 
    703 	},
    704 
    705 	_renderProxy: function() {
    706 
    707 		var el = this.element, o = this.options;
    708 		this.elementOffset = el.offset();
    709 
    710 		if ( this._helper ) {
    711 
    712 			this.helper = this.helper || $( "<div style='overflow:hidden;'></div>" );
    713 
    714 			this._addClass( this.helper, this._helper );
    715 			this.helper.css( {
    716 				width: this.element.outerWidth(),
    717 				height: this.element.outerHeight(),
    718 				position: "absolute",
    719 				left: this.elementOffset.left + "px",
    720 				top: this.elementOffset.top + "px",
    721 				zIndex: ++o.zIndex //TODO: Don't modify option
    722 			} );
    723 
    724 			this.helper
    725 				.appendTo( "body" )
    726 				.disableSelection();
    727 
    728 		} else {
    729 			this.helper = this.element;
    730 		}
    731 
    732 	},
    733 
    734 	_change: {
    735 		e: function( event, dx ) {
    736 			return { width: this.originalSize.width + dx };
    737 		},
    738 		w: function( event, dx ) {
    739 			var cs = this.originalSize, sp = this.originalPosition;
    740 			return { left: sp.left + dx, width: cs.width - dx };
    741 		},
    742 		n: function( event, dx, dy ) {
    743 			var cs = this.originalSize, sp = this.originalPosition;
    744 			return { top: sp.top + dy, height: cs.height - dy };
    745 		},
    746 		s: function( event, dx, dy ) {
    747 			return { height: this.originalSize.height + dy };
    748 		},
    749 		se: function( event, dx, dy ) {
    750 			return $.extend( this._change.s.apply( this, arguments ),
    751 				this._change.e.apply( this, [ event, dx, dy ] ) );
    752 		},
    753 		sw: function( event, dx, dy ) {
    754 			return $.extend( this._change.s.apply( this, arguments ),
    755 				this._change.w.apply( this, [ event, dx, dy ] ) );
    756 		},
    757 		ne: function( event, dx, dy ) {
    758 			return $.extend( this._change.n.apply( this, arguments ),
    759 				this._change.e.apply( this, [ event, dx, dy ] ) );
    760 		},
    761 		nw: function( event, dx, dy ) {
    762 			return $.extend( this._change.n.apply( this, arguments ),
    763 				this._change.w.apply( this, [ event, dx, dy ] ) );
    764 		}
    765 	},
    766 
    767 	_propagate: function( n, event ) {
    768 		$.ui.plugin.call( this, n, [ event, this.ui() ] );
    769 		( n !== "resize" && this._trigger( n, event, this.ui() ) );
    770 	},
    771 
    772 	plugins: {},
    773 
    774 	ui: function() {
    775 		return {
    776 			originalElement: this.originalElement,
    777 			element: this.element,
    778 			helper: this.helper,
    779 			position: this.position,
    780 			size: this.size,
    781 			originalSize: this.originalSize,
    782 			originalPosition: this.originalPosition
    783 		};
    784 	}
    785 
    786 } );
    787 
    788 /*
    789  * Resizable Extensions
    790  */
    791 
    792 $.ui.plugin.add( "resizable", "animate", {
    793 
    794 	stop: function( event ) {
    795 		var that = $( this ).resizable( "instance" ),
    796 			o = that.options,
    797 			pr = that._proportionallyResizeElements,
    798 			ista = pr.length && ( /textarea/i ).test( pr[ 0 ].nodeName ),
    799 			soffseth = ista && that._hasScroll( pr[ 0 ], "left" ) ? 0 : that.sizeDiff.height,
    800 			soffsetw = ista ? 0 : that.sizeDiff.width,
    801 			style = {
    802 				width: ( that.size.width - soffsetw ),
    803 				height: ( that.size.height - soffseth )
    804 			},
    805 			left = ( parseFloat( that.element.css( "left" ) ) +
    806 				( that.position.left - that.originalPosition.left ) ) || null,
    807 			top = ( parseFloat( that.element.css( "top" ) ) +
    808 				( that.position.top - that.originalPosition.top ) ) || null;
    809 
    810 		that.element.animate(
    811 			$.extend( style, top && left ? { top: top, left: left } : {} ), {
    812 				duration: o.animateDuration,
    813 				easing: o.animateEasing,
    814 				step: function() {
    815 
    816 					var data = {
    817 						width: parseFloat( that.element.css( "width" ) ),
    818 						height: parseFloat( that.element.css( "height" ) ),
    819 						top: parseFloat( that.element.css( "top" ) ),
    820 						left: parseFloat( that.element.css( "left" ) )
    821 					};
    822 
    823 					if ( pr && pr.length ) {
    824 						$( pr[ 0 ] ).css( { width: data.width, height: data.height } );
    825 					}
    826 
    827 					// Propagating resize, and updating values for each animation step
    828 					that._updateCache( data );
    829 					that._propagate( "resize", event );
    830 
    831 				}
    832 			}
    833 		);
    834 	}
    835 
    836 } );
    837 
    838 $.ui.plugin.add( "resizable", "containment", {
    839 
    840 	start: function() {
    841 		var element, p, co, ch, cw, width, height,
    842 			that = $( this ).resizable( "instance" ),
    843 			o = that.options,
    844 			el = that.element,
    845 			oc = o.containment,
    846 			ce = ( oc instanceof $ ) ?
    847 				oc.get( 0 ) :
    848 				( /parent/.test( oc ) ) ? el.parent().get( 0 ) : oc;
    849 
    850 		if ( !ce ) {
    851 			return;
    852 		}
    853 
    854 		that.containerElement = $( ce );
    855 
    856 		if ( /document/.test( oc ) || oc === document ) {
    857 			that.containerOffset = {
    858 				left: 0,
    859 				top: 0
    860 			};
    861 			that.containerPosition = {
    862 				left: 0,
    863 				top: 0
    864 			};
    865 
    866 			that.parentData = {
    867 				element: $( document ),
    868 				left: 0,
    869 				top: 0,
    870 				width: $( document ).width(),
    871 				height: $( document ).height() || document.body.parentNode.scrollHeight
    872 			};
    873 		} else {
    874 			element = $( ce );
    875 			p = [];
    876 			$( [ "Top", "Right", "Left", "Bottom" ] ).each( function( i, name ) {
    877 				p[ i ] = that._num( element.css( "padding" + name ) );
    878 			} );
    879 
    880 			that.containerOffset = element.offset();
    881 			that.containerPosition = element.position();
    882 			that.containerSize = {
    883 				height: ( element.innerHeight() - p[ 3 ] ),
    884 				width: ( element.innerWidth() - p[ 1 ] )
    885 			};
    886 
    887 			co = that.containerOffset;
    888 			ch = that.containerSize.height;
    889 			cw = that.containerSize.width;
    890 			width = ( that._hasScroll ( ce, "left" ) ? ce.scrollWidth : cw );
    891 			height = ( that._hasScroll ( ce ) ? ce.scrollHeight : ch ) ;
    892 
    893 			that.parentData = {
    894 				element: ce,
    895 				left: co.left,
    896 				top: co.top,
    897 				width: width,
    898 				height: height
    899 			};
    900 		}
    901 	},
    902 
    903 	resize: function( event ) {
    904 		var woset, hoset, isParent, isOffsetRelative,
    905 			that = $( this ).resizable( "instance" ),
    906 			o = that.options,
    907 			co = that.containerOffset,
    908 			cp = that.position,
    909 			pRatio = that._aspectRatio || event.shiftKey,
    910 			cop = {
    911 				top: 0,
    912 				left: 0
    913 			},
    914 			ce = that.containerElement,
    915 			continueResize = true;
    916 
    917 		if ( ce[ 0 ] !== document && ( /static/ ).test( ce.css( "position" ) ) ) {
    918 			cop = co;
    919 		}
    920 
    921 		if ( cp.left < ( that._helper ? co.left : 0 ) ) {
    922 			that.size.width = that.size.width +
    923 				( that._helper ?
    924 					( that.position.left - co.left ) :
    925 					( that.position.left - cop.left ) );
    926 
    927 			if ( pRatio ) {
    928 				that.size.height = that.size.width / that.aspectRatio;
    929 				continueResize = false;
    930 			}
    931 			that.position.left = o.helper ? co.left : 0;
    932 		}
    933 
    934 		if ( cp.top < ( that._helper ? co.top : 0 ) ) {
    935 			that.size.height = that.size.height +
    936 				( that._helper ?
    937 					( that.position.top - co.top ) :
    938 					that.position.top );
    939 
    940 			if ( pRatio ) {
    941 				that.size.width = that.size.height * that.aspectRatio;
    942 				continueResize = false;
    943 			}
    944 			that.position.top = that._helper ? co.top : 0;
    945 		}
    946 
    947 		isParent = that.containerElement.get( 0 ) === that.element.parent().get( 0 );
    948 		isOffsetRelative = /relative|absolute/.test( that.containerElement.css( "position" ) );
    949 
    950 		if ( isParent && isOffsetRelative ) {
    951 			that.offset.left = that.parentData.left + that.position.left;
    952 			that.offset.top = that.parentData.top + that.position.top;
    953 		} else {
    954 			that.offset.left = that.element.offset().left;
    955 			that.offset.top = that.element.offset().top;
    956 		}
    957 
    958 		woset = Math.abs( that.sizeDiff.width +
    959 			( that._helper ?
    960 				that.offset.left - cop.left :
    961 				( that.offset.left - co.left ) ) );
    962 
    963 		hoset = Math.abs( that.sizeDiff.height +
    964 			( that._helper ?
    965 				that.offset.top - cop.top :
    966 				( that.offset.top - co.top ) ) );
    967 
    968 		if ( woset + that.size.width >= that.parentData.width ) {
    969 			that.size.width = that.parentData.width - woset;
    970 			if ( pRatio ) {
    971 				that.size.height = that.size.width / that.aspectRatio;
    972 				continueResize = false;
    973 			}
    974 		}
    975 
    976 		if ( hoset + that.size.height >= that.parentData.height ) {
    977 			that.size.height = that.parentData.height - hoset;
    978 			if ( pRatio ) {
    979 				that.size.width = that.size.height * that.aspectRatio;
    980 				continueResize = false;
    981 			}
    982 		}
    983 
    984 		if ( !continueResize ) {
    985 			that.position.left = that.prevPosition.left;
    986 			that.position.top = that.prevPosition.top;
    987 			that.size.width = that.prevSize.width;
    988 			that.size.height = that.prevSize.height;
    989 		}
    990 	},
    991 
    992 	stop: function() {
    993 		var that = $( this ).resizable( "instance" ),
    994 			o = that.options,
    995 			co = that.containerOffset,
    996 			cop = that.containerPosition,
    997 			ce = that.containerElement,
    998 			helper = $( that.helper ),
    999 			ho = helper.offset(),
   1000 			w = helper.outerWidth() - that.sizeDiff.width,
   1001 			h = helper.outerHeight() - that.sizeDiff.height;
   1002 
   1003 		if ( that._helper && !o.animate && ( /relative/ ).test( ce.css( "position" ) ) ) {
   1004 			$( this ).css( {
   1005 				left: ho.left - cop.left - co.left,
   1006 				width: w,
   1007 				height: h
   1008 			} );
   1009 		}
   1010 
   1011 		if ( that._helper && !o.animate && ( /static/ ).test( ce.css( "position" ) ) ) {
   1012 			$( this ).css( {
   1013 				left: ho.left - cop.left - co.left,
   1014 				width: w,
   1015 				height: h
   1016 			} );
   1017 		}
   1018 	}
   1019 } );
   1020 
   1021 $.ui.plugin.add( "resizable", "alsoResize", {
   1022 
   1023 	start: function() {
   1024 		var that = $( this ).resizable( "instance" ),
   1025 			o = that.options;
   1026 
   1027 		$( o.alsoResize ).each( function() {
   1028 			var el = $( this );
   1029 			el.data( "ui-resizable-alsoresize", {
   1030 				width: parseFloat( el.width() ), height: parseFloat( el.height() ),
   1031 				left: parseFloat( el.css( "left" ) ), top: parseFloat( el.css( "top" ) )
   1032 			} );
   1033 		} );
   1034 	},
   1035 
   1036 	resize: function( event, ui ) {
   1037 		var that = $( this ).resizable( "instance" ),
   1038 			o = that.options,
   1039 			os = that.originalSize,
   1040 			op = that.originalPosition,
   1041 			delta = {
   1042 				height: ( that.size.height - os.height ) || 0,
   1043 				width: ( that.size.width - os.width ) || 0,
   1044 				top: ( that.position.top - op.top ) || 0,
   1045 				left: ( that.position.left - op.left ) || 0
   1046 			};
   1047 
   1048 			$( o.alsoResize ).each( function() {
   1049 				var el = $( this ), start = $( this ).data( "ui-resizable-alsoresize" ), style = {},
   1050 					css = el.parents( ui.originalElement[ 0 ] ).length ?
   1051 							[ "width", "height" ] :
   1052 							[ "width", "height", "top", "left" ];
   1053 
   1054 				$.each( css, function( i, prop ) {
   1055 					var sum = ( start[ prop ] || 0 ) + ( delta[ prop ] || 0 );
   1056 					if ( sum && sum >= 0 ) {
   1057 						style[ prop ] = sum || null;
   1058 					}
   1059 				} );
   1060 
   1061 				el.css( style );
   1062 			} );
   1063 	},
   1064 
   1065 	stop: function() {
   1066 		$( this ).removeData( "ui-resizable-alsoresize" );
   1067 	}
   1068 } );
   1069 
   1070 $.ui.plugin.add( "resizable", "ghost", {
   1071 
   1072 	start: function() {
   1073 
   1074 		var that = $( this ).resizable( "instance" ), cs = that.size;
   1075 
   1076 		that.ghost = that.originalElement.clone();
   1077 		that.ghost.css( {
   1078 			opacity: 0.25,
   1079 			display: "block",
   1080 			position: "relative",
   1081 			height: cs.height,
   1082 			width: cs.width,
   1083 			margin: 0,
   1084 			left: 0,
   1085 			top: 0
   1086 		} );
   1087 
   1088 		that._addClass( that.ghost, "ui-resizable-ghost" );
   1089 
   1090 		// DEPRECATED
   1091 		// TODO: remove after 1.12
   1092 		if ( $.uiBackCompat !== false && typeof that.options.ghost === "string" ) {
   1093 
   1094 			// Ghost option
   1095 			that.ghost.addClass( this.options.ghost );
   1096 		}
   1097 
   1098 		that.ghost.appendTo( that.helper );
   1099 
   1100 	},
   1101 
   1102 	resize: function() {
   1103 		var that = $( this ).resizable( "instance" );
   1104 		if ( that.ghost ) {
   1105 			that.ghost.css( {
   1106 				position: "relative",
   1107 				height: that.size.height,
   1108 				width: that.size.width
   1109 			} );
   1110 		}
   1111 	},
   1112 
   1113 	stop: function() {
   1114 		var that = $( this ).resizable( "instance" );
   1115 		if ( that.ghost && that.helper ) {
   1116 			that.helper.get( 0 ).removeChild( that.ghost.get( 0 ) );
   1117 		}
   1118 	}
   1119 
   1120 } );
   1121 
   1122 $.ui.plugin.add( "resizable", "grid", {
   1123 
   1124 	resize: function() {
   1125 		var outerDimensions,
   1126 			that = $( this ).resizable( "instance" ),
   1127 			o = that.options,
   1128 			cs = that.size,
   1129 			os = that.originalSize,
   1130 			op = that.originalPosition,
   1131 			a = that.axis,
   1132 			grid = typeof o.grid === "number" ? [ o.grid, o.grid ] : o.grid,
   1133 			gridX = ( grid[ 0 ] || 1 ),
   1134 			gridY = ( grid[ 1 ] || 1 ),
   1135 			ox = Math.round( ( cs.width - os.width ) / gridX ) * gridX,
   1136 			oy = Math.round( ( cs.height - os.height ) / gridY ) * gridY,
   1137 			newWidth = os.width + ox,
   1138 			newHeight = os.height + oy,
   1139 			isMaxWidth = o.maxWidth && ( o.maxWidth < newWidth ),
   1140 			isMaxHeight = o.maxHeight && ( o.maxHeight < newHeight ),
   1141 			isMinWidth = o.minWidth && ( o.minWidth > newWidth ),
   1142 			isMinHeight = o.minHeight && ( o.minHeight > newHeight );
   1143 
   1144 		o.grid = grid;
   1145 
   1146 		if ( isMinWidth ) {
   1147 			newWidth += gridX;
   1148 		}
   1149 		if ( isMinHeight ) {
   1150 			newHeight += gridY;
   1151 		}
   1152 		if ( isMaxWidth ) {
   1153 			newWidth -= gridX;
   1154 		}
   1155 		if ( isMaxHeight ) {
   1156 			newHeight -= gridY;
   1157 		}
   1158 
   1159 		if ( /^(se|s|e)$/.test( a ) ) {
   1160 			that.size.width = newWidth;
   1161 			that.size.height = newHeight;
   1162 		} else if ( /^(ne)$/.test( a ) ) {
   1163 			that.size.width = newWidth;
   1164 			that.size.height = newHeight;
   1165 			that.position.top = op.top - oy;
   1166 		} else if ( /^(sw)$/.test( a ) ) {
   1167 			that.size.width = newWidth;
   1168 			that.size.height = newHeight;
   1169 			that.position.left = op.left - ox;
   1170 		} else {
   1171 			if ( newHeight - gridY <= 0 || newWidth - gridX <= 0 ) {
   1172 				outerDimensions = that._getPaddingPlusBorderDimensions( this );
   1173 			}
   1174 
   1175 			if ( newHeight - gridY > 0 ) {
   1176 				that.size.height = newHeight;
   1177 				that.position.top = op.top - oy;
   1178 			} else {
   1179 				newHeight = gridY - outerDimensions.height;
   1180 				that.size.height = newHeight;
   1181 				that.position.top = op.top + os.height - newHeight;
   1182 			}
   1183 			if ( newWidth - gridX > 0 ) {
   1184 				that.size.width = newWidth;
   1185 				that.position.left = op.left - ox;
   1186 			} else {
   1187 				newWidth = gridX - outerDimensions.width;
   1188 				that.size.width = newWidth;
   1189 				that.position.left = op.left + os.width - newWidth;
   1190 			}
   1191 		}
   1192 	}
   1193 
   1194 } );
   1195 
   1196 return $.ui.resizable;
   1197 
   1198 } ) );