$.extend($.ui.resizable.prototype, {
	inverseResize: false
});

$.ui.plugin.add("resizable", "inverseResize", {

	start: function (event, ui) {
		var self = $(this).data("resizable"), o = self.options;

		var _store = function (exp) {
			$(exp).each(function() {
				var el = $(this);
				el.data("resizable-inverseresize", {
					width: parseInt(el.width(), 10), height: parseInt(el.height(), 10),
					left: parseInt(el.css('left'), 10), top: parseInt(el.css('top'), 10),
					position: el.css('position') // to reset Opera on stop()
				});
			});
		};

		if (typeof(o.inverseResize) == 'object' && !o.inverseResize.parentNode) {
			if (o.inverseResize.length) { o.inverseResize = o.inverseResize[0]; _store(o.inverseResize); }
			else { $.each(o.inverseResize, function (exp) { _store(exp); }); }
		}else{
			_store(o.inverseResize);
		}
	},

	resize: function (event, ui) {
		var self = $(this).data("resizable"), o = self.options, os = self.originalSize, op = self.originalPosition;

		var delta = {
			height: -(self.size.height - os.height) || 0, width: -(self.size.width - os.width) || 0,
			top: -(self.position.top - op.top) || 0, left: -(self.position.left - op.left) || 0
		},

		_inverseResize = function (exp, c) {
			$(exp).each(function() {
				var el = $(this), start = $(this).data("resizable-inverseresize"), style = {}, 
					css = c && c.length ? c : 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;
				});

				// Opera fixing relative position
				if ($.browser.opera && /relative/.test(el.css('position'))) {
					self._revertToRelativePosition = true;
					el.css({ position: 'absolute', top: 'auto', left: 'auto' });
				}

				el.css(style);
			});
		};

		if (typeof(o.inverseResize) == 'object' && !o.inverseResize.nodeType) {
			$.each(o.inverseResize, function (exp, c) { _inverseResize(exp, c); });
		}else{
			_inverseResize(o.inverseResize);
		}
	},

	stop: function (event, ui) {
		var self = $(this).data("resizable"), o = self.options;

		var _reset = function (exp) {
			$(exp).each(function() {
				var el = $(this);
				// reset position for Opera - no need to verify it was changed
				el.css({ position: el.data("resizable-inverseresize").position });
			});
		};

		if (self._revertToRelativePosition) {
			self._revertToRelativePosition = false;
			if (typeof(o.inverseResize) == 'object' && !o.inverseResize.nodeType) {
				$.each(o.inverseResize, function (exp) { _reset(exp); });
			}else{
				_reset(o.inverseResize);
			}
		}

		$(this).removeData("resizable-inverseresize");
	}
});
