$.fn.positionAround = function(event, o) {

	var options = $.extend({
		around: 'mouse',
		direction: 'default',
		forceDirection: false,
		offset: [0, 0]
	}, o);

	var leftOffset	= 0,
		topOffset	= 0,
		height		= this[0].offsetHeight,
		width		= this[0].offsetWidth,
		op			= this.offsetParent(),
		sp			= $(this.scrollParent().length ? this.scrollParent() : document.body),
		spBorderTop = parseInt(op.css('borderTopWidth'),10),
		spBorderLeft= parseInt(op.css('borderLeftWidth'),10),
		opBorderTop = parseInt(op.css('borderTopWidth'),10),
		opBorderLeft= parseInt(op.css('borderLeftWidth'),10),
		opOffset	= op.offset()
		//spOffset	= sp.offset()
	;

	//Ugly fix for the issues of offset related to the body element
	opOffset = (/(html|body)/).test(op[0].tagName.toLowerCase()) ? { top: 0, left: 0 } : opOffset;
	spOffset = (/(html|body)/).test(op[0].tagName.toLowerCase()) ? { top: 0, left: 0 } : spOffset;

	var bottomEdge = (/(html|body)/).test(op[0].tagName.toLowerCase()) ? $(window).height() : spOffset.top + spBorderTop + sp.height();
	var rightEdge = (/(html|body)/).test(op[0].tagName.toLowerCase()) ? $(window).width() : spOffset.left + spBorderLeft + sp.width();

	if($(options.around).length && $(options.around)[0].nodeName) { //If around is an element

		var element = $(options.around),
			offset = element.offset(),
			relHeight = element[0].offsetHeight,
			relWidth = element[0].offsetWidth
		;

		if((/(left|right)/).test(options.direction)) {

			leftOffset = ( options.direction == 'left' ? (offset.left - spOffset.left - spBorderLeft > width || options.forceDirection) : (rightEdge-offset.left-relWidth < width && !options.forceDirection) ) ? -(width) : relWidth;
			topOffset = event ? ( bottomEdge - offset.top < height ? -(height-relHeight) : 0 ) : 0;
		} else {
			topOffset = ( options.direction == 'above' ? (offset.top - spOffset.top - spBorderTop  > height || options.forceDirection) : (bottomEdge-offset.top-relHeight < height && !options.forceDirection) ) ? -(height) : relHeight;
		}

		this.css({
			left: offset.left - opOffset.left - opBorderLeft + leftOffset + options.offset[0],
			top: offset.top - opOffset.top - opBorderTop + topOffset + options.offset[1]
		});

	} else {

		if((/(below|default)/).test(options.direction)) {
			topOffset = bottomEdge - event.pageY < height && !options.forceDirection ? -(height) : 0;
		} else if ((/above/).test(options.direction)) {
			topOffset = (event.pageY - spOffset.top - spBorderTop) > height || options.forceDirection ? -(height) : 0;
		}

		if((/(right|default)/).test(options.direction)) {
			leftOffset = rightEdge - event.pageX < width && !options.forceDirection ? -(width) : 0;
		} else if ((/left/).test(options.direction)) {
			leftOffset = (event.pageX - spOffset.left - spBorderLeft) > width || options.forceDirection ? -(width) : 0;
		}


		this.css({
			left: event.pageX - opOffset.left - opBorderLeft + leftOffset + options.offset[0],
			top: event.pageY - opOffset.top - opBorderTop + topOffset + options.offset[1]
		});

	}

};
