
var helpBubble = new function(){
	/* options = {
	 * 		'target':	Specifies element which optionss are relative to
	 *		'anchor':	Specifies which corner or side the bubble should be in relation to target ('n','s','e', or 'w')
	 * 		'x':		Specifies horizontal options of help bubble (relative to 'anchor' of 'target' if it exists otherwise absolute) (in 'px')
	 * 		'y':		Specifies vertical options of help bubble (relative to 'anchor' of 'target' if it exists otherwise absolute) (in 'px')
	 *	 	'px':		Specifies vertical location of pointer relative to help bubble element (in 'px' or '%')
	 * 		'py':		Specifies horizontal location of pointer relative to help bubble element (in 'px' or '%') 
	 * }
	 */
	var show = function(bubble,options,fade_time){
		bubble = typeof(bubble) == "string" ? $(bubble) : bubble;
		if(bubble){
			//if(!bubble.options) bubble.options = options;
			//var options = bubble.options; // SO WE CAN OVERWRITE THESE LATER ON AND HAVE THEM 'STICK'
			// SET DEFAULT VALUES
			if(fade_time == undefined)	fade_time = 0.5;
			if(typeof options != "object") options = {};
			if(options.autohide == undefined)	options.autohide = true;
			if(options.fixed) options.autohide = false;
			
			if(options.target) options.target = typeof(options.target) == "string" ? $(options.target) : options.target;
			if(options.target && options.target.nodeType != 1) options.target = null;
			if(!bubble) return false;
			if(!options.anchor) options.anchor = "n"; 	
			else options.anchor = options.anchor.toLowerCase();

			// LOAD THE ELEMENT WITH THE NECESSARY ELEMENTS 
			if(!bubble.loaded) load(bubble, options);
			document.body.appendChild(bubble);
			bubble.style.display = 'block';
			move(bubble,options);
			
			// FADE IT IN...
			if(fade_time && typeof(Animate) == "function"){
				if(document.all) var tween = Animate.Tween(bubble.style, 'filter', 'regularEaseOut', 0, 100,fade_time,')','alpha(opacity:');
				else{
					var tween = Animate.Tween(bubble.style, 'opacity', 'regularEaseOut', 0, 1,fade_time,'','');
					var tween = Animate.Tween(bubble.style, 'MozOpacity', 'regularEaseOut', 0, 1,fade_time,'');
				}
			}
			if(options.autohide){
				// MAKE IT DISAPPEAR WHEN YOU CLICK ANYWHERE
				window.setTimeout(function(){
					bubble.hide_event = addEvent(document, "mousedown", function(event){
						var s = new Date().getTime();
						for(k=(event.target?event.target:event.srcElement); k.parentNode && k.nodeName != 'BODY'; ){
							if(k == bubble) return false; 
							k = k.parentNode;
						}
						hide(bubble);
					});
				},10);
			}
		}
		return false;
	}
	var load = function(bubble, options){
		var pointer = newEl('DIV');
		var top = newEl('DIV',{'class':'top'});
		appendChildren(top,[newEl('SPAN',{'class':'l'}),newEl('SPAN',{'class':'r'})]);
		var middle = newEl('DIV',{'class':'middle','innerHTML':bubble.innerHTML});
		var close = newEl('SPAN',{'innerHTML':'X','class':'close'});
		close.onclick = function(){hide(bubble);return false;}
		middle.insertBefore(close,middle.firstChild);
		var bottom = newEl('DIV',{'class':'bottom'});
		appendChildren(bottom,[newEl('SPAN',{'class':'l'}),newEl('SPAN',{'class':'r'})]);
		removeChildren(bubble);
		appendChildren(bubble,[pointer,top,middle,bottom]);
		bubble.pointer = pointer;
		bubble.middle = middle;
		bubble.loaded = true;
	}
	var hide = function(bubble){
		bubble = typeof(bubble) == "string" ? $(bubble) : bubble;
		bubble.style.display = 'none';
		removeEvent(bubble.hide_event);
	}
	var move = function(bubble,options, already_moved){
		
		//if(options.width) bubble.style.width = options.width;
		//if(options.height) bubble.style.height = options.height;
		
		// SET POINTER CLASS
		if(options.anchor == 'e') var pointer_class = 'east';
		else if(options.anchor == 'w') var pointer_class = 'west';
		else if(options.anchor.indexOf('n') != -1) var pointer_class = 'north';
		else var pointer_class = 'south';
		bubble.pointer.className = 'pointer '+pointer_class;
		
		if(options.target){
			// FIND OUT WHAT IT'S WIDTH/HEIGHT ARE
			bubble.style.display = 'block';
			var target_pos = absPos(options.target);
			var bubble_pos = absPos(bubble);
			var point = getPoint(options.target, options.anchor, 5);
			
			var width = bubble.offsetWidth;
			var height = bubble.offsetHeight;
			var pointer_left = bubble.pointer.offsetLeft;
			var pointer_top = bubble.pointer.offsetTop;
			// NORTH & SOUTH
			if(hasClassName(bubble.pointer, 'north') || hasClassName(bubble.pointer, 'south')){
				height += bubble.pointer.offsetHeight;
				// NORTH
				if(hasClassName(bubble.pointer, 'north')){
					pointer_top += bubble.pointer.offsetHeight;
					pointer_left += bubble.pointer.offsetWidth/2;
					// CHECK IF OFF SCREEN TOP
					if((y_diff = (height - point.y)) > 0){
						if(y_diff/height > .2){
							options.anchor = 's';
						} else{
							options.width = 'auto';
							options.height = (bubble.offsetHeight - y_diff - 5)+"px";
						}
						if(!already_moved) return move(bubble, options, true);
					}
				// SOUTH
				} else{
					pointer_left += bubble.pointer.offsetWidth/2;		
				}
				// CHECK IF OFF SCREEN LEFT
				if((x_diff = (pointer_left - point.x)) > 0){
					pointer_left = point.x - 5;
					bubble.pointer.style.left = pointer_left - (bubble.pointer.offsetWidth/2) + "px";
				// CHECK IF OFF SCREEN RIGHT
				} else/* if((x_diff = (pointer_left+point.x-document.body.clientWidth)) > 0){
					
					pointer_left += x_diff;
					bubble.pointer.style.left = pointer_left - (bubble.pointer.clientWidth/2) + "px";
				}*/
				if((x_diff = (pointer_left+point.x+bubble.offsetWidth-document.body.clientWidth)) > 0){
						
						pointer_left = x_diff-pointer_left+10
						//bubble.pointer.style.left = pointer_left - (bubble.pointer.clientWidth/2) + "px";
					}
				
			// EAST & WEST
			}else{
				width += bubble.pointer.offsetWidth;
				// WEST
				if(hasClassName(bubble.pointer, 'west')){
					pointer_left += bubble.pointer.offsetWidth;
					pointer_top += bubble.pointer.offsetHeight/2;
					// CHECK IF OFF SCREEN LEFT
					if((x_diff = (width - point.x)) > 0){
						if(x_diff/width > .4){
							options.anchor = 's';
						} else{
							options.height = 'auto';
							options.width = (bubble.offsetWidth - x_diff - 5)+"px";
						}
						if(!already_moved) return move(bubble, options, true);
					}
				// EAST	
				}else{
					pointer_top += bubble.pointer.offsetHeight/2;
					if((x_diff = (pointer_left+point.x+bubble.offsetWidth-document.body.clientWidth)) > 0){
						pointer_left = x_diff-pointer_left+10
						//bubble.pointer.style.left = pointer_left - (bubble.pointer.clientWidth/2) + "px";
					}
				}
				// CHECK IF OFF SCREEN TOP
				if((y_diff = (pointer_top - point.y)) > 0){
					pointer_top = point.y - 5;
					bubble.pointer.style.top = pointer_top - (bubble.pointer.offsetHeight/2) + "px";
				}
			}
			bubble.style.left = (point.x - pointer_left)+"px";
			bubble.style.top = (point.y - pointer_top)+"px";
		} else if(options.y || options.x){
			bubble.style.top = options.y+"px";
			bubble.style.left = options.x+"px";
		}
		
	}
	var getPoint = function(el, dir, buffer){
		var pos = absPos(el);
		switch(dir){
			case 'nw': return {'x':pos.w-buffer, 		'y':pos.n-buffer};
			case 'n':  return {'x':pos.w+(pos.e-pos.w)/2, 	'y':pos.n-buffer};
			case 'ne': return {'x':pos.e+buffer, 		'y':pos.n-buffer};
			case 'e':  return {'x':pos.e+buffer, 		'y':pos.n+(pos.s-pos.n)/2};
			case 'se': return {'x':pos.e+buffer, 		'y':pos.s+buffer};
			case 's':  return {'x':pos.w+(pos.e-pos.w)/2, 	'y':pos.s+buffer};
			case 'sw': return {'x':pos.w-buffer, 		'y':pos.s+buffer};
			case 'w':  return {'x':pos.w-buffer, 		'y':pos.n+(pos.s-pos.n)/2};
		}
	}
	this.show = show;
	this.hide = hide;
}
