/* creates the tooltip overlay using the title attribute as tooltip text */

if (typeof document.attachEvent!='undefined') {
   window.attachEvent('onload',init);
   document.attachEvent('onmousemove',moveMouse);
   document.attachEvent('onclick',checkMove); }
else {
   window.addEventListener('load',init,false);
   document.addEventListener('mousemove',moveMouse,false);
   document.addEventListener('click',checkMove,false);
}

var oDv,dvBdy,boxMove,lockX=0,lockY=0,ox=10,oy=10,boxLeft,boxRight,boxTop,boxBottom,evt,mouseX,mouseY;

function init() {
	oDv = document.createElement("div");
	oDv.className = "tooltipOuter";
	oDv.style.position="absolute";
	oDv.style.visibility="hidden";
	document.body.appendChild(oDv);	
}

function hasTooltip(node) {
	return (node && node.className=="tooltip" && node.title.length > 0);
}

function scanBO(curNode) {
	if (hasTooltip(curNode)) {
		curNode.boBDY=curNode.title;
		curNode.boBDY = curNode.boBDY.replace(/\\n/g, "<br />");
		curNode.boBDY = curNode.boBDY.replace("[", "<h4>");
		curNode.boBDY = curNode.boBDY.replace("]", "</h4>");
		curNode.title="";
		curNode.hasbox=1;
	}
	else {
		curNode.hasbox=2;
	}
}

function Left(elem) {	
	var x=0;
	if (elem.calcLeft) {
		return elem.calcLeft;
	}
	var oElem=elem;
	while(elem) {
		if ((elem.currentStyle)&& (!isNaN(parseInt(elem.currentStyle.borderLeftWidth)))&&(x!=0)) {
			x+=parseInt(elem.currentStyle.borderLeftWidth);
		}
		x+=elem.offsetLeft;
		elem=elem.offsetParent;
	} 
	oElem.calcLeft=x;
	return x;
}

function Top(elem) {
	var x=0;
	if (elem.calcTop) {
		return elem.calcTop;
	}
	var oElem=elem;
	while (elem) {		
		if ((elem.currentStyle)&& (!isNaN(parseInt(elem.currentStyle.borderTopWidth)))&&(x!=0)) {
			x+=parseInt(elem.currentStyle.borderTopWidth);
		}
		x+=elem.offsetTop;
		elem=elem.offsetParent;
	}
	oElem.calcTop=x;
	return x; 
}

var ab = false;
function applyStyles() {
	if (ab) {
		oDv.removeChild(dvBdy);
	}
	dvBdy = document.createElement("div");
	dvBdy.className = "tooltipInner";
	dvBdy.innerHTML = CBE.boBDY;
	ab = false;
	if (CBE.boBDY!=""){
		oDv.appendChild(dvBdy);
		oDv.style.visibility='visible';
		ab=true;
	}
}

var CSE,iterElem,LSE,CBE,LBE, totalScrollLeft, totalScrollTop, width, height;
var ini=false;

// Customised function for inner window dimension
function SHW() {
   if (document.body && (document.body.clientWidth != 0)) {
      width=document.body.clientWidth;
      height=document.body.clientHeight;
   }
   if (document.documentElement && (document.documentElement.clientWidth!=0) && (document.body.clientWidth + 20 >= document.documentElement.clientWidth)) {
      width=document.documentElement.clientWidth;   
      height=document.documentElement.clientHeight;   
   }   
   return [width,height];
}


