/////////////////////////////////////////////////////////////////////////////
// Callout.js
//		Java script functions used to display floating callout bubbles.

var		_objCalloutOwner = null;
var		_nPosCallout = 0;
var		_nMaxWidthCallout = 0;
var		_objCallout = null;
var		_objCalloutContent = null;
var		_urlCalloutRequest = null;
var		_objShadow = null;
var		_idCalloutTimer = 0;
var		_bWaitingToShow = false;
var		_bWaitingToHide = false;

/////////////////////////////////////////////////////////////////////////////
//	Function used to clear any pending timer.
function CancelCalloutTimer()
{
	if (_idCalloutTimer)
		clearTimeout(_idCalloutTimer);
	_idCalloutTimer = 0;
}

/////////////////////////////////////////////////////////////////////////////
//	Function used to monitor a delayed timer for displaying and hiding the
//	callout bubble.
function _MonitorCallout()
{
	// Clear our timer
	CancelCalloutTimer();

	// See if we are waiting to show or hide the callout
	if (_bWaitingToShow)
	{
		_ShowCallout();
		_bWaitingToShow = false;
	}		
	else if (_bWaitingToHide)
	{
		_HideCallout();			
		_bWaitingToHide = false;
	}	
}

/////////////////////////////////////////////////////////////////////////////
//	Callback function that receives the content by _LoadCallout.
function OnCalloutUpdate(httpRequest)
{
	// See if the request has completed
	if (httpRequest.readyState == 4 && httpRequest.status == 200 && httpRequest.responseText != null)
	{
		// See if we are still waiting for this content
		if (_objWaitingToLoad == _objCalloutOwner)		
		{
			// Load the content from the XML into the callout
			if (_objCalloutContent)
				_objCalloutContent.innerHTML = httpRequest.responseText;

			// Resize the shadow to match the new content size				
			if (_objShadow)
			{
				var rect = _GetObjectRect(_objCallout);
				_objShadow.style.width = (rect.right - rect.left) + 18;
				_objShadow.style.height = (rect.bottom - rect.top) + 18;
			}
				
			_objWaitingToLoad = null;
		}
		
		// See if we are ready to be displayed
		var		bVisible = (_objCallout != null && _objCallout.style.visibility != "hidden");		
		if (!bVisible && !_bWaitingToShow && _objCallout)
		{
			_CheckCalloutPosition();
			_objCallout.style.visibility = "visible";
			_objShadow.style.visibility = "visible";
		}
	}
}

/////////////////////////////////////////////////////////////////////////////
//	Attempt to get the content and update the callout before it is displayed
function _LoadCallout()
{
	// Ensure we have an object and a content url
	if (_urlCalloutRequest && _objCallout)
	{
		_objWaitingToLoad = _objCalloutOwner;
		ExecuteXMLHttpRequestGET(_urlCalloutRequest, OnCalloutUpdate, true)
	}
}

/////////////////////////////////////////////////////////////////////////////
//	Ensure the callout is positioned so all content is visible
function _CheckCalloutPosition()
{
	// Get the width and hieght of the client area for the browser's window
	var		rectClient =  _GetWindowRect();
	
	// Get the rectangle of the callout and see if it extends past the client area
	var		rectCallout = _GetObjectRect(_objCallout);
	if (rectCallout.right > rectClient.right)
	{
		// Determine if we can move the callout to be visible
		var		left = rectClient.right - (rectCallout.right - rectCallout.left);
		if (left > 0)
		{
			// Reposition the callout and shadow
			_objCallout.style.left = left;
			_objShadow.style.left = _objCallout.style.left;
		}	
	}
}

/////////////////////////////////////////////////////////////////////////////
//	Position and display our callout bubble
function _ShowCallout()
{
	// Determine the position of the callout
	if (_objCalloutOwner && _objCallout)
	{
		// Start our content loading
		_LoadCallout();
	
		// Position the callout
		var rect = _GetObjectRect(_objCalloutOwner);
		_objCallout.style.left = rect.right + 5;
		_objCallout.style.top = rect.top + ((rect.bottom - rect.top) / 2);
		
		// Position the shadow
		_objShadow.style.left = _objCallout.style.left;
		_objShadow.style.top = _objCallout.style.top;
		
		// Set the callout's maximum width
		if (_nMaxWidthCallout > 0)
			_objCallout.style.width = _nMaxWidthCallout;

		// Only show the callout if our content is ready
		if (_objWaitingToLoad == null)
		{
			_CheckCalloutPosition();
			_objCallout.style.visibility = "visible";
			_objShadow.style.visibility = "visible";
		}
	}
}

/////////////////////////////////////////////////////////////////////////////
//	Hide our callout bubble
function _HideCallout()
{
	// Cancel any pending timer
	CancelCalloutTimer();

	// Hide the callout and clear our variables
	if (_objCallout)
	{
		_objCallout.style.visibility = "hidden";
		_objCallout.style.left = _objCallout.style.top = 0;
		_objCallout = null;
	}
	if (_objShadow)
	{
		_objShadow.style.visibility = "hidden";
		_objShadow.style.left = _objShadow.style.top = 0;	
		_objShadow = null;
	}
	_objCalloutContent = null;
	_objCalloutOwner = null;
	_nPosCallout = 0;
	_urlCalloutRequest = null;
	_bWaitingToShow = false;
	_bWaitingToHide = false;
}

/////////////////////////////////////////////////////////////////////////////
// Start or continue the delayed display of the callout bubble.
// The parameter objOwner is the object initiating the callout and nPos can be
// one of the following:
//		0 = right side of the object
// The parameter nMaxWidth defines the maximum width for the callout, a value of
// zero can be used for the default maximum width.
// The urlContentRequest parameter specifies the content to be loaded into the callout.
function _StartCallout(objOwner, nPos, nMaxWidth, idCallout, idCalloutContent, idShadow, urlContentRequest)
{
	// Cancel any pending hide or show operation
	CancelCalloutTimer();

	// See if the callout is currently visible
	var		bVisible = (_objCallout != null && _objCallout.style.visibility != "hidden");
	
	// If it's the same owner or the callout itself then do nothing
	if (bVisible && objOwner == _objCalloutOwner || objOwner == _objCallout)
		return;

	// See if we should cancel the current callout operation
	if (_objCalloutOwner != null && objOwner != _objCalloutOwner)
		_HideCallout();
	
	// Save the information for later
	_objCalloutOwner = objOwner;
	_nPosCallout = nPos;
	_nMaxWidthCallout = nMaxWidth;
	_objCallout = document.getElementById(idCallout);
	if (!_objCallout)
		return;
	if (idCalloutContent != null)
		_objCalloutContent = document.getElementById(idCalloutContent);
	else
		_objCalloutContent = null;
	_objShadow = document.getElementById(idShadow);
	if (!_objShadow)
		return;
	_urlCalloutRequest = urlContentRequest;
	
	// If the callout was already visible just move and update it
	if (bVisible)
		_ShowCallout();
	else
	{	
		// Set our timer for delayed display
		_bWaitingToHide = false;
		_bWaitingToShow = true;
		_idCalloutTimer = setTimeout('_MonitorCallout()', 500);
	}
}

/////////////////////////////////////////////////////////////////////////////
// Cancel the current callout bubble if it is associated with the specified object.
function _CancelCallout(objOwner)
{
	// See if the owner matches or if this is the callout
	if (objOwner == _objCalloutOwner || objOwner == _objCallout)
	{
		// Set our timer for delayed hidding
		_bWaitingToShow = false;
		_bWaitingToHide = true;
		_idCalloutTimer = setTimeout('_MonitorCallout()', 500);
	}
}

