// Title: Tigra Hints
// URL: http://www.softcomplex.com/products/tigra_hints/
// Version: 1.2
// Date: 04/18/2003 (mm/dd/yyyy)
// Feedback: feedback@softcomplex.com (specify product title in the subject)
// Note: Permission given to use this script in ANY kind of applications if
//    header lines are left unchanged.
// About us: Our company provides offshore IT consulting services.
//    Contact us at sales@softcomplex.com if you have any programming task you
//    want to be handled by professionals. Our typical hourly rate is $20.

function TTipShow (id) {
	if (document.layers) return;
	this.hide();
	if (this.divs[id]) {
		if (this.n_dl_show) this.divs[id].timer = setTimeout("myHint.showD(" + id + ")", this.n_dl_show);
		else this.showD(id);
		this.visible = id;
	}
}

function TTipShowD (id) {
	this.move(id);
	this.showElem(id);
	if (this.n_dl_hide) this.timer = setTimeout("myHint.hide()", this.n_dl_hide);
}

function TTipMove (id) {
// This works perfectly in IE but no netscapes or mozillas. I'm gonna find out why if it kills me.
// 'id' is this instance's id tag as well as the 'name' attribute of the DIV it's in.

// X and Y of the pixel the mouse is pointed at now, adjusted for horiz/vert scrolling:
	var n_x = this.x + this.left, n_y = this.y + this.top;
// IE and MozNet act the same if this is turned off:
	if (this.b_wise) {
// width and height of the popup window.
		var n_w = this.getSize(id), n_h = this.getSize(id, true);
// width and height of the document display area of the browser (the "window").
		var n_win_w = this.getWinSz(), n_win_h = this.getWinSz(true);
// the number of pixels the window has been scrolled to the right and down.
// therefore, n_win_l means "the X of the leftmost *visible* pixel number on the page,"
// and n_win_t means "the Y of the topmost *visible* pixel on the page." Too close to win_n_t for my taste, but...
		var n_win_l = this.getWinSc(), n_win_t = this.getWinSc(true);

// Okay, they all look right in here...
//alert("n_x: "+n_x+"\nn_w: "+n_w+"\nn_win_w: "+n_win_w+"\nn_win_l: "+n_win_l);

// THIS is working perfectly too:
//alert("MouseX + tip width: "+(n_x+n_w)+"\nWin width + right-scrolled: "+(n_win_w+n_win_l)+"Adj: "+(n_win_w+n_win_l-n_w));

// this means, set X to the window's width plus the leftmost visible pixel's X minus the popup's width, but ONLY
// IF (X + popup's width) > (window's width + X of leftmost visible pixel).
		if (n_x + n_w > n_win_w + n_win_l) n_x = n_win_w + n_win_l - n_w;
// now, if the new X is less than the leftmost visible pixel's X, set it to that very number.
// Verified: this has nothing to do with the problem. It's the line above, has to be.
		if (n_x < n_win_l) n_x = n_win_l;
// This is the same thing for Y. s/width/height/, s/right/down/
		if (n_y + n_h > n_win_h + n_win_t) n_y = n_win_h + n_win_t - n_h;
		if (n_y < n_win_t) n_y = n_win_t;
	}

// n_x and n_y are always properly-set by this point. The fault isn't in here...
// it has to be in how the browser applies the new window position. Like, it's confused
// by the scrolling caused by the popup itself. See, when the popup first appears, it's
// all visible; then, for each pixel you move the mouse, the window jumps like a dozen
// pixels to the right until the popup's left edge is in-line with the mouse, and then
// it follows it around like usual but with most of it off-screen. Bottom line:
// Netscape's/Gecko's CSS-driven window rendering sucks. They'll have to fix THIS one.

	this.divs[id].o_css.left = n_x;
	this.divs[id].o_css.top = n_y;
}

