// Opens and closes the content for a widget.
function widgetBoxToggle(sWidgetID)
{
	var oLink = document.getElementById(sWidgetID + "_WidgetLink");
	var oWidget = document.getElementById(sWidgetID + "_WidgetBox");
	
	if (null == oLink || null == oWidget)
		return;
		
	oWidget.className = ("widgetBoxClosed" == oWidget.className) ? "widgetBoxOpen" : "widgetBoxClosed";
	oLink.className = ("widgetLinkClosed" == oLink.className) ? "widgetLinkOpen" : "widgetLinkClosed";
}

// Initializes a floating widget.
function widgetFloatInit(sWidgetID)
{
	// Get reference to the floating widget container.
	var oFloat = document.getElementById(sWidgetID);
	
	// Make sure the element exists.
	if (null == oFloat)
		return;

	// Set behavior object to store widget state and perform actions.
	oFloat.behavior = new WidgetBehavior(oFloat);

	// Hook up event to start drag.
	oFloat.onmousedown = widgetBeginDrag;
}

// Handles mousedown event for a floating widget.
function widgetBeginDrag(oEvent)
{
	var oFloat;
	var iX;
	var iY;
	
	// This covers the WC3 DOM event model and the nonstandard IE event model.
	// Get reference to the floating widget container.
	// Tell the widget behavior that the widget will be dragged.
	if (document.all)
	{
		oFloat = window.event.srcElement;
		iX = window.event.screenX;
		iY = window.event.screenY;
	}
	else
	{
		oFloat = oEvent.target;
		iX = oEvent.screenX;
		iY = oEvent.screenY;
	}

	// Make sure we have an element reference.
	if (null == oFloat)
		return;
		
	while (null == oFloat.behavior)
	{
		oFloat = oFloat.parentNode;
	}

	oFloat.behavior.beginDrag(iX, iY);

	// Hook up event handlers for dragging.
	oFloat.onmousemove = widgetDrag;
	oFloat.onmouseup = widgetEndDrag;
	oFloat.onmouseout = widgetEndDrag;
}

// Handles mousemove event for a floating widget.
function widgetDrag(oEvent)
{
	var oFloat;
	var iX;
	var iY;
	
	// This covers the WC3 DOM event model and the nonstandard IE event model.
	// Get reference to the floating widget container.
	// Tell the widget behavior that the widget was dragged.
	if (document.all)
	{
		// Cancel default event and stop event bubbling.
		event.returnValue = false;
		event.cancelBubble = true;
		
		// Prevent selection of text while dragging.
		document.selection.clear();

		oFloat = window.event.srcElement;
		iX = window.event.screenX;
		iY = window.event.screenY;
	}
	else
	{
		// Cancel default event and stop event bubbling.
		oEvent.stopPropagation();
		oEvent.preventDefault();

		oFloat = oEvent.target;
		iX = oEvent.screenX;
		iY = oEvent.screenY;
	}

	// Make sure we have an element reference.
	if (null == oFloat)
		return;
		
	while (null == oFloat.behavior)
	{
		oFloat = oFloat.parentNode;
	}

	oFloat.behavior.drag(iX, iY);
}

// Handles mouseup event for a floating widget.
function widgetEndDrag(oEvent)
{
	var oFloat;
	
	// This covers the WC3 DOM event model and the nonstandard IE event model.
	// Get reference to the floating widget container.
	// Tell the widget behavior that the widget won't be dragged any more.
	if (document.all)
	{
		oFloat = window.event.srcElement;
	}
	else
	{
		oFloat = oEvent.target;
	}

	// Make sure we have an element reference.
	if (null == oFloat)
		return;
		
	while (null == oFloat.behavior)
	{
		oFloat = oFloat.parentNode;
	}

	oFloat.behavior.endDrag();

	// Remove event handlers for dragging.
	oFloat.onmousemove = null;
	oFloat.onmouseup = null;
	oFloat.onmouseout = null;
}

// Behavior for floating widget.
// Maintains state of the widget and performs required actions.
function WidgetBehavior(oWidgetElement)
{
	this.oFloat = oWidgetElement;
	this.iLeft = 0;
	this.iTop = 0;
	this.iLastPosX = 0;
	this.iLastPosY = 0;
	
	this.beginDrag = WidgetBehavior_beginDrag;
	this.drag = WidgetBehavior_drag;
	this.endDrag = WidgetBehavior_endDrag;
	this.setCookie = WidgetBehavior_setCookie;
	this.getCookie = WidgetBehavior_getCookie;

	// Read persisted position for the widget and reposition.	
	var sLeft = this.getCookie(this.oFloat.id + "_Left");
	var sTop = this.getCookie(this.oFloat.id + "_Top");
	
	if (null != sLeft && null != sTop)
	{
		this.oFloat.style.left = sLeft + "px";
		this.oFloat.style.top = sTop + "px";
	}
	
	// Stores current mouse position, current widget position.
	function WidgetBehavior_beginDrag(iPosX, iPosY)
	{
		this.iLeft = parseInt(this.oFloat.style.left);
		this.iTop = parseInt(this.oFloat.style.top);

		this.iLastPosX = iPosX;
		this.iLastPosY = iPosY;
	}
	
	// Calculates new location and moves widget, based on current mouse position.
	function WidgetBehavior_drag(iPosX, iPosY)
	{
		var iDeltaX = iPosX - this.iLastPosX;
		var iDeltaY = iPosY - this.iLastPosY;
		
		this.iLastPosX = iPosX;
		this.iLastPosY = iPosY;

		this.iLeft = this.iLeft + iDeltaX;
		this.iTop = this.iTop + iDeltaY;
		
		this.oFloat.style.left = this.iLeft.toString() + "px";
		this.oFloat.style.top = this.iTop.toString() + "px";
	}
	
	// Persists location of the widget in a cookie.
	function WidgetBehavior_endDrag()
	{
		this.setCookie( this.oFloat.id + "_Left", this.iLeft.toString() );
		this.setCookie( this.oFloat.id + "_Top", this.iTop.toString() );
	}
	
	// Creates a cookie with the specified name and value.
	function WidgetBehavior_setCookie(sName, sValue)
	{
		// Cookie is set to expire in a month.
		// Cookie will be valid for entire site.
		var expireDate = new Date();
		expireDate.setMonth( expireDate.getMonth() + 1 );

		document.cookie =	sName + "=" + escape(sValue) +
							"; expires=" + expireDate.toGMTString() +
							"; path=/";
	}

	// Reads value of a cookie with the specified name.
	function WidgetBehavior_getCookie(sName)
	{
		// Cookies are separated by semicolons
		var sCookie = document.cookie.split("; ");
		
		for (var i = 0; i < sCookie.length; i++)
		{
			// A name/value pair (a crumb) is separated by an equal sign
			var sCrumb = sCookie[i].split("=");
			
			if (sName == sCrumb[0]) 
				return unescape(sCrumb[1]);
		}

		// A cookie with the requested name does not exist
		return null;
	}
}
