//
// Constants
//
var POPUP_LAYER_BLANK_IMAGE                    = "../images/blank.gif";
var POPUP_LAYER_DEFAULT_IMAGE_CLASS_NAME       = "popupLayerImage";
var POPUP_LAYER_DEFAULT_POPUP_LAYER_CLASS_NAME = "popupLayer";
var POPUP_LAYER_ID_PREFIX                      = "popupLayer_";
var POPUP_LAYER_POPUP_LAYER_ID                 = "popupLayer";
var POPUP_LAYER_INITIATION_TIMEOUT             = 100; // in milliseconds
var POPUP_LAYER_TERMINATION_TIMEOUT            = 100; // in milliseconds
var POPUP_LAYER_DEFAULT_X_OFFSET               = 0; // in pixels
var POPUP_LAYER_DEFAULT_Y_OFFSET               = 0; // in pixels

var SCROLLBAR_HEIGHT                           = 20; /* in pixels - an approximation */
var SCROLLBAR_WIDTH                            = 20;

//
// Hash table of all popup layer objects on the screen
//
var _popupLayers = {};

//
// Object that manages the popup layer objects, including popping them up and down
//
var _popupLayerController = null;

function PopupLayerController()
{
	this.setCurrentLayerId = plc_setCurrentLayerId;
	this.getCurrentLayerId = plc_getCurrentLayerId;
	this.setCurrentLayerId(null);
	
	this.setTimerId = plc_setTimerId;
	this.getTimerId = plc_getTimerId;
	this.setTimerId(0);
	
	this.setPageX = plc_setPageX;
	this.getPageX = plc_getPageX;
	this.setPageX(0);
	
	this.setPageY = plc_setPageY;
	this.getPageY = plc_getPageY;
	this.setPageY(0);
	
	this.getPopupLayer = plc_getPopupLayer;
	
	this.setMouseInsideImage = plc_setMouseInsideImage;
	this.isMouseInsideImage = plc_isMouseInsideImage;
	this.setMouseInsideImage(false);
	
	this.setMouseInsidePopupLayer = plc_setMouseInsidePopupLayer;
	this.isMouseInsidePopupLayer = plc_isMouseInsidePopupLayer;
	this.setMouseInsidePopupLayer(false);
	
	this.startInitiationTimer = plc_startInitiationTimer;
	this.stopInitiationTimer = plc_stopInitiationTimer;
	
	this.startTerminationTimer = plc_startTerminationTimer;
	this.stopTerminationTimer = plc_stopTerminationTimer;
	
	this.initiateHelp = plc_initiateHelp;
	this.terminateHelp = plc_terminateHelp;
	
	return this;
}

function plc_setCurrentLayerId(currentLayerId)
{
	this.currentLayerId = currentLayerId;
}

function plc_getCurrentLayerId()
{
	return this.currentLayerId;
}

function plc_getPopupLayer()
{
	var layer = document.getElementById(POPUP_LAYER_POPUP_LAYER_ID);
	if (layer == null)
	{
		layer = document.createElement("div");
		layer.id = POPUP_LAYER_POPUP_LAYER_ID;
		layer.className = POPUP_LAYER_DEFAULT_POPUP_LAYER_CLASS_NAME;
		layer.onmouseover = eval('new Function(\'_popupLayerPopupLayerMouseOverEvent()\')'); 
		layer.onmouseout = eval('new Function(\'_popupLayerPopupLayerMouseOutEvent()\')'); 
		document.body.appendChild(layer);
	}
	
	return layer;
}

function plc_setMouseInsideImage(mouseInsideImage)
{
	this.mouseInsideImage = mouseInsideImage;
}

function plc_isMouseInsideImage()
{
	return this.mouseInsideImage;
}

function plc_setMouseInsidePopupLayer(mouseInsidePopupLayer)
{
	this.mouseInsidePopupLayer = mouseInsidePopupLayer;
}

