/*
 * Tooltip - jQuery plugin  for styled tooltips
 * Copyright (c) 2006 Jörn Zaefferer, Stefan Petre
 *
 * http://bassistance.de/jquery-plugins/jquery-plugin-tooltip/
 *
 * Dual licensed under the MIT and GPL licenses:
 *   www.opensource.org/licenses/mit-license.php
 *   www.gnu.org/licenses/gpl.html
 */

(function($)
{
	var helper, current, oldTitle, tID;

	$.fn.tooltip = function(settings)
	{
		settings = $.extend($.extend({}, arguments.callee.defaults), settings || {});

		if(!helper)
		{
			helper = $('<div id="tooltip"></div>')
				.hide()
				.appendTo('body');
		}

		$(this).filter('[title]')
			.each(function(){
				this.tSettings = settings;
			})
			.bind('mouseover', save)
			.bind(settings.event, handle);

		return this;
	};

	$.fn.tooltip.defaults = {
		delay: 10,
		event: 'mouseover',
		track: true,
		top: 15,
		left: 15
	};

	function handle(event)
	{
		if(this.tSettings.delay)
		{
			tID = setTimeout(show, this.tSettings.delay);
		}

		else
		{
			show();
		}

		if(this.tSettings.track)
		{
			$('body').bind('mousemove', update);
		}

		update(event);

		$(this).bind('mouseout', hide);
	}

	function save()
	{
		if(this == current || !this.title)
		{
			return;
		}

		current = this;

		var source = $(this), settings = this.tSettings;

		oldTitle = title = source.attr('title');
		source.attr('title','');
		helper.html(title);
	}

	function show()
	{
		tID = null;

		helper.show();

		update();
	}

	function update(event)
	{
		if(current == null)
		{
			$('body').unbind('mousemove', update);
			return;
		}

		var left = helper[0].offsetLeft;
		var top = helper[0].offsetTop;

		if(event)
		{
			var left = event.pageX + 15;
			var top = event.pageY + 15;
			var right = 'auto';

			helper.css({
				left: left,
				right: right,
				top: top
			});
		}

		var v = viewport(),
			h = helper[0];

		if(v.x + v.cx < h.offsetLeft + h.offsetWidth)
		{
			left -= h.offsetWidth + 20 + 15;
			if(left >= 0)
			{
				helper.css({left: left + 'px'});
			}
		}

		if(v.y + v.cy < h.offsetTop + h.offsetHeight)
		{
			top -= h.offsetHeight + 20 + 15;

			if(top >= 0)
			{
				helper.css({top: top + 'px'});
			}
		}
	}

	function viewport()
	{
		var e = document.documentElement || {}, b = document.body || {}, w = window;

		return{
			x: w.pageXOffset || e.scrollLeft || b.scrollLeft || 0,
			y: w.pageYOffset || e.scrollTop || b.scrollTop || 0,
			cx: min(e.clientWidth, b.clientWidth, w.innerWidth ),
			cy: min(e.clientHeight, b.clientHeight, w.innerHeight )
		};

		function min()
		{
			var v = Infinity;

			for(var i = 0; i < arguments.length; i++)
			{
				var n = arguments[i];
				if(n && n < v) v = n;
			}

			return v;
		}
	}

	function hide()
	{
		if(tID)
		{
			clearTimeout(tID);
		}

		current = null;
		helper.hide();

		$(this).attr('title', oldTitle).unbind('mouseout', hide);
	}
})(jQuery);
