// initialize help object
var jshelp = new JSHelp('jshelp');

// how long (in milliseconds) before the help box is hidden
// a millisecond is 1/1000th of a second, so 1000 milliseconds equals 1 second, while 500 equals
// a half second, etc
jshelp.hide_timeout = 1000;

// the default amount of space to leave between the trigger element and the help div (pixels x, pixels y)
// this can be overridden for individual elements in the options below
// values are unsigned (can be positive or negative)
jshelp.offset = new Offset(-10, 0);

// override amount of space to leave between the trigger element and the help div (pixels x, pixels y)
// this overrides the default offset option above for individual elements or alignments
// ex: jshelp.alignoffset['botleft'] = new Offset(15, 5);  See readme.html for more info.
// ex: jshelp.divoffset['mydiv'] = new Offset(-10, 20);

// default helpbox alignment relative to the trigger element.
// Options: topleft, topcenter, topright, midleft, midcenter, midright, botleft, botcenter, botright
jshelp.helpboxalign = 'botleft';

// class name used for help divs
jshelp.div_classname = 'help';

/************************ End Configuration ************************/
var curPos = new mouseCoords();

function isIE() {
	return navigator.appName.indexOf('Microsoft') >= 0;
}
function getLeft(obj) {
	return (obj.offsetParent==null ? obj.offsetLeft : obj.offsetLeft + getLeft(obj.offsetParent));
}
function getTop(obj) {
	return (obj.offsetParent==null ? obj.offsetTop : obj.offsetTop + getTop(obj.offsetParent));
}
function in_array(needle, haystack) {
	for(var i in haystack) {
		if(haystack[i] == needle) return true;
	}
	return false;
}

function Offset(x, y) {
	this.x = x;
	this.y = y;
}
function mouseCoords(display) {
	this.x = this.y = 0;
	this.display = display;

	this.isOver = function(that) {
		if(typeof(that) == 'undefined') return;
		if(that.style.visibilty == 'hidden') return;
		var left = getLeft(that);
		var top = getTop(that);
		if(isIE()) {
			left -= document.body.scrollLeft;
			top -= document.body.scrollTop;
		}
		var right = left + that.offsetWidth;
		var bot = top + that.offsetHeight;
		return (this.x > left) && (this.x < right) && (this.y > top) && (this.y < bot);
	}
}
function eTrackCoords(e) {
	curPos.x = (isIE()) ? event.clientX : e.pageX;
	curPos.y = (isIE()) ? event.clientY : e.pageY;
	if(curPos.display) self.status = curPos.x + ' x ' + curPos.y;
}