function plc_isMouseInsidePopupLayer()
{
	return this.mouseInsidePopupLayer;
}

function plc_setTimerId(timerId)
{
	this.timerId = timerId;
}

function plc_getTimerId()
{
	return this.timerId;
}

function plc_setPageX(pageX)
{
	this.pageX = pageX;
}

function plc_getPageX()
{
	return this.pageX;
}

function plc_setPageY(pageY)
{
	this.pageY = pageY;
}

function plc_getPageY()
{
	return this.pageY;
}

function plc_terminateHelp()
{
	if (this.isMouseInsideImage() || this.isMouseInsidePopupLayer())
	{
		this.startTerminationTimer();
		return;
	}
	else
	{
		this.stopTerminationTimer();
		this.stopInitiationTimer();

		var rollover = this.getPopupLayer();
		if (rollover != null)
		{
			rollover.style.display = "none";
			rollover.style.width = "";
			if (is_ie5up && !is_ie7up)
			{
				showObjects("SELECT", rollover); // Needed only for IE 6.0-
			}
		}
	}
}

function getPopupLayerController()
{
	if (_popupLayerController == null)
	{
		//
		// Create the popup layer controller.  This object manages all the popup layer
		// objects for the screen.
		//
		_popupLayerController = new PopupLayerController();
		
		//
		// Create a handler which will ensure that the currently-presented popup layer
		// pop-up layer will be hidden if the user clicks outside of the layer and outside
		// of the popup layer image.  This handler should be set up exactly once per
		// screen.
		//
		_popupLayerCascadeOnclick = document.onclick != null ? document.onclick : new Function;
		document.onclick = function()
		{
			var plc = getPopupLayerController();
			if (!plc.isMouseInsideImage() && !plc.isMouseInsidePopupLayer())
			{
				plc.terminateHelp();
			}
			
			_popupLayerCascadeOnclick();
		}
	}
	
	return _popupLayerController;
}

function _popupLayerImageMouseClickEvent(e, id)
{
	//
	// Hide the currently-presented popup layer, if any
	//
	var plc = getPopupLayerController();
	plc.terminateHelp();

	//
	// Track the popup layer that the user clicked
	//
	plc.setCurrentLayerId(id);

	//
	// Keep track of the fact that the mouse is inside the popup layer image
	//
	plc.setMouseInsideImage(true);

	//
	// Present the popup layer
	//
	plc.initiateHelp();
}

function _popupLayerPopupLayerMouseOverEvent()
{
	//
	// Keep track of the fact that the cursor is over the rollover's pop-up layer
	//
	var plc = getPopupLayerController();
	plc.setMouseInsidePopupLayer(true);
}

function _popupLayerImageMouseOverEvent(e, id)
{
	//
	// If the cursor was not already over the popup layer image, start the popup layer
	// timer
	//
	var plc = getPopupLayerController();
	if (!plc.isMouseInsideImage())
	{
		//
		// Keep track of the popup layer the cursor is over
		//
		plc.setCurrentLayerId(id);
		
		//
		// Keep track of where the cursor is
		//
		e = e ? e : window.event;
		if (is_ie)
		{
			plc.setPageX(e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft);
			plc.setPageY(e.clientY + document.body.scrollTop + document.documentElement.scrollTop);
		}
		else
		{
			plc.setPageX(e.pageX);
			plc.setPageY(e.pageY);
		}
		
		//
		// Keep track of the fact that the cursor is inside the popup layer image
		//
		plc.setMouseInsideImage(true);
		
		//
		// Start the timer that, once expired, will present the popup layer
		//
		plc.startInitiationTimer();
	}
}

function _popupLayerPopupLayerMouseOutEvent()
{
	//
	// Keep track of the fact that the cursor is no longer inside the popup layer's
	// pop-up layer
	//
	var plc = getPopupLayerController();
	plc.setMouseInsidePopupLayer(false);
}

