/* Copyright (c) 2008 Kean Loong Tan http://www.gimiti.com/kltan
 * Licensed under the MIT (http://www.opensource.org/licenses/mit-license.php)
 * Copyright notice and license must remain intact for legal use
 * jHelpertip
 * Version: 1.0 (Jun 2, 2008)
 * Requires: jQuery 1.2+
 */
(function($) {

	$.fn.jHelperTip0 = function(options) {
		$(this).bind("mouseover", function(e){
			$(this).unbind("mouseover");
			$(this).jHelperTip(options);
			$(this).triggerHandler("mouseover");
		});
	};

	$.fn.jHelperTip = function(options) {
		// disable cache if user doesnt set own ttC
		if (options.source == "container" && !options.ttC)
			options.cache = false;

		// merge users option with default options
		var opts = $.extend({}, $.fn.jHelperTip.defaults, options);
		var t = new Date();
		var wait_start = 0;
		var delay_id = false;
		
		// default actions
		// create a ttC is not found
		if ($(opts.ttC).length == 0)
			$('<div id="'+opts.ttC.slice(1)+'" class="bubbling"></div>').appendTo("body");
		
		// create a dC is not found
		if ($(opts.dC).length == 0)
			$('<div id="'+opts.dC.slice(1)+'"></div>').appendTo("body");
		
		if ($(opts.aC).length == 0)
			$('<div id="'+opts.aC.slice(1)+'"></div>').appendTo("body");

		
		// initialize our tooltip and our data container and also the close box
		$(opts.ttC).add(opts.aC).css({
			position: "absolute",
			display: "inline"
		}).hide();
		
		$(opts.dC).hide();
		
		// close the tooltip box
		var closeBox = function(){
			if (opts.source == "attribute")
				$(opts.aC).hide().empty();
			else if (opts.source == "container" && opts.cache)
				$(opts.ttC).hide();
			else
				$(opts.ttC).hide().empty();
		};
		
		$(".jHelperTipClose").bind("click", closeBox);
		$(opts.ttC).bind("mouseover",function(){
			$(opts.ttC).show();
			return false;
		});

		// the sources of getting data
		var getData = function(obj,e){
			if (opts.source == "ajax") {
				opts.loadingFunc1();
				if (opts.cache && opts.cache_data) {
					$(opts.ttC).html(opts.cache_data);
					opts.loadingFunc2(opts.cache_data);
					return;
				}
				getPosition(e);
				$(opts.ttC).html(opts.loadingHtml).show();

				if (opts.wait_timeout && wait_start + opts.wait_timeout >= t.getTime()) {
					return;
				}

				delay_id = setTimeout(function(){
						wait_start = t.getTime();
						$.ajax({
							type: opts.type,
							url: opts.url,
							data: opts.data,
							success: function(msg){
								msg = opts.loadingFunc2(msg);
								opts.cache_data = msg;
								$(opts.ttC).html(msg);
								// reInitialize the close controller
								$(".jHelperTipClose").unbind("click", closeBox); 
								$(".jHelperTipClose").bind("click", closeBox);
							}
						});
					}, opts.loadingDelay);
			}

			else if (opts.source == "container" && opts.cache){
				$(opts.ttC).show();
				if ($(opts.ttC).is(":empty"))
					$(opts.dC).show().appendTo(opts.ttC);
			}

			else if (opts.source == "container"){
				$(opts.ttC).show().empty();
				$(opts.dC).clone(true).show().appendTo(opts.ttC);
			}
			
			if (opts.source == "attribute"){
				$(opts.aC).html($(obj).attr(opts.attrName));
			}
		};

		// used to position the tooltip
		var getPosition = function (e){
			var c = (opts.source == "attribute") ? $(opts.aC) : $(opts.ttC);
			var top = (e.pageY || 0)+opts.topOff;
			var left = (e.pageX || 0)+opts.leftOff;
			var w = c.width();
			var h = c.height();
			// move tooltip to top
			if (e.clientY + opts.topOff + h >= document.body.clientHeight-1) {
				top = Math.max(e.pageY - opts.topOff - h, 1);
			}          
			if (left + w >= document.body.clientWidth-1) {
				left = Math.max(e.pageX - opts.leftOff - w, 1);
			}

			c.css({
				top: top,
				left: left,
				opacity: opts.opacity
			}).show();
		};

		// just close tool tip when not needed usually trigger by anything outside out tooltip target
		if (opts.trigger == "hover") {

			var th = $(this);
		    var c = (opts.source == "attribute") ? $(opts.aC) : $(opts.ttC);
			c.bind("mouseover", function(e){
				th.triggerHandler("mouseout");
				return false;
			});

			$(this).bind("mouseover", function(e){
				e.preventDefault();
				getData(this, e);
				return false;
			});

			$(this).bind("mousemove", function(e){
				getPosition(e);
				return false;
			});
			
			$(this).bind("mouseout", function(e){
				if (delay_id) clearTimeout(delay_id);
			    if (opts.source == "attribute")
					$(opts.aC).hide().empty();
				else if (opts.source == "container" && opts.cache)
					$(opts.ttC).hide();
				else
					$(opts.ttC).hide().empty();
				return false;
			});
		}
		
		else if (opts.trigger == "click") {
			$(this).bind("click", function(e){
				getData(this, e);
				getPosition(e);
				$(document).bind("click", function(e){
					if (opts.autoClose) {
						if (opts.source == "attribute")
							$(opts.aC).hide().empty();
						else if (opts.source == "container" && opts.cache)
							$(opts.ttC).hide();
						else
							$(opts.ttC).hide().empty();
					}
				});
				
				return false;
			});

		}
	};
	
	$.fn.jHelperTip.defaults = {
		trigger: "click",
		topOff: 3,
		leftOff: 10,
		source: "container", /* attribute, container, ajax */
		attrName: '',
		ttC: "#jHelperTipContainer", /* tooltip Container*/
		dC: "#jHelperTipDataContainer", /* data Container */
		aC: "#jHelperTipAttrContainer", /* attr Container */
		opacity:  1.0,
		loadingHtml: '<div>Loading...</div>',
		loadingDelay: 200,		/* wait before sending ajax request */
		loadingFunc1: function(){},		/* start callback function for ajax request */
		loadingFunc2: function(e){return e;},		/* end callback function for ajax request */
		type: "GET", /* data can be inline or CSS selector */
		//url: '',
		//data: '',
		cache: true, /* if source is ajax - cache ajax response
						if source is container - save data in container, unique ttC for every tooltop
					 */
		wait_timeout: 2000, /* always wait for ajax response before make new one */
		autoClose: true
	};
		
	
		  

})(jQuery);