function JSHelp(objname) {
	this.objname = objname;
	this.helpalignopts = new Array('topleft', 'topcenter', 'topright', 'midleft', 'midcenter', 'midright', 'botleft', 'botcenter', 'botright');
	this.initflag = false;
	this.helpboxes = new Array();
	this.triggers = new Array();
	this.triggerswap = new Array();
	this.divoffset = new Array();
	this.alignoffset = new Array();
	this.timer;
	this.hide_timeout = 1000;
	this.div_classname = 'divhelp';
	this.offset = new Offset(0, 0);
	this.curHelp = '';
	this.triggercount = 0;

	this.create = function() {

	}
	this.init = function() {
		// load help messages
		var tmplist = document.getElementsByTagName('div');
		for(var i=0; i<tmplist.length; ++i) {
			if(tmplist[i].className == this.div_classname && tmplist[i].id) this.helpboxes[tmplist[i].id] = tmplist[i];
		}
	
		// start mouse coord tracking
		if(isIE()) document.onmousemove = eTrackCoords;
		else {
			window.captureEvents(Event.MOUSEMOVE);
			window.onmousemove = eTrackCoords;
		}

		// set init flag
		this.initflag = true;
	}

	this.click = function(that, key, align, swapdata) {
		if(typeof(this.helpboxes[key]) == 'undefined') return;
		var thisdiv = this.helpboxes[key];
		if(thisdiv.style.visibility == 'visible') this.doHide(key);
		else this.show(that, key, align, swapdata);
	}
	this.over = function(that) {
		var key = this.getKeyByObj(that);
		if(!key || typeof(this.helpboxes[key]) == 'undefined') return;
		var thisdiv = this.helpboxes[key];
		if(thisdiv.style.visibility == 'visible') {
			clearTimeout(this.timer);
		}
	}
	this.show = function(that, key, align, swapdata) {
		if(!this.initflag) return;
		clearTimeout(this.timer);
		this.doHideAll();

		if(typeof(this.helpboxes[key]) == 'undefined') return;
		var thisdiv = this.helpboxes[key];

		if(!that.id) that.id = 'helptrigger_' + key + ++this.triggercount;
		if(swapdata) {
			this.triggerswap[key] = new Object();
			if(this.isImage(that)) {
				this.triggerswap[key].upImg = new Image(); this.triggerswap[key].upImg.src = that.src;
				this.triggerswap[key].overImg = new Image(); this.triggerswap[key].overImg.src = swapdata;
			}
			else {
				this.triggerswap[key].upClass = that.className;
				this.triggerswap[key].overClass = swapdata;
			}
		}

		this.triggers[key] = that;

		if(typeof(this.triggerswap[key]) != 'undefined') {
			if(this.isImage(that) && this.triggerswap[key].upImg) {
				that.src = this.triggerswap[key].overImg.src;
			}
			else if(this.triggerswap[key].overClass) {
				that.className = this.triggerswap[key].overClass;
			}
		}

		// helpboxalign
		// topleft, topcenter, topright, midleft, midcenter, midright, botleft, botcenter, botright
		if(!align) align = this.helpboxalign;
		align = align.toLowerCase();
		if(!in_array(align, this.helpalignopts)) align = this.helpboxalign;
		var alignkey = align;
		var valign = align.substr(0, 3);
		align = align.substr(3);

		var offsetx = this.offset.x;
		var offsety = this.offset.y;
		if(typeof(this.alignoffset[alignkey]) != 'undefined') {
			offsetx = this.alignoffset[alignkey].x;
			offsety = this.alignoffset[alignkey].y;
		}
		if(typeof(this.divoffset[key]) != 'undefined') {
			offsetx = this.divoffset[key].x;
			offsety = this.divoffset[key].y;
		}

		// figure out position
		var postop = posleft = 0;
		var thisdivheight = thisdiv.offsetHeight;
		var thisdivwidth = thisdiv.offsetWidth;

		switch(align) {
			case 'left':
				posleft = getLeft(that) - offsetx;
				break;

			case 'center':
				posleft = getLeft(that) + (that.offsetWidth / 2);
				posleft -= thisdivwidth / 2;
				break;

			case 'right':
				posleft = getLeft(that) + that.offsetWidth;
				posleft -= thisdivwidth - offsetx;
				break;
		}

		switch(valign) {
			case 'top':
				postop = getTop(that) - offsety;
				postop -= thisdivheight;
				break;

			case 'mid':
				postop = getTop(that) + (that.offsetHeight / 2)
				postop -= thisdivheight / 2;
				if(align == 'left') posleft = getLeft(that) - thisdivwidth - offsetx;
				else if(align == 'right') posleft = getLeft(that) + that.offsetWidth + offsetx;
				break;

			case 'bot':
				postop = getTop(that) + offsety;
				postop += that.offsetHeight;
				break;
		}

		// make sure the help box fits on the screen vertically

		var divbot = postop + thisdivheight;
		var screenbot = document.body.clientHeight + document.body.scrollTop;
		var screentop = screenbot - document.body.clientHeight;
		if(screenbot < divbot) postop = screenbot - thisdivheight - 1;
		else if(postop < screentop) postop = screentop;

		// now make sure it fit's horizontally

		var divright = posleft + thisdivwidth;
		var screenright = document.body.clientWidth + document.body.scrollLeft;
		var screenleft = screenright - document.body.clientWidth;
		if(screenright < divright) posleft = screenright - thisdivwidth - 1;
		else if(posleft < screenleft) posleft = screenleft;

		// position & display
		thisdiv.style.left = posleft;
		thisdiv.style.top = postop;
		thisdiv.left = posleft;
		thisdiv.right = posleft + thisdivwidth;
		thisdiv.top = postop;
		thisdiv.bot = postop + thisdivheight;
		thisdiv.style.visibility = 'visible';
	}
	this.hide = function(that) {
		if(!this.initflag) return;
		var key = this.getKeyByObj(that);
		clearTimeout(this.timer);
		this.timer = setTimeout("window."+this.objname+".startDoHide('"+key+"')", this.hide_timeout);
	}

	this.startDoHide = function(key) {
		if(curPos.isOver(this.helpboxes[key])) this.hide(this.triggers[key]);
		else this.doHide(key);
	}
	this.doHide = function(key) {
		if(typeof(this.triggers[key]) != 'undefined' && typeof(this.triggerswap[key]) != 'undefined') {
			if(this.isImage(this.triggers[key]) && this.triggerswap[key].upImg) {
				this.triggers[key].src = this.triggerswap[key].upImg.src;
			}
			else if(this.triggerswap[key].upClass) {
				this.triggers[key].className = this.triggerswap[key].upClass;
			}
		}
		if(typeof(this.helpboxes[key]) != 'undefined') this.helpboxes[key].style.visibility = 'hidden';
		else this.doHideAll();
	}
	this.doHideAll = function() {
		for(var k in this.helpboxes) this.doHide(k);
	}

	this.getKeyByObj = function(obj) {
		for(var key in this.triggers) {
			if(obj.id == this.triggers[key].id) return key;
		}
		return '';
	}
	this.isImage = function(that) {
		return(that.tagName == 'IMG' || that.tagName == 'IMAGE');
	}


	this.create();
}