function _popupLayerImageMouseOutEvent(e)
{
	//
	// Keep track of the fact that the cursor is no longer inside the popup layer's
	// image
	//
	var plc = getPopupLayerController();
	plc.setMouseInsideImage(false);
	
	//
	// Start the timer that, once expired, will make the popup layer pop-up layer
	// disappear
	//
	plc.startTerminationTimer();
}

function plc_startInitiationTimer()
{
	//
	// Stop all timers
	//
	this.stopInitiationTimer();
	this.stopTerminationTimer();
	
	//
	// Start the timer that, once expired, will present the popup layer
	//
	var timerId = setTimeout("getPopupLayerController().initiateHelp()", POPUP_LAYER_INITIATION_TIMEOUT);
	this.setTimerId(timerId);
}

function plc_startTerminationTimer()
{
	//
	// Stop all timers
	//
	this.stopTerminationTimer();
	this.stopInitiationTimer();
	
	//
	// Start the timer that, once expired, will make the popup layer disappear
	//
	var timerId = setTimeout("getPopupLayerController().terminateHelp()", POPUP_LAYER_TERMINATION_TIMEOUT);
	this.setTimerId(timerId);
}

function plc_initiateHelp()
{
	if (!this.isMouseInsideImage())
	{
		this.startInitiationTimer();
		return;
	}
	else
	{
		//
		// Get the coordinates where the popup layer DIV should be placed
		//
		var rh = _popupLayers[this.getCurrentLayerId()];
		var button = document.getElementById(this.getCurrentLayerId());
		var buttonLeft   = button.offsetLeft;
		var buttonTop    = button.offsetTop;
		var buttonParent = button.offsetParent;
		while (buttonParent != null)
		{
			buttonLeft  += buttonParent.offsetLeft;
			buttonTop   += buttonParent.offsetTop;
			buttonParent = buttonParent.offsetParent;
		}

		//
		// Set the CSS class for this particular popup layer
		//
		var rollover = this.getPopupLayer();
		rollover.className = rh.getPopupLayerClassName();

		//
		// Put the help text into the popup layer DIV
		//
		var html = rh.getInnerHtml();
		rollover.innerHTML = html;

		//
		// Show the popup layer DIV
		//
		rollover.style.top  = buttonTop + button.offsetHeight + 'px';
		//rollover.style.left = (buttonLeft + button.offsetWidth + rh.getXOffset()) + 'px';
		rollover.style.left = (buttonLeft + rh.getXOffset()) + 'px';
		rollover.style.display = "inline";
	
		//
		// Attempt to ensure the popup layer DIV fits vertically on the page
		//
		var windowSize = getWindowSize();
		var scrollCoords = getScrollbarCoordinates();
		var windowBottom = scrollCoords.y + windowSize.height;
		if (is_firefox)
		{
			windowBottom -= SCROLLBAR_HEIGHT; // Firefox needs to account for the horizontal scrollbar
		}
		
		var rolloverBottom = rollover.offsetTop + rollover.offsetHeight;
		if (rolloverBottom > windowBottom)
		{
			rollover.style.top = (parseInt(rollover.style.top) - (rolloverBottom - windowBottom)) + 'px';
		}
		
		//
		// Attempt to ensure the DIV fits horizontally on the page
		//
		if (buttonLeft + button.offsetWidth + rollover.offsetWidth + SCROLLBAR_WIDTH > windowSize.width)
		{
			rollover.style.width = (windowSize.width - buttonLeft - button.offsetWidth - SCROLLBAR_WIDTH) + 'px';
		}
		else
		{
			rollover.style.width = '';
		}
	
		//
		// Hide all <select> elements that are underneath the dropdown DIV.  Needed for IE 6.0- only.  <select>
		// elements have a z-index of infinity in IE 6.0-.  That is, no matter what you set the z-index to for
		// any element, it will appear behind a <select> object.  The only option is to hide the overlapping
		// <select> objects while the dropdown is presented.
		//
		if (is_ie5up && !is_ie7up)
		{
			hideObjects("SELECT", rollover); // Needed for IE 6.0- only
		}
	}
}

