// Client file for the popup hyperlink
function PopupHyperlink()
{
    this.parentElements = [];
    this.groups = [];
    this.lastzIndex = 32000;
    this.parentGroups = null;
    this.timeoutIndex = 1;
    this.invalidateVisibleTimeout = 0;
    this.invalidateInvisibleTimeout = 300;
}
PopupHyperlink.prototype.run = function(id)
{
    var root = document.getElementById(id);
    new PopupHyperlinkRoot(root);
}
PopupHyperlink.prototype.addParentElement = function(parent, group, root)
{
    this.parentElements[this.parentElements.length] = {parent:parent, group:group, root:root};
}
PopupHyperlink.prototype.addGroup = function(parent, group)
{
    this.groups[this.groups.length] = {parent:parent, group:group, mInParentEl:false, mInTheGroup:false, mInChildGroup:false, timeout:0};
}
PopupHyperlink.prototype.mouseover = function(event)
{
    PopupHyperlink.domouseover(this);
}
PopupHyperlink.prototype.domouseover = function(element)
{
    // check if the element is a parent element
    var childGroup = null;
    var parGroup = null;
    var inParEl = false; 
    for(var i=0;i<this.parentElements.length;i++)
    {
        if (this.parentElements[i].parent == element)
        {   inParEl = true;
            childGroup = this.parentElements[i].group;
            break;            
        }
    }
    if (!childGroup)
        childGroup = element;
    // check if the element is a group
    do {
        parGroup = null;
        for(var i=0;i<this.groups.length;i++)
        {
            if (this.groups[i].group == childGroup)
            {
                parGroup = this.groups[i].parent;
                if (inParEl)
                    this.groups[i].mInParentEl = true;
                else if (!inParEl && childGroup == element)
                    this.groups[i].mInTheGroup = true;
                else 
                    this.groups[i].mInChildGroup = true; 
                childGroup = parGroup;
                break;            
            }
        }
    } while (parGroup);
    // update the groups table
    this.update(this.timeoutIndex++);
}
PopupHyperlink.prototype.mouseout = function(event)
{
    PopupHyperlink.domouseout(this);
}
PopupHyperlink.prototype.domouseout = function(element)
{
    // check if the element is a parent element
    var childGroup = null;
    var parGroup = null;
    var outParEl = false; 
    for(var i=0;i<this.parentElements.length;i++)
    {
        if (this.parentElements[i].parent == element)
        {   outParEl = true;
            childGroup = this.parentElements[i].group;
            break;            
        }
    }
    if (!childGroup)
        childGroup = element;
    // check if the element is a group
    do {
        parGroup = null;
        for(var i=0;i<this.groups.length;i++)
        {
            if (this.groups[i].group == childGroup)
            {
                parGroup = this.groups[i].parent;
                if (outParEl)
                    this.groups[i].mInParentEl = false;
                else if (!outParEl && childGroup == element)
                    this.groups[i].mInTheGroup = false;
                else 
                    this.groups[i].mInChildGroup = false; 
                this.groups[i].timeout = this.timeoutIndex;
                childGroup = parGroup;
                break;            
            }
        }
    } while (parGroup);
    // update the groups table
    this.update(this.timeoutIndex++);
}
PopupHyperlink.prototype.click = function(event)
{
    if (this && this.tagName == 'A')
        PopupHyperlink.doclick(this);
}
PopupHyperlink.prototype.doclick = function(element)
{
    for(var i=0;i<this.groups.length;i++)
    {
         this.groups[i].mInParentEl = false;
         this.groups[i].mInTheGroup = false;
         this.groups[i].mInChildGroup = false; 
         this.groups[i].timeout = this.timeoutIndex;
    }
    this.invalidateInvisible(this.timeoutIndex++);        
}
PopupHyperlink.prototype.update = function(idx)
{
    window.setTimeout("window.PopupHyperlink.invalidateVisible();", this.invalidateVisibleTimeout);
    window.setTimeout("window.PopupHyperlink.invalidateInvisible("+idx+");", this.invalidateInvisibleTimeout);
}
PopupHyperlink.prototype.invalidateVisible = function()
{
    for(var i=0;i<this.groups.length;i++)
    {
        if (this.groups[i].mInParentEl || this.groups[i].mInTheGroup || this.groups[i].mInChildGroup)
        {
            // Ensure visibility
            if (this.groups[i].group.style.display == 'none')
            {
                this.invalidateInvisible(-1);
                var el = this.groups[i].group;
                if (el.offsetParent != PopupHyperlink.parentGroups)
                {
                    PopupHyperlink.parentGroups.appendChild(el)
                    
                }

                if (el.style.position != 'absolute')
                {
                    el.style.position = 'absolute';
                    el.style.zIndex = PopupHyperlink.lastzIndex++;
                }
                el.style.visibility = 'hidden';
                el.style.display = '';
                // calculate position
              	var tx, ty;
              	var itm = this.parentElements[i].parent;
                if (this.parentElements[i].root) 
                {
  		                tx = this.offsetX(itm) - this.offsetX(el.offsetParent);
  		                ty = this.offsetY(itm) - this.offsetY(el.offsetParent) + itm.offsetHeight;
  		                // Smart position
		                if (tx + el.offsetWidth > document.body.clientWidth + document.body.scrollLeft)
		                {
			                tx = document.body.clientWidth  + document.body.scrollLeft - el.offsetWidth; 
		                }
		                if (tx <  document.body.scrollLeft)
			                tx =  document.body.scrollLeft;
                }
                else 
                {
	                tx = this.offsetX(itm) - this.offsetX(el.offsetParent) + itm.offsetWidth;
	                ty = this.offsetY(itm) - this.offsetY(el.offsetParent);
	                if (tx + el.offsetWidth > document.body.clientWidth +  document.body.scrollLeft)
	                {
		                tx = tx - el.offsetWidth - itm.offsetParent.offsetWidth; 
	                }
	                if (tx <  document.body.scrollLeft)
		                tx =  document.body.scrollLeft;
	            }
	            tx = tx - (el.offsetHeight - el.clientHeight)/2;
	            el.style.left = tx + "px";
	            el.style.top = ty + "px";
                el.style.visibility = '';
            }
        }
    }
}
PopupHyperlink.prototype.invalidateInvisible = function(idx)
{
    for(var i=0;i<this.groups.length;i++)
    {
        if ((idx == -1 || this.groups[i].timeout == idx) && !(this.groups[i].mInParentEl || this.groups[i].mInTheGroup || this.groups[i].mInChildGroup))
        {
            // Ensure visibility
            if (this.groups[i].group.style.display == '')
            {
                this.groups[i].group.style.display = 'none';
            }
        }
    }
}
PopupHyperlink.prototype.offsetX = function(o, relto)
{
    if (typeof(o) != 'object' || o == null)
        return 0;
    else
        return o.offsetLeft + this.offsetX(o.offsetParent, relto);
}
PopupHyperlink.prototype.offsetY = function(o)
{
    if (typeof(o) != 'object' || o == null)
        return 0;
    else
        return o.offsetTop + this.offsetY(o.offsetParent);
}
function PopupHyperlinkRoot(element)
{
    if (!window.PopupHyperlink.parentGroups)
        window.PopupHyperlink.parentGroups = element.offsetParent;
    this.initRoot(element);
}
PopupHyperlinkRoot.prototype.initRoot = function(control)
{
    var el = document.getElementById(control.id+'_popup');
    if (el.tagName == "TABLE" && (control.tagName == "A" || control.tagName == "TD"))
    {
        // el is a child group
        // control is a parent element
        el.onmouseover = window.PopupHyperlink.mouseover;
        el.onmouseout = window.PopupHyperlink.mouseout;
        el.onclick = window.PopupHyperlink.click;

        control.onmouseover = window.PopupHyperlink.mouseover;
        control.onmouseout = window.PopupHyperlink.mouseout;
        
        window.PopupHyperlink.addParentElement(control, el, true);
        window.PopupHyperlink.addGroup(null, el);
    }
    this.initTree(el, el);
}
PopupHyperlinkRoot.prototype.initTree = function(control, parentGroup)
{
    var group = parentGroup;
    for(var i=0;i<control.childNodes.length;i++)
    {
        var el = control.childNodes[i];
        if (typeof(el.tagName) == 'undefined')
            continue;
        if (el.tagName == "TABLE" && (control.tagName == "A" || control.tagName == "TD"))
        {
            // el is a child group
            // control is a parent element
            el.onmouseover = window.PopupHyperlink.mouseover;
            el.onmouseout = window.PopupHyperlink.mouseout;
            el.onclick = window.PopupHyperlink.click;

            control.onmouseover = window.PopupHyperlink.mouseover;
            control.onmouseout = window.PopupHyperlink.mouseout;
            group = el;
            
            window.PopupHyperlink.addParentElement(control, group, false);
            window.PopupHyperlink.addGroup(parentGroup, group);
        }
        this.initTree(el, group);
    }
}


window.PopupHyperlink = new PopupHyperlink(); 

function log(msg)
{
    if (window.dump)
        window.dump(msg);
    var l = document.getElementById('log');
    if (l)
        l.innerHTML += '<BR>'+msg;
}
function clearLog()
{
    var l = document.getElementById('log');
    if (l)
        l.innerHTML = '';
}