function TTipHide () {
	if (this.timer) clearTimeout(this.timer);
	if (this.visible != null) {
		if (this.divs[this.visible].timer) clearTimeout(this.divs[this.visible].timer);
		setTimeout("myHint.showElem(" + this.visible + ", true)", 10);
		this.visible = null;
	}
}

function THints (o_cfg, items) {
	this.top = o_cfg.top ? o_cfg.top : 0;
	this.left = o_cfg.left ? o_cfg.left : 0;
	this.n_dl_show = o_cfg.show_delay;
	this.n_dl_hide = o_cfg.hide_delay;
	this.b_wise = o_cfg.wise;
	this.b_follow = o_cfg.follow;
	this.x = 0;
	this.y = 0;
	this.divs = [];
	this.show  = TTipShow;
	this.showD = TTipShowD;
	this.hide = TTipHide;
	this.move = TTipMove;
	if (document.layers) return;
	var b_IE = navigator.userAgent.indexOf('MSIE') > -1,
	b_NS = window.innerHeight != null,
	s_tag = ['<div id="TTip%name%" style="visibility:hidden;position:absolute;top:0px;left:0px;', b_IE ? 'width:1px;height:1px;' : '', o_cfg['z-index'] != null ? 'z-index:' + o_cfg['z-index'] : '', '"><table width="300" cellpadding="4" cellspacing="0" border="0" bgcolor="white" style="border:1px solid #777777"><tr valign="top"><td class="hint_text" nowrap>%text%</td></tr></table></div>'].join('');
//	s_tag = ['<div id="TTip%name%" style="visibility:hidden;position:absolute;top:0px;left:0px;', b_IE ? 'width:1px;height:1px;' : '', o_cfg['z-index'] != null ? 'z-index:' + o_cfg['z-index'] : '', '"><table cellpadding="0" cellspacing="0" border="0"><tr><td class="', o_cfg.css, '" nowrap>%text%</td></tr></table></div>'].join('');

	this.getElem = 
		function (id) { return document.all ? document.all[id] : document.getElementById(id); };
	this.showElem = 
		function (id, hide) { this.divs[id].o_css.visibility = hide ? 'hidden' : 'visible'; };
	this.getWinSz = b_NS
		? function (b_hight) { return b_hight ? innerHeight : innerWidth; }
		: function (b_hight) { return document.body[b_hight ? 'clientHeight' : 'clientWidth']; };	
	this.getWinSc = b_NS
		? function (b_hight) { return b_hight ? pageYOffset : pageXOffset; }
		: function (b_hight) { return document.body[b_hight ? 'scrollTop' : 'scrollLeft']; };	
	if (window.opera) {
		this.getSize = function (id, b_hight) { 
			return this.divs[id].o_css[b_hight ? 'pixelHeight' : 'pixelWidth']
		};
		document.onmousemove = function () {
			myHint.x = event.clientX;
			myHint.y = event.clientY;
			if (myHint.b_follow && myHint.visible) myHint.move(myHint.visible)
			return true;
		};
	}
	else {
		this.getSize = function (id, b_hight) { 
			return this.divs[id].o_obj[b_hight ? 'offsetHeight' : 'offsetWidth'] 
		};
		document.onmousemove = b_IE
		? function () {
			myHint.x = event.clientX + document.body.scrollLeft;
			myHint.y = event.clientY + document.body.scrollTop;
			if (myHint.b_follow && myHint.visible) myHint.move(myHint.visible);
			return true;
		} 
		: function (e) {
			myHint.x = e.pageX;
			myHint.y = e.pageY;
//			myHint.x = 0;
//			myHint.y = 0;
			if (myHint.b_follow && myHint.visible) myHint.move(myHint.visible);
			return true;
		};
	}
	for (i in items) {
		document.write (s_tag.replace(/%text%/, items[i]).replace(/%name%/, i));
		this.divs[i] = { 'o_obj' : this.getElem('TTip' + i) };
		this.divs[i].o_css = this.divs[i].o_obj.style;
	}
}
