integration/back-office/lib/jquery-ui/ui/jquery.ui.resizable.js
changeset 2 78f71aa0a477
parent 1 b95aebb070b5
child 3 54f80d24f469
child 6 547b3ddedf7f
equal deleted inserted replaced
1:b95aebb070b5 2:78f71aa0a477
     1 /*!
       
     2  * jQuery UI Resizable 1.10.3
       
     3  * http://jqueryui.com
       
     4  *
       
     5  * Copyright 2013 jQuery Foundation and other contributors
       
     6  * Released under the MIT license.
       
     7  * http://jquery.org/license
       
     8  *
       
     9  * http://api.jqueryui.com/resizable/
       
    10  *
       
    11  * Depends:
       
    12  *	jquery.ui.core.js
       
    13  *	jquery.ui.mouse.js
       
    14  *	jquery.ui.widget.js
       
    15  */
       
    16 (function( $, undefined ) {
       
    17 
       
    18 function num(v) {
       
    19 	return parseInt(v, 10) || 0;
       
    20 }
       
    21 
       
    22 function isNumber(value) {
       
    23 	return !isNaN(parseInt(value, 10));
       
    24 }
       
    25 
       
    26 $.widget("ui.resizable", $.ui.mouse, {
       
    27 	version: "1.10.3",
       
    28 	widgetEventPrefix: "resize",
       
    29 	options: {
       
    30 		alsoResize: false,
       
    31 		animate: false,
       
    32 		animateDuration: "slow",
       
    33 		animateEasing: "swing",
       
    34 		aspectRatio: false,
       
    35 		autoHide: false,
       
    36 		containment: false,
       
    37 		ghost: false,
       
    38 		grid: false,
       
    39 		handles: "e,s,se",
       
    40 		helper: false,
       
    41 		maxHeight: null,
       
    42 		maxWidth: null,
       
    43 		minHeight: 10,
       
    44 		minWidth: 10,
       
    45 		// See #7960
       
    46 		zIndex: 90,
       
    47 
       
    48 		// callbacks
       
    49 		resize: null,
       
    50 		start: null,
       
    51 		stop: null
       
    52 	},
       
    53 	_create: function() {
       
    54 
       
    55 		var n, i, handle, axis, hname,
       
    56 			that = this,
       
    57 			o = this.options;
       
    58 		this.element.addClass("ui-resizable");
       
    59 
       
    60 		$.extend(this, {
       
    61 			_aspectRatio: !!(o.aspectRatio),
       
    62 			aspectRatio: o.aspectRatio,
       
    63 			originalElement: this.element,
       
    64 			_proportionallyResizeElements: [],
       
    65 			_helper: o.helper || o.ghost || o.animate ? o.helper || "ui-resizable-helper" : null
       
    66 		});
       
    67 
       
    68 		//Wrap the element if it cannot hold child nodes
       
    69 		if(this.element[0].nodeName.match(/canvas|textarea|input|select|button|img/i)) {
       
    70 
       
    71 			//Create a wrapper element and set the wrapper to the new current internal element
       
    72 			this.element.wrap(
       
    73 				$("<div class='ui-wrapper' style='overflow: hidden;'></div>").css({
       
    74 					position: this.element.css("position"),
       
    75 					width: this.element.outerWidth(),
       
    76 					height: this.element.outerHeight(),
       
    77 					top: this.element.css("top"),
       
    78 					left: this.element.css("left")
       
    79 				})
       
    80 			);
       
    81 
       
    82 			//Overwrite the original this.element
       
    83 			this.element = this.element.parent().data(
       
    84 				"ui-resizable", this.element.data("ui-resizable")
       
    85 			);
       
    86 
       
    87 			this.elementIsWrapper = true;
       
    88 
       
    89 			//Move margins to the wrapper
       
    90 			this.element.css({ marginLeft: this.originalElement.css("marginLeft"), marginTop: this.originalElement.css("marginTop"), marginRight: this.originalElement.css("marginRight"), marginBottom: this.originalElement.css("marginBottom") });
       
    91 			this.originalElement.css({ marginLeft: 0, marginTop: 0, marginRight: 0, marginBottom: 0});
       
    92 
       
    93 			//Prevent Safari textarea resize
       
    94 			this.originalResizeStyle = this.originalElement.css("resize");
       
    95 			this.originalElement.css("resize", "none");
       
    96 
       
    97 			//Push the actual element to our proportionallyResize internal array
       
    98 			this._proportionallyResizeElements.push(this.originalElement.css({ position: "static", zoom: 1, display: "block" }));
       
    99 
       
   100 			// avoid IE jump (hard set the margin)
       
   101 			this.originalElement.css({ margin: this.originalElement.css("margin") });
       
   102 
       
   103 			// fix handlers offset
       
   104 			this._proportionallyResize();
       
   105 
       
   106 		}
       
   107 
       
   108 		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" });
       
   109 		if(this.handles.constructor === String) {
       
   110 
       
   111 			if ( this.handles === "all") {
       
   112 				this.handles = "n,e,s,w,se,sw,ne,nw";
       
   113 			}
       
   114 
       
   115 			n = this.handles.split(",");
       
   116 			this.handles = {};
       
   117 
       
   118 			for(i = 0; i < n.length; i++) {
       
   119 
       
   120 				handle = $.trim(n[i]);
       
   121 				hname = "ui-resizable-"+handle;
       
   122 				axis = $("<div class='ui-resizable-handle " + hname + "'></div>");
       
   123 
       
   124 				// Apply zIndex to all handles - see #7960
       
   125 				axis.css({ zIndex: o.zIndex });
       
   126 
       
   127 				//TODO : What's going on here?
       
   128 				if ("se" === handle) {
       
   129 					axis.addClass("ui-icon ui-icon-gripsmall-diagonal-se");
       
   130 				}
       
   131 
       
   132 				//Insert into internal handles object and append to element
       
   133 				this.handles[handle] = ".ui-resizable-"+handle;
       
   134 				this.element.append(axis);
       
   135 			}
       
   136 
       
   137 		}
       
   138 
       
   139 		this._renderAxis = function(target) {
       
   140 
       
   141 			var i, axis, padPos, padWrapper;
       
   142 
       
   143 			target = target || this.element;
       
   144 
       
   145 			for(i in this.handles) {
       
   146 
       
   147 				if(this.handles[i].constructor === String) {
       
   148 					this.handles[i] = $(this.handles[i], this.element).show();
       
   149 				}
       
   150 
       
   151 				//Apply pad to wrapper element, needed to fix axis position (textarea, inputs, scrolls)
       
   152 				if (this.elementIsWrapper && this.originalElement[0].nodeName.match(/textarea|input|select|button/i)) {
       
   153 
       
   154 					axis = $(this.handles[i], this.element);
       
   155 
       
   156 					//Checking the correct pad and border
       
   157 					padWrapper = /sw|ne|nw|se|n|s/.test(i) ? axis.outerHeight() : axis.outerWidth();
       
   158 
       
   159 					//The padding type i have to apply...
       
   160 					padPos = [ "padding",
       
   161 						/ne|nw|n/.test(i) ? "Top" :
       
   162 						/se|sw|s/.test(i) ? "Bottom" :
       
   163 						/^e$/.test(i) ? "Right" : "Left" ].join("");
       
   164 
       
   165 					target.css(padPos, padWrapper);
       
   166 
       
   167 					this._proportionallyResize();
       
   168 
       
   169 				}
       
   170 
       
   171 				//TODO: What's that good for? There's not anything to be executed left
       
   172 				if(!$(this.handles[i]).length) {
       
   173 					continue;
       
   174 				}
       
   175 			}
       
   176 		};
       
   177 
       
   178 		//TODO: make renderAxis a prototype function
       
   179 		this._renderAxis(this.element);
       
   180 
       
   181 		this._handles = $(".ui-resizable-handle", this.element)
       
   182 			.disableSelection();
       
   183 
       
   184 		//Matching axis name
       
   185 		this._handles.mouseover(function() {
       
   186 			if (!that.resizing) {
       
   187 				if (this.className) {
       
   188 					axis = this.className.match(/ui-resizable-(se|sw|ne|nw|n|e|s|w)/i);
       
   189 				}
       
   190 				//Axis, default = se
       
   191 				that.axis = axis && axis[1] ? axis[1] : "se";
       
   192 			}
       
   193 		});
       
   194 
       
   195 		//If we want to auto hide the elements
       
   196 		if (o.autoHide) {
       
   197 			this._handles.hide();
       
   198 			$(this.element)
       
   199 				.addClass("ui-resizable-autohide")
       
   200 				.mouseenter(function() {
       
   201 					if (o.disabled) {
       
   202 						return;
       
   203 					}
       
   204 					$(this).removeClass("ui-resizable-autohide");
       
   205 					that._handles.show();
       
   206 				})
       
   207 				.mouseleave(function(){
       
   208 					if (o.disabled) {
       
   209 						return;
       
   210 					}
       
   211 					if (!that.resizing) {
       
   212 						$(this).addClass("ui-resizable-autohide");
       
   213 						that._handles.hide();
       
   214 					}
       
   215 				});
       
   216 		}
       
   217 
       
   218 		//Initialize the mouse interaction
       
   219 		this._mouseInit();
       
   220 
       
   221 	},
       
   222 
       
   223 	_destroy: function() {
       
   224 
       
   225 		this._mouseDestroy();
       
   226 
       
   227 		var wrapper,
       
   228 			_destroy = function(exp) {
       
   229 				$(exp).removeClass("ui-resizable ui-resizable-disabled ui-resizable-resizing")
       
   230 					.removeData("resizable").removeData("ui-resizable").unbind(".resizable").find(".ui-resizable-handle").remove();
       
   231 			};
       
   232 
       
   233 		//TODO: Unwrap at same DOM position
       
   234 		if (this.elementIsWrapper) {
       
   235 			_destroy(this.element);
       
   236 			wrapper = this.element;
       
   237 			this.originalElement.css({
       
   238 				position: wrapper.css("position"),
       
   239 				width: wrapper.outerWidth(),
       
   240 				height: wrapper.outerHeight(),
       
   241 				top: wrapper.css("top"),
       
   242 				left: wrapper.css("left")
       
   243 			}).insertAfter( wrapper );
       
   244 			wrapper.remove();
       
   245 		}
       
   246 
       
   247 		this.originalElement.css("resize", this.originalResizeStyle);
       
   248 		_destroy(this.originalElement);
       
   249 
       
   250 		return this;
       
   251 	},
       
   252 
       
   253 	_mouseCapture: function(event) {
       
   254 		var i, handle,
       
   255 			capture = false;
       
   256 
       
   257 		for (i in this.handles) {
       
   258 			handle = $(this.handles[i])[0];
       
   259 			if (handle === event.target || $.contains(handle, event.target)) {
       
   260 				capture = true;
       
   261 			}
       
   262 		}
       
   263 
       
   264 		return !this.options.disabled && capture;
       
   265 	},
       
   266 
       
   267 	_mouseStart: function(event) {
       
   268 
       
   269 		var curleft, curtop, cursor,
       
   270 			o = this.options,
       
   271 			iniPos = this.element.position(),
       
   272 			el = this.element;
       
   273 
       
   274 		this.resizing = true;
       
   275 
       
   276 		// bugfix for http://dev.jquery.com/ticket/1749
       
   277 		if ( (/absolute/).test( el.css("position") ) ) {
       
   278 			el.css({ position: "absolute", top: el.css("top"), left: el.css("left") });
       
   279 		} else if (el.is(".ui-draggable")) {
       
   280 			el.css({ position: "absolute", top: iniPos.top, left: iniPos.left });
       
   281 		}
       
   282 
       
   283 		this._renderProxy();
       
   284 
       
   285 		curleft = num(this.helper.css("left"));
       
   286 		curtop = num(this.helper.css("top"));
       
   287 
       
   288 		if (o.containment) {
       
   289 			curleft += $(o.containment).scrollLeft() || 0;
       
   290 			curtop += $(o.containment).scrollTop() || 0;
       
   291 		}
       
   292 
       
   293 		//Store needed variables
       
   294 		this.offset = this.helper.offset();
       
   295 		this.position = { left: curleft, top: curtop };
       
   296 		this.size = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
       
   297 		this.originalSize = this._helper ? { width: el.outerWidth(), height: el.outerHeight() } : { width: el.width(), height: el.height() };
       
   298 		this.originalPosition = { left: curleft, top: curtop };
       
   299 		this.sizeDiff = { width: el.outerWidth() - el.width(), height: el.outerHeight() - el.height() };
       
   300 		this.originalMousePosition = { left: event.pageX, top: event.pageY };
       
   301 
       
   302 		//Aspect Ratio
       
   303 		this.aspectRatio = (typeof o.aspectRatio === "number") ? o.aspectRatio : ((this.originalSize.width / this.originalSize.height) || 1);
       
   304 
       
   305 		cursor = $(".ui-resizable-" + this.axis).css("cursor");
       
   306 		$("body").css("cursor", cursor === "auto" ? this.axis + "-resize" : cursor);
       
   307 
       
   308 		el.addClass("ui-resizable-resizing");
       
   309 		this._propagate("start", event);
       
   310 		return true;
       
   311 	},
       
   312 
       
   313 	_mouseDrag: function(event) {
       
   314 
       
   315 		//Increase performance, avoid regex
       
   316 		var data,
       
   317 			el = this.helper, props = {},
       
   318 			smp = this.originalMousePosition,
       
   319 			a = this.axis,
       
   320 			prevTop = this.position.top,
       
   321 			prevLeft = this.position.left,
       
   322 			prevWidth = this.size.width,
       
   323 			prevHeight = this.size.height,
       
   324 			dx = (event.pageX-smp.left)||0,
       
   325 			dy = (event.pageY-smp.top)||0,
       
   326 			trigger = this._change[a];
       
   327 
       
   328 		if (!trigger) {
       
   329 			return false;
       
   330 		}
       
   331 
       
   332 		// Calculate the attrs that will be change
       
   333 		data = trigger.apply(this, [event, dx, dy]);
       
   334 
       
   335 		// Put this in the mouseDrag handler since the user can start pressing shift while resizing
       
   336 		this._updateVirtualBoundaries(event.shiftKey);
       
   337 		if (this._aspectRatio || event.shiftKey) {
       
   338 			data = this._updateRatio(data, event);
       
   339 		}
       
   340 
       
   341 		data = this._respectSize(data, event);
       
   342 
       
   343 		this._updateCache(data);
       
   344 
       
   345 		// plugins callbacks need to be called first
       
   346 		this._propagate("resize", event);
       
   347 
       
   348 		if (this.position.top !== prevTop) {
       
   349 			props.top = this.position.top + "px";
       
   350 		}
       
   351 		if (this.position.left !== prevLeft) {
       
   352 			props.left = this.position.left + "px";
       
   353 		}
       
   354 		if (this.size.width !== prevWidth) {
       
   355 			props.width = this.size.width + "px";
       
   356 		}
       
   357 		if (this.size.height !== prevHeight) {
       
   358 			props.height = this.size.height + "px";
       
   359 		}
       
   360 		el.css(props);
       
   361 
       
   362 		if (!this._helper && this._proportionallyResizeElements.length) {
       
   363 			this._proportionallyResize();
       
   364 		}
       
   365 
       
   366 		// Call the user callback if the element was resized
       
   367 		if ( ! $.isEmptyObject(props) ) {
       
   368 			this._trigger("resize", event, this.ui());
       
   369 		}
       
   370 
       
   371 		return false;
       
   372 	},
       
   373 
       
   374 	_mouseStop: function(event) {
       
   375 
       
   376 		this.resizing = false;
       
   377 		var pr, ista, soffseth, soffsetw, s, left, top,
       
   378 			o = this.options, that = this;
       
   379 
       
   380 		if(this._helper) {
       
   381 
       
   382 			pr = this._proportionallyResizeElements;
       
   383 			ista = pr.length && (/textarea/i).test(pr[0].nodeName);
       
   384 			soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height;
       
   385 			soffsetw = ista ? 0 : that.sizeDiff.width;
       
   386 
       
   387 			s = { width: (that.helper.width()  - soffsetw), height: (that.helper.height() - soffseth) };
       
   388 			left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null;
       
   389 			top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
       
   390 
       
   391 			if (!o.animate) {
       
   392 				this.element.css($.extend(s, { top: top, left: left }));
       
   393 			}
       
   394 
       
   395 			that.helper.height(that.size.height);
       
   396 			that.helper.width(that.size.width);
       
   397 
       
   398 			if (this._helper && !o.animate) {
       
   399 				this._proportionallyResize();
       
   400 			}
       
   401 		}
       
   402 
       
   403 		$("body").css("cursor", "auto");
       
   404 
       
   405 		this.element.removeClass("ui-resizable-resizing");
       
   406 
       
   407 		this._propagate("stop", event);
       
   408 
       
   409 		if (this._helper) {
       
   410 			this.helper.remove();
       
   411 		}
       
   412 
       
   413 		return false;
       
   414 
       
   415 	},
       
   416 
       
   417 	_updateVirtualBoundaries: function(forceAspectRatio) {
       
   418 		var pMinWidth, pMaxWidth, pMinHeight, pMaxHeight, b,
       
   419 			o = this.options;
       
   420 
       
   421 		b = {
       
   422 			minWidth: isNumber(o.minWidth) ? o.minWidth : 0,
       
   423 			maxWidth: isNumber(o.maxWidth) ? o.maxWidth : Infinity,
       
   424 			minHeight: isNumber(o.minHeight) ? o.minHeight : 0,
       
   425 			maxHeight: isNumber(o.maxHeight) ? o.maxHeight : Infinity
       
   426 		};
       
   427 
       
   428 		if(this._aspectRatio || forceAspectRatio) {
       
   429 			// We want to create an enclosing box whose aspect ration is the requested one
       
   430 			// First, compute the "projected" size for each dimension based on the aspect ratio and other dimension
       
   431 			pMinWidth = b.minHeight * this.aspectRatio;
       
   432 			pMinHeight = b.minWidth / this.aspectRatio;
       
   433 			pMaxWidth = b.maxHeight * this.aspectRatio;
       
   434 			pMaxHeight = b.maxWidth / this.aspectRatio;
       
   435 
       
   436 			if(pMinWidth > b.minWidth) {
       
   437 				b.minWidth = pMinWidth;
       
   438 			}
       
   439 			if(pMinHeight > b.minHeight) {
       
   440 				b.minHeight = pMinHeight;
       
   441 			}
       
   442 			if(pMaxWidth < b.maxWidth) {
       
   443 				b.maxWidth = pMaxWidth;
       
   444 			}
       
   445 			if(pMaxHeight < b.maxHeight) {
       
   446 				b.maxHeight = pMaxHeight;
       
   447 			}
       
   448 		}
       
   449 		this._vBoundaries = b;
       
   450 	},
       
   451 
       
   452 	_updateCache: function(data) {
       
   453 		this.offset = this.helper.offset();
       
   454 		if (isNumber(data.left)) {
       
   455 			this.position.left = data.left;
       
   456 		}
       
   457 		if (isNumber(data.top)) {
       
   458 			this.position.top = data.top;
       
   459 		}
       
   460 		if (isNumber(data.height)) {
       
   461 			this.size.height = data.height;
       
   462 		}
       
   463 		if (isNumber(data.width)) {
       
   464 			this.size.width = data.width;
       
   465 		}
       
   466 	},
       
   467 
       
   468 	_updateRatio: function( data ) {
       
   469 
       
   470 		var cpos = this.position,
       
   471 			csize = this.size,
       
   472 			a = this.axis;
       
   473 
       
   474 		if (isNumber(data.height)) {
       
   475 			data.width = (data.height * this.aspectRatio);
       
   476 		} else if (isNumber(data.width)) {
       
   477 			data.height = (data.width / this.aspectRatio);
       
   478 		}
       
   479 
       
   480 		if (a === "sw") {
       
   481 			data.left = cpos.left + (csize.width - data.width);
       
   482 			data.top = null;
       
   483 		}
       
   484 		if (a === "nw") {
       
   485 			data.top = cpos.top + (csize.height - data.height);
       
   486 			data.left = cpos.left + (csize.width - data.width);
       
   487 		}
       
   488 
       
   489 		return data;
       
   490 	},
       
   491 
       
   492 	_respectSize: function( data ) {
       
   493 
       
   494 		var o = this._vBoundaries,
       
   495 			a = this.axis,
       
   496 			ismaxw = isNumber(data.width) && o.maxWidth && (o.maxWidth < data.width), ismaxh = isNumber(data.height) && o.maxHeight && (o.maxHeight < data.height),
       
   497 			isminw = isNumber(data.width) && o.minWidth && (o.minWidth > data.width), isminh = isNumber(data.height) && o.minHeight && (o.minHeight > data.height),
       
   498 			dw = this.originalPosition.left + this.originalSize.width,
       
   499 			dh = this.position.top + this.size.height,
       
   500 			cw = /sw|nw|w/.test(a), ch = /nw|ne|n/.test(a);
       
   501 		if (isminw) {
       
   502 			data.width = o.minWidth;
       
   503 		}
       
   504 		if (isminh) {
       
   505 			data.height = o.minHeight;
       
   506 		}
       
   507 		if (ismaxw) {
       
   508 			data.width = o.maxWidth;
       
   509 		}
       
   510 		if (ismaxh) {
       
   511 			data.height = o.maxHeight;
       
   512 		}
       
   513 
       
   514 		if (isminw && cw) {
       
   515 			data.left = dw - o.minWidth;
       
   516 		}
       
   517 		if (ismaxw && cw) {
       
   518 			data.left = dw - o.maxWidth;
       
   519 		}
       
   520 		if (isminh && ch) {
       
   521 			data.top = dh - o.minHeight;
       
   522 		}
       
   523 		if (ismaxh && ch) {
       
   524 			data.top = dh - o.maxHeight;
       
   525 		}
       
   526 
       
   527 		// fixing jump error on top/left - bug #2330
       
   528 		if (!data.width && !data.height && !data.left && data.top) {
       
   529 			data.top = null;
       
   530 		} else if (!data.width && !data.height && !data.top && data.left) {
       
   531 			data.left = null;
       
   532 		}
       
   533 
       
   534 		return data;
       
   535 	},
       
   536 
       
   537 	_proportionallyResize: function() {
       
   538 
       
   539 		if (!this._proportionallyResizeElements.length) {
       
   540 			return;
       
   541 		}
       
   542 
       
   543 		var i, j, borders, paddings, prel,
       
   544 			element = this.helper || this.element;
       
   545 
       
   546 		for ( i=0; i < this._proportionallyResizeElements.length; i++) {
       
   547 
       
   548 			prel = this._proportionallyResizeElements[i];
       
   549 
       
   550 			if (!this.borderDif) {
       
   551 				this.borderDif = [];
       
   552 				borders = [prel.css("borderTopWidth"), prel.css("borderRightWidth"), prel.css("borderBottomWidth"), prel.css("borderLeftWidth")];
       
   553 				paddings = [prel.css("paddingTop"), prel.css("paddingRight"), prel.css("paddingBottom"), prel.css("paddingLeft")];
       
   554 
       
   555 				for ( j = 0; j < borders.length; j++ ) {
       
   556 					this.borderDif[ j ] = ( parseInt( borders[ j ], 10 ) || 0 ) + ( parseInt( paddings[ j ], 10 ) || 0 );
       
   557 				}
       
   558 			}
       
   559 
       
   560 			prel.css({
       
   561 				height: (element.height() - this.borderDif[0] - this.borderDif[2]) || 0,
       
   562 				width: (element.width() - this.borderDif[1] - this.borderDif[3]) || 0
       
   563 			});
       
   564 
       
   565 		}
       
   566 
       
   567 	},
       
   568 
       
   569 	_renderProxy: function() {
       
   570 
       
   571 		var el = this.element, o = this.options;
       
   572 		this.elementOffset = el.offset();
       
   573 
       
   574 		if(this._helper) {
       
   575 
       
   576 			this.helper = this.helper || $("<div style='overflow:hidden;'></div>");
       
   577 
       
   578 			this.helper.addClass(this._helper).css({
       
   579 				width: this.element.outerWidth() - 1,
       
   580 				height: this.element.outerHeight() - 1,
       
   581 				position: "absolute",
       
   582 				left: this.elementOffset.left +"px",
       
   583 				top: this.elementOffset.top +"px",
       
   584 				zIndex: ++o.zIndex //TODO: Don't modify option
       
   585 			});
       
   586 
       
   587 			this.helper
       
   588 				.appendTo("body")
       
   589 				.disableSelection();
       
   590 
       
   591 		} else {
       
   592 			this.helper = this.element;
       
   593 		}
       
   594 
       
   595 	},
       
   596 
       
   597 	_change: {
       
   598 		e: function(event, dx) {
       
   599 			return { width: this.originalSize.width + dx };
       
   600 		},
       
   601 		w: function(event, dx) {
       
   602 			var cs = this.originalSize, sp = this.originalPosition;
       
   603 			return { left: sp.left + dx, width: cs.width - dx };
       
   604 		},
       
   605 		n: function(event, dx, dy) {
       
   606 			var cs = this.originalSize, sp = this.originalPosition;
       
   607 			return { top: sp.top + dy, height: cs.height - dy };
       
   608 		},
       
   609 		s: function(event, dx, dy) {
       
   610 			return { height: this.originalSize.height + dy };
       
   611 		},
       
   612 		se: function(event, dx, dy) {
       
   613 			return $.extend(this._change.s.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
       
   614 		},
       
   615 		sw: function(event, dx, dy) {
       
   616 			return $.extend(this._change.s.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
       
   617 		},
       
   618 		ne: function(event, dx, dy) {
       
   619 			return $.extend(this._change.n.apply(this, arguments), this._change.e.apply(this, [event, dx, dy]));
       
   620 		},
       
   621 		nw: function(event, dx, dy) {
       
   622 			return $.extend(this._change.n.apply(this, arguments), this._change.w.apply(this, [event, dx, dy]));
       
   623 		}
       
   624 	},
       
   625 
       
   626 	_propagate: function(n, event) {
       
   627 		$.ui.plugin.call(this, n, [event, this.ui()]);
       
   628 		(n !== "resize" && this._trigger(n, event, this.ui()));
       
   629 	},
       
   630 
       
   631 	plugins: {},
       
   632 
       
   633 	ui: function() {
       
   634 		return {
       
   635 			originalElement: this.originalElement,
       
   636 			element: this.element,
       
   637 			helper: this.helper,
       
   638 			position: this.position,
       
   639 			size: this.size,
       
   640 			originalSize: this.originalSize,
       
   641 			originalPosition: this.originalPosition
       
   642 		};
       
   643 	}
       
   644 
       
   645 });
       
   646 
       
   647 /*
       
   648  * Resizable Extensions
       
   649  */
       
   650 
       
   651 $.ui.plugin.add("resizable", "animate", {
       
   652 
       
   653 	stop: function( event ) {
       
   654 		var that = $(this).data("ui-resizable"),
       
   655 			o = that.options,
       
   656 			pr = that._proportionallyResizeElements,
       
   657 			ista = pr.length && (/textarea/i).test(pr[0].nodeName),
       
   658 			soffseth = ista && $.ui.hasScroll(pr[0], "left") /* TODO - jump height */ ? 0 : that.sizeDiff.height,
       
   659 			soffsetw = ista ? 0 : that.sizeDiff.width,
       
   660 			style = { width: (that.size.width - soffsetw), height: (that.size.height - soffseth) },
       
   661 			left = (parseInt(that.element.css("left"), 10) + (that.position.left - that.originalPosition.left)) || null,
       
   662 			top = (parseInt(that.element.css("top"), 10) + (that.position.top - that.originalPosition.top)) || null;
       
   663 
       
   664 		that.element.animate(
       
   665 			$.extend(style, top && left ? { top: top, left: left } : {}), {
       
   666 				duration: o.animateDuration,
       
   667 				easing: o.animateEasing,
       
   668 				step: function() {
       
   669 
       
   670 					var data = {
       
   671 						width: parseInt(that.element.css("width"), 10),
       
   672 						height: parseInt(that.element.css("height"), 10),
       
   673 						top: parseInt(that.element.css("top"), 10),
       
   674 						left: parseInt(that.element.css("left"), 10)
       
   675 					};
       
   676 
       
   677 					if (pr && pr.length) {
       
   678 						$(pr[0]).css({ width: data.width, height: data.height });
       
   679 					}
       
   680 
       
   681 					// propagating resize, and updating values for each animation step
       
   682 					that._updateCache(data);
       
   683 					that._propagate("resize", event);
       
   684 
       
   685 				}
       
   686 			}
       
   687 		);
       
   688 	}
       
   689 
       
   690 });
       
   691 
       
   692 $.ui.plugin.add("resizable", "containment", {
       
   693 
       
   694 	start: function() {
       
   695 		var element, p, co, ch, cw, width, height,
       
   696 			that = $(this).data("ui-resizable"),
       
   697 			o = that.options,
       
   698 			el = that.element,
       
   699 			oc = o.containment,
       
   700 			ce = (oc instanceof $) ? oc.get(0) : (/parent/.test(oc)) ? el.parent().get(0) : oc;
       
   701 
       
   702 		if (!ce) {
       
   703 			return;
       
   704 		}
       
   705 
       
   706 		that.containerElement = $(ce);
       
   707 
       
   708 		if (/document/.test(oc) || oc === document) {
       
   709 			that.containerOffset = { left: 0, top: 0 };
       
   710 			that.containerPosition = { left: 0, top: 0 };
       
   711 
       
   712 			that.parentData = {
       
   713 				element: $(document), left: 0, top: 0,
       
   714 				width: $(document).width(), height: $(document).height() || document.body.parentNode.scrollHeight
       
   715 			};
       
   716 		}
       
   717 
       
   718 		// i'm a node, so compute top, left, right, bottom
       
   719 		else {
       
   720 			element = $(ce);
       
   721 			p = [];
       
   722 			$([ "Top", "Right", "Left", "Bottom" ]).each(function(i, name) { p[i] = num(element.css("padding" + name)); });
       
   723 
       
   724 			that.containerOffset = element.offset();
       
   725 			that.containerPosition = element.position();
       
   726 			that.containerSize = { height: (element.innerHeight() - p[3]), width: (element.innerWidth() - p[1]) };
       
   727 
       
   728 			co = that.containerOffset;
       
   729 			ch = that.containerSize.height;
       
   730 			cw = that.containerSize.width;
       
   731 			width = ($.ui.hasScroll(ce, "left") ? ce.scrollWidth : cw );
       
   732 			height = ($.ui.hasScroll(ce) ? ce.scrollHeight : ch);
       
   733 
       
   734 			that.parentData = {
       
   735 				element: ce, left: co.left, top: co.top, width: width, height: height
       
   736 			};
       
   737 		}
       
   738 	},
       
   739 
       
   740 	resize: function( event ) {
       
   741 		var woset, hoset, isParent, isOffsetRelative,
       
   742 			that = $(this).data("ui-resizable"),
       
   743 			o = that.options,
       
   744 			co = that.containerOffset, cp = that.position,
       
   745 			pRatio = that._aspectRatio || event.shiftKey,
       
   746 			cop = { top:0, left:0 }, ce = that.containerElement;
       
   747 
       
   748 		if (ce[0] !== document && (/static/).test(ce.css("position"))) {
       
   749 			cop = co;
       
   750 		}
       
   751 
       
   752 		if (cp.left < (that._helper ? co.left : 0)) {
       
   753 			that.size.width = that.size.width + (that._helper ? (that.position.left - co.left) : (that.position.left - cop.left));
       
   754 			if (pRatio) {
       
   755 				that.size.height = that.size.width / that.aspectRatio;
       
   756 			}
       
   757 			that.position.left = o.helper ? co.left : 0;
       
   758 		}
       
   759 
       
   760 		if (cp.top < (that._helper ? co.top : 0)) {
       
   761 			that.size.height = that.size.height + (that._helper ? (that.position.top - co.top) : that.position.top);
       
   762 			if (pRatio) {
       
   763 				that.size.width = that.size.height * that.aspectRatio;
       
   764 			}
       
   765 			that.position.top = that._helper ? co.top : 0;
       
   766 		}
       
   767 
       
   768 		that.offset.left = that.parentData.left+that.position.left;
       
   769 		that.offset.top = that.parentData.top+that.position.top;
       
   770 
       
   771 		woset = Math.abs( (that._helper ? that.offset.left - cop.left : (that.offset.left - cop.left)) + that.sizeDiff.width );
       
   772 		hoset = Math.abs( (that._helper ? that.offset.top - cop.top : (that.offset.top - co.top)) + that.sizeDiff.height );
       
   773 
       
   774 		isParent = that.containerElement.get(0) === that.element.parent().get(0);
       
   775 		isOffsetRelative = /relative|absolute/.test(that.containerElement.css("position"));
       
   776 
       
   777 		if(isParent && isOffsetRelative) {
       
   778 			woset -= that.parentData.left;
       
   779 		}
       
   780 
       
   781 		if (woset + that.size.width >= that.parentData.width) {
       
   782 			that.size.width = that.parentData.width - woset;
       
   783 			if (pRatio) {
       
   784 				that.size.height = that.size.width / that.aspectRatio;
       
   785 			}
       
   786 		}
       
   787 
       
   788 		if (hoset + that.size.height >= that.parentData.height) {
       
   789 			that.size.height = that.parentData.height - hoset;
       
   790 			if (pRatio) {
       
   791 				that.size.width = that.size.height * that.aspectRatio;
       
   792 			}
       
   793 		}
       
   794 	},
       
   795 
       
   796 	stop: function(){
       
   797 		var that = $(this).data("ui-resizable"),
       
   798 			o = that.options,
       
   799 			co = that.containerOffset,
       
   800 			cop = that.containerPosition,
       
   801 			ce = that.containerElement,
       
   802 			helper = $(that.helper),
       
   803 			ho = helper.offset(),
       
   804 			w = helper.outerWidth() - that.sizeDiff.width,
       
   805 			h = helper.outerHeight() - that.sizeDiff.height;
       
   806 
       
   807 		if (that._helper && !o.animate && (/relative/).test(ce.css("position"))) {
       
   808 			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
       
   809 		}
       
   810 
       
   811 		if (that._helper && !o.animate && (/static/).test(ce.css("position"))) {
       
   812 			$(this).css({ left: ho.left - cop.left - co.left, width: w, height: h });
       
   813 		}
       
   814 
       
   815 	}
       
   816 });
       
   817 
       
   818 $.ui.plugin.add("resizable", "alsoResize", {
       
   819 
       
   820 	start: function () {
       
   821 		var that = $(this).data("ui-resizable"),
       
   822 			o = that.options,
       
   823 			_store = function (exp) {
       
   824 				$(exp).each(function() {
       
   825 					var el = $(this);
       
   826 					el.data("ui-resizable-alsoresize", {
       
   827 						width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
       
   828 						left: parseInt(el.css("left"), 10), top: parseInt(el.css("top"), 10)
       
   829 					});
       
   830 				});
       
   831 			};
       
   832 
       
   833 		if (typeof(o.alsoResize) === "object" && !o.alsoResize.parentNode) {
       
   834 			if (o.alsoResize.length) { o.alsoResize = o.alsoResize[0]; _store(o.alsoResize); }
       
   835 			else { $.each(o.alsoResize, function (exp) { _store(exp); }); }
       
   836 		}else{
       
   837 			_store(o.alsoResize);
       
   838 		}
       
   839 	},
       
   840 
       
   841 	resize: function (event, ui) {
       
   842 		var that = $(this).data("ui-resizable"),
       
   843 			o = that.options,
       
   844 			os = that.originalSize,
       
   845 			op = that.originalPosition,
       
   846 			delta = {
       
   847 				height: (that.size.height - os.height) || 0, width: (that.size.width - os.width) || 0,
       
   848 				top: (that.position.top - op.top) || 0, left: (that.position.left - op.left) || 0
       
   849 			},
       
   850 
       
   851 			_alsoResize = function (exp, c) {
       
   852 				$(exp).each(function() {
       
   853 					var el = $(this), start = $(this).data("ui-resizable-alsoresize"), style = {},
       
   854 						css = c && c.length ? c : el.parents(ui.originalElement[0]).length ? ["width", "height"] : ["width", "height", "top", "left"];
       
   855 
       
   856 					$.each(css, function (i, prop) {
       
   857 						var sum = (start[prop]||0) + (delta[prop]||0);
       
   858 						if (sum && sum >= 0) {
       
   859 							style[prop] = sum || null;
       
   860 						}
       
   861 					});
       
   862 
       
   863 					el.css(style);
       
   864 				});
       
   865 			};
       
   866 
       
   867 		if (typeof(o.alsoResize) === "object" && !o.alsoResize.nodeType) {
       
   868 			$.each(o.alsoResize, function (exp, c) { _alsoResize(exp, c); });
       
   869 		}else{
       
   870 			_alsoResize(o.alsoResize);
       
   871 		}
       
   872 	},
       
   873 
       
   874 	stop: function () {
       
   875 		$(this).removeData("resizable-alsoresize");
       
   876 	}
       
   877 });
       
   878 
       
   879 $.ui.plugin.add("resizable", "ghost", {
       
   880 
       
   881 	start: function() {
       
   882 
       
   883 		var that = $(this).data("ui-resizable"), o = that.options, cs = that.size;
       
   884 
       
   885 		that.ghost = that.originalElement.clone();
       
   886 		that.ghost
       
   887 			.css({ opacity: 0.25, display: "block", position: "relative", height: cs.height, width: cs.width, margin: 0, left: 0, top: 0 })
       
   888 			.addClass("ui-resizable-ghost")
       
   889 			.addClass(typeof o.ghost === "string" ? o.ghost : "");
       
   890 
       
   891 		that.ghost.appendTo(that.helper);
       
   892 
       
   893 	},
       
   894 
       
   895 	resize: function(){
       
   896 		var that = $(this).data("ui-resizable");
       
   897 		if (that.ghost) {
       
   898 			that.ghost.css({ position: "relative", height: that.size.height, width: that.size.width });
       
   899 		}
       
   900 	},
       
   901 
       
   902 	stop: function() {
       
   903 		var that = $(this).data("ui-resizable");
       
   904 		if (that.ghost && that.helper) {
       
   905 			that.helper.get(0).removeChild(that.ghost.get(0));
       
   906 		}
       
   907 	}
       
   908 
       
   909 });
       
   910 
       
   911 $.ui.plugin.add("resizable", "grid", {
       
   912 
       
   913 	resize: function() {
       
   914 		var that = $(this).data("ui-resizable"),
       
   915 			o = that.options,
       
   916 			cs = that.size,
       
   917 			os = that.originalSize,
       
   918 			op = that.originalPosition,
       
   919 			a = that.axis,
       
   920 			grid = typeof o.grid === "number" ? [o.grid, o.grid] : o.grid,
       
   921 			gridX = (grid[0]||1),
       
   922 			gridY = (grid[1]||1),
       
   923 			ox = Math.round((cs.width - os.width) / gridX) * gridX,
       
   924 			oy = Math.round((cs.height - os.height) / gridY) * gridY,
       
   925 			newWidth = os.width + ox,
       
   926 			newHeight = os.height + oy,
       
   927 			isMaxWidth = o.maxWidth && (o.maxWidth < newWidth),
       
   928 			isMaxHeight = o.maxHeight && (o.maxHeight < newHeight),
       
   929 			isMinWidth = o.minWidth && (o.minWidth > newWidth),
       
   930 			isMinHeight = o.minHeight && (o.minHeight > newHeight);
       
   931 
       
   932 		o.grid = grid;
       
   933 
       
   934 		if (isMinWidth) {
       
   935 			newWidth = newWidth + gridX;
       
   936 		}
       
   937 		if (isMinHeight) {
       
   938 			newHeight = newHeight + gridY;
       
   939 		}
       
   940 		if (isMaxWidth) {
       
   941 			newWidth = newWidth - gridX;
       
   942 		}
       
   943 		if (isMaxHeight) {
       
   944 			newHeight = newHeight - gridY;
       
   945 		}
       
   946 
       
   947 		if (/^(se|s|e)$/.test(a)) {
       
   948 			that.size.width = newWidth;
       
   949 			that.size.height = newHeight;
       
   950 		} else if (/^(ne)$/.test(a)) {
       
   951 			that.size.width = newWidth;
       
   952 			that.size.height = newHeight;
       
   953 			that.position.top = op.top - oy;
       
   954 		} else if (/^(sw)$/.test(a)) {
       
   955 			that.size.width = newWidth;
       
   956 			that.size.height = newHeight;
       
   957 			that.position.left = op.left - ox;
       
   958 		} else {
       
   959 			that.size.width = newWidth;
       
   960 			that.size.height = newHeight;
       
   961 			that.position.top = op.top - oy;
       
   962 			that.position.left = op.left - ox;
       
   963 		}
       
   964 	}
       
   965 
       
   966 });
       
   967 
       
   968 })(jQuery);