function moveMouse(e) {
	e?evt=e:evt=event;
	CSE=evt.target?evt.target:evt.srcElement;
	
	if (!CSE.hasbox) {
	   // Note we need to scan up DOM here, some elements like TR don't get triggered as srcElement
	   iElem=CSE;
	   while ((iElem.parentNode) && (!iElem.hasbox)) {
	      scanBO(iElem);
	      iElem=iElem.parentNode;
	   }	   
	}
	
	if ((CSE!=LSE)&&(!isChild(CSE,dvBdy))){		
	   if (!CSE.boxItem) {
			iterElem=CSE;
			while ((iterElem.hasbox==2)&&(iterElem.parentNode)) {
				iterElem=iterElem.parentNode; 
			}
			CSE.boxItem=iterElem;
		}
		iterElem=CSE.boxItem;
		if (CSE.boxItem&&(CSE.boxItem.hasbox==1))  {
			LBE=CBE;
			CBE=iterElem;
			if (CBE!=LBE) {
				applyStyles();
				lockX=0;
				lockY=0;
				boxMove=true;
				ox=10;
				oy=10;
			}
		}
		else if (!isChild(CSE,dvBdy) && (boxMove))	{
			// The conditional here fixes flickering between tables cells.
			if ((!isChild(CBE,CSE)) || (CSE.tagName!='TABLE')) {   			
				CBE=null;
				hideBox();
			}
		}
		LSE=CSE;
	}
	else if (isChild(CSE,dvBdy) && boxMove) {
		totalScrollLeft=0;
		totalScrollTop=0;
		
		iterElem=CSE;
		while (iterElem) {
			if (!isNaN(parseInt(iterElem.scrollTop))) {
				totalScrollTop+=parseInt(iterElem.scrollTop);
			}
			if (!isNaN(parseInt(iterElem.scrollLeft))) {
				totalScrollLeft+=parseInt(iterElem.scrollLeft);
			}
			iterElem=iterElem.parentNode;
		}
		if (CBE!=null) {
			boxLeft=Left(CBE)-totalScrollLeft;
			boxRight=parseInt(Left(CBE)+CBE.offsetWidth)-totalScrollLeft;
			boxTop=Top(CBE)-totalScrollTop;
			boxBottom=parseInt(Top(CBE)+CBE.offsetHeight)-totalScrollTop;
			doCheck();
		}
	}
	
	if (boxMove&&CBE) {
		// This added to alleviate bug in IE6 w.r.t DOCTYPE
		bodyScrollTop=document.documentElement&&document.documentElement.scrollTop?document.documentElement.scrollTop:document.body.scrollTop;
		bodyScrollLet=document.documentElement&&document.documentElement.scrollLeft?document.documentElement.scrollLeft:document.body.scrollLeft;
		mouseX=evt.pageX?evt.pageX-bodyScrollLet:evt.clientX-document.body.clientLeft;
		mouseY=evt.pageY?evt.pageY-bodyScrollTop:evt.clientY-document.body.clientTop;
		if (CBE) {
			mouseY < -oy?lockY=-mouseY-oy:lockY=0;
			mouseX < -ox?lockX=-mouseX-ox:lockX=0;
			mouseY > (SHW()[1]-oDv.offsetHeight-oy)?lockY=-mouseY+SHW()[1]-oDv.offsetHeight-oy:lockY=lockY;
			mouseX > (SHW()[0]-dvBdy.offsetWidth-ox)?lockX=-mouseX-ox+SHW()[0]-dvBdy.offsetWidth:lockX=lockX;			
		}
		oDv.style.left=bodyScrollLet+mouseX+ox+lockX+"px";
		oDv.style.top=bodyScrollTop+mouseY+oy+lockY+"px";
	}
}

function doCheck() {	
	if ((mouseX < boxLeft) || (mouseX > boxRight) || (mouseY < boxTop) || (mouseY > boxBottom)) {
		hideBox();
		CBE=null;
	}
}

function hideBox(e) {
	oDv.style.visibility="hidden";
}

function isChild(s,d) {
	while (s) {
		if (s==d) {return true;}
		s=s.parentNode;
	}
	return false;
}

var cSrc;
function checkMove(e) {
	e?evt=e:evt=event;
	cSrc=evt.target?evt.target:evt.srcElement;
	if ((!boxMove)&&(!isChild(cSrc,oDv))) {
		hideBox();
		boxMove=true;
		CBE=null;
	}
}
