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

(function($) {
	var helper = {},
		current,
		title,
		tID,
		IE = $.browser.msie && /MSIE\s(5\.5|6\.)/.test(navigator.userAgent);
		
	$.fn.extend({
		Tooltip: function(settings) {
			settings = $.extend({}, $.Tooltip.defaults, settings);
			createHelper();
			this.filter('[@title]')
				.each(function() {
					this.tSettings = settings;
				})
				.bind("mouseover", save)
				.bind(settings.event, handle);
			return this;
		},
		fixPNG: IE ? function() {
			return this.each(function () {
				var image = $(this).css('backgroundImage');
				if (image.match(/^url\(["'](.*\.png)["']\)$/i)) {
					image = RegExp.$1;
					$(this).css({
						'backgroundImage': 'none',
						'filter': "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image + "')"
					}).each(function () {
						var position = $(this).css('position');
						if (position != 'absolute' && position != 'relative')
							$(this).css('position', 'relative');
					});
				}
			});
		} : function() { return this; },
		unfixPNG: IE ? function() {
			return this.each(function () {
				$(this).css({'filter': '', backgroundImage: ''});
			});
		} : function() { return this; },
		getAndSetAttr: function(name, value) {
			var result = this.attr(name);
			this.attr(name, value);
			return result;
		},
		hideWhenEmpty: function() {
			return this.each(function() {
				$(this)[ $(this).html() ? "show" : "hide" ]();
			});
		},
		url: function() {
			return this.attr('href') || this.attr('src');
		}
	});
	
	function createHelper() {
		if( helper.parent )
			return;
		helper.parent = $('<div id="tooltip"><h3></h3><p class="body"></p><p class="url"></p></div>')
			.hide()
			.css({ position: 'absolute', zIndex: "3000" })
			.appendTo('body');
		helper.title = $('h3', helper.parent);
		helper.body = $('p.body', helper.parent);
		helper.url = $('p.url', helper.parent);
	}
	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);
		if (this.tSettings.event != "click")
			$(this).bind('click', hide);
		$(this).bind('mouseout', hide);
	}
	function save() {
		if(this == current || !this.title)
			return;
		current = this;
		title = $(this).getAndSetAttr('title', '');
		if ( this.tSettings.bodyHandler ) {
			helper.title.hide();
			helper.body.html( this.tSettings.bodyHandler.call(this) ).show();
		} else if ( this.tSettings.showBody ) {
			var parts = title.split(this.tSettings.showBody);
			helper.title.html(parts.shift()).show();
			helper.body.empty();
			for(var i = 0, part; part = parts[i]; i++) {
				if(i > 0)
					helper.body.append("<br/>");
				helper.body.append(part);
			}
			helper.body.hideWhenEmpty();
		} else {
			helper.title.html(title).show();
			helper.body.hide();
		}
		if( this.tSettings.showURL && $(this).url() )
			helper.url.html( $(this).url().replace('http://', '') ).show();
		else 
			helper.url.hide();
		helper.parent.addClass(this.tSettings.extraClass);
		if (this.tSettings.fixPNG )
			helper.parent.fixPNG();
	}
	function show() {
		tID = null;
		helper.parent.show();
		update();
	}
	function update(event)	{
		if( current == null ) {
			$('body').unbind('mousemove', update);
			return;	
		}
		
		var left = helper.parent[0].offsetLeft;
		var top = helper.parent[0].offsetTop;
		if(event) {
			left = event.pageX + 15;
			top = event.pageY + 15;
			helper.parent.css({
				left: left + 'px',
				top: top + 'px'
			});
		}
		
		var v = viewport(),
			h = helper.parent[0];
		if(v.x + v.cx < h.offsetLeft + h.offsetWidth) {
			left -= h.offsetWidth + 20;
			helper.parent.css({left: left + 'px'});
		}
		if(v.y + v.cy < h.offsetTop + h.offsetHeight) {
			top -= h.offsetHeight + 20;
			helper.parent.css({top: top + 'px'});
		}
	}
	
	function viewport() {
		var e = document.documentElement || {},
			b = document.body || {},
			w = window;
		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;
		}
		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 hide(event) {
		if(tID)
			clearTimeout(tID);
		current = null;
		helper.parent.hide().removeClass( this.tSettings.extraClass );
		if (event.type != "click") {
			$(this)
				.attr('title', title)
				.unbind('mouseout', hide);
		}
		if (this.tSettings.event != "click")
			$(this).unbind('click', hide);
			
		if( this.tSettings.fixPNG )
			helper.parent.unfixPNG();
	}
	
	$.Tooltip = {};
	$.Tooltip.defaults = {
		delay: 250,
		event: "mouseover",
		showURL: true,
		extraClass: ""
	};

})(jQuery);