/*
 * jQuery Tooltip plugin 1.3
 * 
 * http://bassistance.de/jquery-plugins/jquery-plugin-tooltip/
 * http://docs.jquery.com/Plugins/Tooltip
 *
 * Copyright (c) 2006 - 2008 Jörn Zaefferer
 *
 * $Id: jquery.tooltip.js 5741 2008-06-21 15:22:16Z joern.zaefferer $
 * 
 * Dual licensed under the MIT and GPL licenses:
 *   http://www.opensource.org/licenses/mit-license.php
 *   http://www.gnu.org/licenses/gpl.html
 */
 
;(function($) {
	
		// the poptool element
	var helper = {},
		// the current poptool element
		current,
		// timeout id for delayed poptools
		tID, jID;

	$.poptool = {
		blocked: false,
		defaults: {
			showDelay: 200,
			hideDelay: 1400,
			top: 15,
			left: 15,
			id: "poptool",
			onClick: false
		},
		block: function() {
			$.poptool.blocked = !$.poptool.blocked;
		},
		close: function() {
			$.poptool.blocked = false;
			hide();
		}
	};

	$.fn.extend({
		poptool: function(options) {
			//Merge default settings with userdefined passed through usage
			options = $.extend({}, $.poptool.defaults, options);
			//Create the helper DIV
			createHelper(options);
			//Return each element used
			return this.each(function() {
				// save current
				current = this;

				//Store the settings as poptool
				$.data(this, "objSettings", options);

				// copy poptool into its own expando and remove the title
				$(this).removeAttr("title");

				// also remove alt attribute to prevent default poptool in IE
				$(this).alt = "";
	
				// prevent the click through on anchor tags
				$(this).click(function(event) {
					event.preventDefault();
				})

				if (!settings(current).onClick) {
					$(this).mouseover(save);
					$(this).mouseout(function() {
						if(tID)
							clearTimeout(tID);
						jID = setTimeout(hide,settings(current).hideDelay);
					});
				}
				$(this).click(save)
			})
		},
		
		hideWhenEmpty: function() {
			return this.each(function() {
				$(this)[ $(this).html() ? "show" : "hide" ]();
			});
		}
	});
	
	function settings(element) {
		return $.data(element, "objSettings");
	}
		
	function createHelper(options) {
		// there can be only one poptool helper
		if( helper.parent )
			return;
		// create the helper, h3 for title, div for url
		helper.parent = $('<div id="' + options.id + '"><div class="body"></div></div>')
			// add to document
			.appendTo(document.body)
			// hide it at first
			.hide()
		
		// save references to title and url elements
		helper.body = $('div.body', helper.parent);	
		
		helper.closeButton = $('<span class="close">close</span>')
			.prependTo(helper.parent)
			.hide()
			.click(function(){
				$.poptool.close();
			});
	}
	
	// save elements title before the poptool is displayed
	function save() {
	
		if(jID)
			clearTimeout(jID);
		
		// if this is the current source, or it has no title (occurs with click event), stop
		if ( $.poptool.blocked || (!settings(this).bodyHandler) )
			return;
		
		// if body.handler contains content first hide then show
		hide();
			
		// save current
		current = this;
		
		if ( settings(current).bodyHandler ) {
			var bodyContent = settings(current).bodyHandler.call(current);
			if (bodyContent.nodeType || bodyContent.jquery) {
				helper.body.empty().append(bodyContent)
			} else {
				helper.body.html( bodyContent );
			}
			helper.body.show();
		} else {
			helper.body.hide();
		}
		
		if ( settings(current).onClick ) {
			jID = null;
			
			//show the button
			helper.closeButton.show();

			//make the box draggable
			helper.parent.draggable();
			helper.parent.css("cursor","move");

		} else {
		
			// stop hide on mouse enters
			helper.parent.bind("mouseenter",function(e){
				if(jID)
					clearTimeout(jID);
			})
			// hide after mouse leaves
			.bind("mouseleave",function(e){
				jID = setTimeout(hide, settings(current).hideDelay);
			});
		}
			
		handle.apply(current, arguments);	
	}
	
	// main event handler to start showing poptools
	function handle(event) {
		// show helper, either with timeout or on instant
		if( settings(this).showDelay && !settings(current).onClick )
			tID = setTimeout(show, settings(this).showDelay);
		else
			show();

		// update at least once
		update(event);
	}
	
	// delete timeout and show helper
	function show() {
		tID = null;
		helper.parent.show();
		update();
	}
	
	// hide helper and restore added classes and the title
	function hide() {
		if($.poptool.blocked)
			return;

		// clear timeout if possible
		if(jID)
			clearTimeout(jID);

		// no more current element
		current = null;

		helper.closeButton.hide();
		
		helper.parent.hide()
			.css("opacity", "")
			.draggable('destroy')
			.unbind('mouseenter')
			.unbind('mouseleave');
	}

	/**
	 * callback for mousemove
	 * updates the helper position
	 * removes itself when no current element
	 */
	function update(event)	{
		if($.poptool.blocked)
			return;
		
		if (event && event.target.tagName == "OPTION") {
			return;
		}
		
		// stop updating when tracking is disabled and the poptool is visible
		if ( helper.parent.is(":visible")) {
			$(document.body).unbind('mousemove', update)
		}
		
		// if no current element is available, remove this listener
		if( current == null ) {
			$(document.body).unbind('mousemove', update);
			return;	
		}
		
		// remove position helper classes
		helper.parent.removeClass("viewport-right").removeClass("viewport-bottom");
		
		var left = helper.parent[0].offsetLeft;
		var top = helper.parent[0].offsetTop;
		if (event) {
			// position the helper 15 pixel to bottom right, starting from mouse position
			left = event.pageX + settings(current).left;
			top = event.pageY + settings(current).top;
			var right='auto';
			if (settings(current).positionLeft) {
				right = $(window).width() - left;
				left = 'auto';
			}
			helper.parent.css({
				left: left,
				right: right,
				top: top
			});
		}
		
		var v = viewport(),
			h = helper.parent[0];
		// check horizontal position
		if (v.x + v.cx < h.offsetLeft + h.offsetWidth) {
			left -= h.offsetWidth + 20 + settings(current).left;
			helper.parent.css({left: left + 'px'}).addClass("viewport-right");
		}
		// check vertical position
		if (v.y + v.cy < h.offsetTop + h.offsetHeight) {
			top -= h.offsetHeight + 20 + settings(current).top;
			helper.parent.css({top: top + 'px'}).addClass("viewport-bottom");
		}
	}
	
	function viewport() {
		return {
			x: $(window).scrollLeft(),
			y: $(window).scrollTop(),
			cx: $(window).width(),
			cy: $(window).height()
		};
	}
	
})(jQuery);
