// voxTip - a full featured, light-weight, customizable tooltip based on jQuery 1.3
// c) 2010 Samuel Lee
// inspired by colortip and prototip

(function($) {
	
	$.extend($.fn, {
		
		tooltip : function(options) {
			var defaults = {
				position: 'bottom-center',
				popupType: 'default',
				source: 'child-attr',
				sourceSelector: false,
				sourceAttr: 'title',
				showPointer: true,
				additionalClasses: false,
				waitDuration: 700,
				fadeDuration: 500
			};
			var options = $.extend(defaults, options);
			var showTip;
			
			$().tooltipCreate(options);
			
			return this.each(function() {
				$(this).initTarget();
				$(this).hover(
					function(event){
						
						var element = $(this);
						showTip = window.setTimeout(function() {
							element.data('tipActive', true);
							content = element.getContent(options);
							popup = $().tooltipElement(options);
							popup.setContent(options,content);
							
							/*
							$(this).mousemove(function(e){
								target = $(this).getTargetMouse(e);
								$().setPopupPosition(options,target,popup);
							}); 
							*/
							
							target = element.getTargetElement();
							$().setPopupPosition(options,target,popup);
							popup.stop(true, true).fadeIn(options.fadeDuration);
						}, options.waitDuration);
					},
					function(){
						element = $(this);
						if (element.data('tipActive')) {
							element.removeData('tipActive');
							popup = $().tooltipElement(options);
							popup.stop(true, true).fadeOut(options.fadeDuration); 
						} else {
							window.clearTimeout(showTip);
						}
					}
				);
			});
		},
		
		tooltipCreate: function(options){
		
			classHtml = options.additionalClasses!==false ? ' class="'+options.additionalClasses+'"' : '';
		
			if(options.popupType=='default') {
				$tooltip_html = $('<span id="tooltip_html"'+classHtml+'></span>');
				$tooltip_content = $('<span class="container"><span class="content"></span><span class="point_border"></span><span class="point"></span></span>');
				$tooltip_html.append($tooltip_content);
				$('body').append($tooltip_html);
			}
			else if(options.popupType=='source') {
				$tooltip_html = $('<span id="tooltip_html"'+classHtml+'></span>');
				$('body').append($tooltip_html);
			}
		},
		
		tooltipElement: function(options){
			return $('#tooltip_html');
		},
		
		initTarget: function(){
			anchors = $(this).find('a');
			anchors.each(function(){
				value = $(this).attr('title');
				$(this).attr('title','');
				$(this).data('title',value);
			});
		},
		
		setPopupPosition: function(options,target,popup){
			
			popupPos = $().tooltipPosition(options,target,popup);
			popupX = popupPos.x;
			popupY = popupPos.y;
			
			popup.css('top',popupY);
			popup.css('left',popupX);
		},
		
		getContent: function(options){
			temp = options.source.split('-');
			selectorType = temp[0];
			sourceType = temp[1];
			content = '';
			
			switch(selectorType){
				case 'current':
					selector = $(this);
				break;
				
				case 'child':
					if(options.sourceSelector===false)
						return '';
					selector = $(this).find(options.sourceSelector);
				break;
				
				case 'parent':
					if(options.sourceSelector===false)
						return '';
					selector = $(this).parents(options.sourceSelector);
				break;
				
				case 'global':
					if(options.sourceSelector===false)
						return '';
					selector = $(options.sourceSelector);
				break;
			}
			
			switch(sourceType){
				case 'attr':
					if(options.sourceAttr===false || options.sourceAttr==='')
						return '';
					content = selector.getAttr(options.sourceAttr);
				break;
				
				case 'html':
					content = selector.html();
				break;
				
				case 'val':
					content = selector.val();
				break;
				
				case 'text':
					content = selector.text();
				break;
			}
			return content;
		},
		
		getAttr: function(attr){
			
			if(attr=='title') {
				value = $(this).data(attr);
			}
			else {
				value = $(this).attr(attr);
			}
			return value;
		},
		
		setContent: function(options,content){
			if(options.popupType=='source')
				$(this).html(content);
			else
				$(this).find('.content').html(content);
		},
		
		setPointer: function(position){
		
		/*receives position.side & position.alignment as pointer direction*/
			position_class = 'side_'+position.side+' alignment_'+position.alignment;
			$(this).attr('class',position_class);
		},

		tooltipPositionSuggestion: function(target,popup,defaultPosition) {

			targetRelX = target.relX;
			targetRelY = target.relY;
			targetHeight = target.height;
			targetWidth = target.width;
			popupHeight = popup.outerHeight();
			popupWidth = popup.outerWidth();

			viewportMinX = 0;
			viewportMaxX = $(window).width();
			viewportMinY = 0;
			viewportMaxY = window.innerHeight ? window.innerHeight : $(window).height();
			
			
			popupMinX = targetRelX - popupWidth;
			popupCtrMinX = targetRelX + (targetWidth/2) - (popupWidth/2);
			popupCtrMaxX = targetRelX + (targetWidth/2) + (popupWidth/2);
			popupMaxX = targetRelX + popupWidth;
			
			popupMinY = targetRelY - popupHeight;
			popupCtrMinY = targetRelY + (targetHeight/2) - (popupHeight/2);
			popupCtrMaxY = targetRelY + (targetHeight/2) + (popupHeight/2);
			popupMaxY = targetRelY + popupHeight;
			popupPosition = defaultPosition;
			
			$.each(defaultPosition,function(index,position){
				
				newPosition = position;
				switch(position){
					case 'top':
						if(popupMinY < viewportMinY)
							newPosition = 'bottom';
					break;
					
					case 'bottom':
						if(popupMaxY > viewportMaxY)
							newPosition = 'top';
					break;
					
					case 'middle':
						if(popupCtrMinY < viewportMinY)
							popupPositionY = 'bottom';
						else if(popupCtrMaxY > viewportMaxY)
							newPosition = 'top';
					break;
				
					case 'left':
						if(popupMinX < viewportMinX)
							newPosition = 'right';
					break;
					
					case 'right':
						if(popupMaxX > viewportMaxX)
							newPosition = 'left';
					break;
					
					case 'center':
						
						if(popupCtrMinX < viewportMinX)
							newPosition = 'right';
						else if(popupCtrMaxX > viewportMaxX)
							newPosition = 'left';
					break;
					
				}
				
				popupPosition[index] = newPosition;
			});
			return popupPosition;
		},

		getTargetElement: function(){
			target = $(this);
			targetPos = target.position();
			targetData = new Array();
			
			targetData['relX'] = targetPos.left;
			targetData['relY'] = targetPos.top;
			/*
			targetData['relX'] = target.offset().left;
			targetData['relY'] = target.offset().top;
			*/
			targetData['height'] = target.outerHeight();
			targetData['width'] = target.outerWidth();
			targetData['absX'] = target.offset().left;
			targetData['absY'] = target.offset().top;
			return targetData;
		},
		
		getTargetMouse: function(e){
			target = $(this); 
			targetData = new Array();
			targetData['relX'] = e.pageX;
			targetData['relY'] = e.pageY;
			targetData['height'] = 0;
			targetData['width'] = 0;
			targetData['absX'] = targetData['relX'] - target.offset().left;
			targetData['absY'] = targetData['relY'] - target.offset().top;
			
			return targetData;
		},
		
		tooltipPosition : function(options,target,popup){
		
			targetAbsX = target.absX;
			targetAbsY = target.absY;
			targetHeight = target.height;
			targetWidth = target.width;
			
			popupHeight = popup.outerHeight();
			popupWidth = popup.outerWidth();
			optionPosition = options.position.split('-');
			defaultPosition = {side: optionPosition[0], alignment: optionPosition[1]};
			popupPosition = $().tooltipPositionSuggestion(target,popup,defaultPosition);
			var popupX = popupY = 0;
			
			if(options.showPointer)
				popup.setPointer(popupPosition);
			
			$.each(popupPosition,function(index,position){
			switch(position){
				case 'top':
					popupY = targetAbsY - popupHeight;
				break;
				
				case 'bottom':
					popupY = targetAbsY + targetHeight;
				break;
				
				case 'middle':
					popupY = targetAbsY + (targetHeight/2) - (popupHeight/2);
				break;
			
				case 'left':
					popupX = targetAbsX - popupWidth;
				break;
				
				case 'right':
					popupX = targetAbsX + targetWidth;
				break;
				
				case 'center':
					popupX = targetAbsX + (targetWidth/2) - (popupWidth/2);
				break;
			}
			});
			
			return {x: popupX, y: popupY};
		}
	});
})(jQuery); 