function plc_stopInitiationTimer()
{
	if (this.getTimerId() > 0)
	{
		clearTimeout(this.getTimerId());
		this.setTimerId(0);
	}
}
	
function plc_stopTerminationTimer()
{
	if (this.getTimerId() > 0)
	{
		clearTimeout(this.getTimerId());
		this.setTimerId(0);
	}
}
	
function PopupLayer(id)
{
	this.setId = pl_setId;
	this.getId = pl_getId;
	var len = 0;
	for (var rh in _popupLayers)
	{
		len++;
	}
	this.setId(id);

	this.setImageClassName = pl_setImageClassName;
	this.getImageClassName = pl_getImageClassName;
	this.setImageClassName(POPUP_LAYER_DEFAULT_IMAGE_CLASS_NAME);
	
	this.setPopupLayerClassName = pl_setPopupLayerClassName;
	this.getPopupLayerClassName = pl_getPopupLayerClassName;
	this.setPopupLayerClassName(POPUP_LAYER_DEFAULT_POPUP_LAYER_CLASS_NAME);
	
	this.setInnerHtml = pl_setInnerHtml;
	this.getInnerHtml = pl_getInnerHtml;
	this.setInnerHtml(' ');

	this.setXOffset = pl_setXOffset;
	this.getXOffset = pl_getXOffset;
	this.setXOffset(POPUP_LAYER_DEFAULT_X_OFFSET);
	
	this.setYOffset = pl_setYOffset;
	this.getYOffset = pl_getYOffset;
	this.setYOffset(POPUP_LAYER_DEFAULT_Y_OFFSET);

	this.setBlankImage = pl_setBlankImage;
	this.getBlankImage = pl_getBlankImage;
	this.setBlankImage(POPUP_LAYER_BLANK_IMAGE);
	
	this.getHtml = pl_getHtml;
	
	this.writeHtml = pl_writeHtml;
	
	_popupLayers[this.getId()] = this;
	
	return this;
}

function pl_setId(id)
{
	this.id = id;
}

function pl_getId()
{
	return this.id;
}

function pl_setXOffset(xoffset)
{
	this.xoffset = xoffset;
}

function pl_getXOffset()
{
	return this.xoffset;
}

function pl_setYOffset(yoffset)
{
	this.yoffset = yoffset;
}

function pl_getYOffset()
{
	return this.yoffset;
}

function pl_setInnerHtml(innerHtml)
{
	this.innerHtml = innerHtml;
}

function pl_getInnerHtml()
{
	return this.innerHtml;
}

function pl_setImageClassName(imageClassName)
{
	this.imageClassName = imageClassName;
}

function pl_getImageClassName()
{
	return this.imageClassName;
}

function pl_setPopupLayerClassName(popupLayerClassName)
{
	this.popupLayerClassName = popupLayerClassName;
}

function pl_getPopupLayerClassName()
{
	return this.popupLayerClassName;
}

function pl_setBlankImage(blankImage)
{
	this.blankImage = blankImage;
}

function pl_getBlankImage()
{
	return this.blankImage;
}

function pl_getHtml()
{
	var html =
		'<img' +
			' src="' + this.getBlankImage() + '"' +
			' class="' + this.getImageClassName() + '"' +
			' id="' + this.getId() + '"' +
			' border="0"' +
			' onclick="javascript:_popupLayerImageMouseClickEvent(event, \'' + this.getId() + '\')"' +
			' onmouseover="javascript:_popupLayerImageMouseOverEvent(event, \'' + this.getId() + '\')"' +
			' onMouseOut="javascript:_popupLayerImageMouseOutEvent(event, \'' + this.getId() + '\')"' +
		'>';

	return html;
}

function pl_writeHtml()
{
	document.write(this.getHtml());
}
