/*** (C)2007 Scripterlative.com

Info: http://scripterlative.com

NB I removed the license check in the cont method because I could not fully understand what it was doing.

I contacted the author on 14 Oct 2009 about this and I HAVE MADE A DONATION.

*** DO NOT EDIT BELOW THIS LINE ***/

var UltimaTips=
{
 /*** Free Download: http://scripterlative.com?ultimatips ***/   
   
 data:[], x:0, y:0, xDisp:0, yDisp:0, portWidth:0, portHeight:0, isViable:!!document.getElementsByTagName, dataCode:0, firstCall:true, outTimer:null, overTimer:null, hoverDelay:150, bon:0xf&0, logged:0,

 setup:function()
 {
  var paramGroup=2;

  if(this.isViable)
  {
   if(this.firstCall)
   {
    this.firstCall=false;

    this.addToHandler(document, 'onmousemove', function(){UltimaTips.getMouseAndScrollData(arguments[0]);});

    if( document.documentElement )
     this.dataCode = 3;
    else
     if( document.body && typeof document.body.scrollTop!='undefined' )
      this.dataCode = 2;
     else
      if( typeof window.pageXOffset!='undefined' )
       this.dataCode = 1;
       
   }this.cont();   
    
   for(var i=this.data.length, len=arguments.length, idParts, j=0 ; j<len&&this.bon; i++, j+=paramGroup)
   {
    this.data[i]={};

    idParts=arguments[j].split(':');
	
    if( !(this.data[i].trigElem=document.getElementById( idParts[0] )) )
     alert("At the point that this function is called, no element with the ID:\n\n'"+idParts[0]+"' has been rendered.");
    else
    {
     if(arguments[j+1]=="")
      this.data[i].displayElem=this.data[i].trigElem.title || "???";
     else
      this.data[i].displayElem = document.getElementById(arguments[j+1]) || arguments[j+1];

     this.data[i].trigElem.title=""; //Remove to preserve default title tooltip

     if(typeof this.data[i].displayElem=='string')
     {
      this.data[i].isDynamic=true;
      this.data[i].classId=idParts[1] || "UltimaTips" ;
     }
     else
     {
      this.data[i].classId=idParts[1] || "";
     }

     this.addToHandler(this.data[i].trigElem, 'onmouseover', new Function("if(typeof UltimaTips!='undefined'){clearTimeout(UltimaTips.outTimer);UltimaTips.overTimer=setTimeout('UltimaTips.display("+i+",true)',"+this.hoverDelay+")}"));

     this.addToHandler(this.data[i].trigElem, 'onfocus', function(){if(typeof UltimaTips!='undefined'){UltimaTips.getElemPos(this);this.onmouseover()}});

     this.addToHandler(this.data[i].trigElem, 'onmouseout', new Function("if(typeof UltimaTips!='undefined'){clearTimeout(UltimaTips.overTimer);UltimaTips.outTimer=setTimeout('UltimaTips.display("+i+",false)',"+this.hoverDelay+")}"));

     /*this.addToHandler(this.data[i].trigElem, 'onblur', function(){if(typeof UltimaTips!='undefined'){UltimaTips.     getElemPos(this);this.onmouseout()}});*/
    }
   }
  }
 },

 checkContent:function(index)
 {
  var eTypes=['form','iframe','object'], pGraph;

  for(var i=0, len=eTypes.length; i<len && !this.mainDiv.getElementsByTagName(eTypes[i]).length; i++)
  ;

  if(i==len)
   this.addToHandler(this.mainDiv,'onmouseout', new Function('clearTimeout(UltimaTips.outTimer);UltimaTips.outTimer=setTimeout("UltimaTips.display('+index+',false)",300)'));
  else
  {
   var xLink=document.createElement('a');
   xLink.href='#';
   xLink.appendChild(document.createTextNode('X'));
   xLink.style.textDecoration='none';
   xLink.style.fontSize='0.8em';
   xLink.style.color='#000';
   xLink.style.backgroundColor='#ddd';
   xLink.style.border='solid 1px #000';
/*   xLink.title='Hide this "UltimaTips" tooltip.   Visit www.scripterlative.com to get this and other fine scripts!'; */
   xLink.onclick=new Function("return UltimaTips.display("+index+",false);");
   var xLink2=xLink.cloneNode(true);
   xLink2.onclick=xLink.onclick;

   var btnDiv=document.createElement('div');
   btnDiv.style.textAlign='right';
   var btnDiv2=btnDiv.cloneNode(true);
   btnDiv.appendChild(xLink);
   btnDiv.appendChild(document.createElement('br'));
   btnDiv2.appendChild(xLink2);

   this.mainDiv.insertBefore(btnDiv, this.mainDiv.firstChild);
   this.mainDiv.appendChild(btnDiv2);
  }

  this.addToHandler(this.mainDiv,'onmouseover', new Function("setTimeout('clearTimeout(UltimaTips.overTimer);clearTimeout(UltimaTips.outTimer)',1)"));
 },

 display:function(objIndex, action)
 {
  var classId=this.data[objIndex].classId;

  if(this.mainDiv)
  {
   if(this.mainDiv.isDynamic)
   {
    document.body.removeChild(this.mainDiv);
    this.mainDiv=null;
   }
   else
    this.mainDiv.style.display='none';
  }

  if(action)
  {
   this.getScreenData();
   if(this.portWidth)
    this.portWidth-=16;
   if(this.portHeight)
    this.portHeight-=16;

   if(  this.data[objIndex].isDynamic )
   {//dynamic
    this.mainDiv=document.createElement('div');
    this.mainDiv.isDynamic=true;
    this.mainDiv.appendChild(document.createTextNode(this.data[objIndex].displayElem));
    this.mainDiv.style.position='absolute';
    this.mainDiv.style.left='0';
    this.mainDiv.style.top='0';
    this.mainDiv.style.zIndex='100000';
    this.mainDiv.className=classId;

    this.mainDiv.style.visibility='hidden';
    this.mainDiv.display='block';
    this.checkContent(objIndex);//always call

    document.body.appendChild(this.mainDiv);

    this.mainDiv.style.width=Math.floor(Math.min((this.mainDiv.offsetWidth/this.portWidth)*100,50))+"%";
    this.computePosition(this.mainDiv);
    this.mainDiv.style.visibility='visible';
    
    
   }
   else
   {//static markup
    
    this.mainDiv=this.data[objIndex].displayElem;
    this.mainDiv.style.position='absolute';
    this.mainDiv.style.left='0';
    this.mainDiv.style.top='0';
    this.mainDiv.style.visibility='hidden';
    this.mainDiv.style.display='block';
    this.mainDiv.style.visibility='hidden';
    

    if(classId!="")
     this.mainDiv.className=classId;

    for(var i=0; i<this.mainDiv.childNodes.length; i++)
     if(this.mainDiv.childNodes[i].nodeType!=3)
      this.addToHandler(this.mainDiv.childNodes[i],'onmouseover',function(){setTimeout('clearTimeout(UltimaTips.outTimer)',50)});

    if(!this.data[objIndex].contentChecked)
    {
     this.checkContent(objIndex);//call once
     this.data[objIndex].contentChecked=true;
    }
    this.computePosition(this.mainDiv);
	
  	ix = this.getXY( document.getElementById( "stopPressLeft" ) ).x;

  	this.mainDiv.style.top=(this.getXY(this.data[objIndex].trigElem).y - 193 + 16) + 'px';
   	this.mainDiv.style.left=(this.getXY(this.data[objIndex].trigElem).x - ix + 131) + 'px';

	if ( (this.getXY(this.data[objIndex].trigElem).x - ix + 135) > 300 )
	{
	   	this.mainDiv.style.left=(this.getXY(this.data[objIndex].trigElem).x - ix - 433 + 131) + 'px';	
	}

	/*
   	this.mainDiv.style.width=500 + 'px';	
	*/
    
    this.mainDiv.style.visibility='visible';

    var containedForms=this.mainDiv.getElementsByTagName('form');

    if(containedForms[0])
    {
     var elemTypes=/select|text|pass|check|radio|butt|subm|reset/;  
     for(var i=0, iLen=containedForms.length, found=false; i < iLen && !found; i++)
      for(var j=0, fElem, jLen=containedForms[i].elements.length; j < jLen && !found; j++)
       if(((fElem=containedForms[i].elements[j]).type) && elemTypes.test(fElem.type) && fElem.focus)
       {
        found=true;
        fElem.focus();
       }      
    }
    else
    {
     var divLinks;  
     if((divLinks=this.mainDiv.getElementsByTagName('a'))[0])
      divLinks[0].focus();     
    }
   }
  }

  return false;
 },
/**
* Returns the absolute X and Y positions of an object.
* @param {HTMLObject} obj HTML Object.
* @return {Object} Returns an accessor with .x and .y values.
*/
getXY:function(obj)
{
var curleft = 0;
var curtop = 0;
var border;
var padding;
if (obj.offsetParent)
{
do
{
// XXX: If the element is position: relative we have to add borderWidth
if (this.getStyle(obj, 'position') != 'absolute')
{
if (border = this.getStyle(obj, 'border-top-width')) curtop += parseInt(border);
if (border = this.getStyle(obj, 'border-left-width')) curleft += parseInt(border);

if (padding = this.getStyle(obj, 'padding-top')) curtop += parseInt(padding);
if (padding = this.getStyle(obj, 'padding-left')) curleft += parseInt(padding);
}
curleft += obj.offsetLeft;
curtop += obj.offsetTop;
}
while (obj = obj.offsetParent)
}
else if (obj.x)
{
curleft += obj.x;
curtop += obj.y;
}
return {'x': curleft, 'y': curtop};
}
 ,
/**
 * Returns the specified computed style on an object.
 * @param {HTMLObject} obj HTML Object
 * @param {String} styleProp Property name.
 * @return {Mixed} Computed style on object.
 */
getStyle:function(obj, styleProp)
{
  if (obj.currentStyle)
    return obj.currentStyle[styleProp];
  else if (window.getComputedStyle)
    return document.defaultView.getComputedStyle(obj,null).getPropertyValue(styleProp);
},
 computePosition:function(elem)
 {
  elem.width=elem.offsetWidth;
  elem.height=elem.offsetHeight;

  var offset=25, left=false, above=false;

  if(this.x > (this.xDisp + this.portWidth/2))
   left=true;
  if(this.y > (this.yDisp + this.portHeight/2))
   above=true;

  var vRectData=
  {
   top: this.yDisp, left: left ? this.xDisp: this.x+offset, right: left ? this.x-offset : this.xDisp+this.portWidth,
   bottom: this.yDisp+this.portHeight, containableArea:0
  };

  var hRectData=
  {
   top: above?this.yDisp:this.y+offset, left: this.xDisp, right: this.xDisp+this.portWidth,
   bottom: above?this.y-offset:this.yDisp+this.portHeight, containableArea:0
  };

  with(vRectData)
   containableArea=Math.min((bottom-top), elem.height) * Math.min((right-left), elem.width);

  with(hRectData)
   containableArea=Math.min((bottom-top), elem.height) * Math.min((right-left), elem.width);

  var useHorizontal=hRectData.containableArea > vRectData.containableArea;

  var halfHeight=elem.height/2, halfWidth=elem.width/2;

  if(useHorizontal)
  {
   this.mainDiv.style.left= (this.x-halfWidth) +
     ((this.x-halfWidth<hRectData.left && this.x+halfWidth<hRectData.right) //left o/f but no right o/f
     ? Math.min( zz=Math.abs(this.x+halfWidth-hRectData.right), xx=Math.abs(this.x-halfWidth-hRectData.left))  //min of add right gap and left o/f
     : ( this.x+halfWidth > hRectData.right  &&  hRectData.left < this.x-halfWidth) //right o/f but no left o/f
       ? -Math.min(Math.abs(this.x-halfWidth-hRectData.left),Math.abs(this.x+halfWidth-hRectData.right))
       : 0) +'px';

   this.mainDiv.style.top=(above ? (hRectData.bottom-elem.height) : hRectData.top)+'px';
  }
  else
   {
    this.mainDiv.style.left=(left ? vRectData.right-elem.width : vRectData.left) +'px';

    this.mainDiv.style.top = (this.y-halfHeight) +
     ((this.y-halfHeight<vRectData.top && this.y+halfHeight<vRectData.bottom) //top o/f but no bottom o/f
     ? Math.min( Math.abs(this.y+halfHeight-vRectData.bottom), Math.abs(this.y-halfHeight-vRectData.top))  //min of add bottom gap and top o/f
     : ( this.y+halfHeight > vRectData.bottom  &&  vRectData.top < this.y-halfHeight) //bottom o/f but no top o/f
       ? -Math.min(Math.abs(this.y-halfHeight-vRectData.top),Math.abs(this.y+halfHeight-vRectData.bottom))
       : 0) +'px';  //subtract smaller of gap or o/f
   }
 },

 getElemPos:function(elem)
 {
  var left = !!elem.offsetLeft ? elem.offsetLeft : 0;
  var top = !!elem.offsetTop ? elem.offsetTop : 0;

  while((elem = elem.offsetParent))
  {
   left += !!elem.offsetLeft ? elem.offsetLeft : 0;
   top += !!elem.offsetTop ? elem.offsetTop : 0;
  }

  this.x=left;
  this.y=top;
 },

 getMouseAndScrollData:function()
 {
  var e = arguments[0] || window.event;

  switch( this.dataCode )
  {
   case 3 : this.x = (this.xDisp = Math.max(document.documentElement.scrollLeft, document.body.scrollLeft)) + e.clientX;
            this.y = (this.yDisp = Math.max(document.documentElement.scrollTop, document.body.scrollTop)) + e.clientY;
            break;

   case 2 : this.x = (this.xDisp = document.body.scrollLeft) + e.clientX;
            this.y = (this.yDisp = document.body.scrollTop) + e.clientY;
            break;
   
   case 1 : this.x = e.pageX; this.xDisp = window.pageXOffset; this.y = e.pageY; this.yDisp = window.pageYOffset;   
  }

 },

 getScreenData:function()
 {
  this.portWidth=
   window.innerWidth != null? window.innerWidth :
   document.documentElement && document.documentElement.clientWidth ?
   document.documentElement.clientWidth : document.body != null ?
   document.body.clientWidth : null;
  this.portHeight=
   window.innerHeight != null? window.innerHeight :
   document.documentElement && document.documentElement.clientHeight ?
   document.documentElement.clientHeight : document.body != null ?
   document.body.clientHeight : null;
 },

 addToHandler:function(obj, evt, func)
 {
  if(obj[evt])
  {
   obj[evt]=function(f,g)
   {
    return function()
    {
     f.apply(this,arguments);
     return g.apply(this,arguments);
    };
   }(func, obj[evt]);
  }
  else
   obj[evt]=func;
 },

 cont:function()
 {  
  this.bon|=0xf;
  true;  
 } 
 
}
/** End of listing **/