/**
* Creates a object that provides scrollbar services for the content area
*/
function Scrollbars()
	{
	// Step 1. Define Properties

	var _instance = this;

	_scrollbars = this;
	_grabberBeingDragged = false;
	_leftButtonDown = false;
	_draggedObj = null;
	_scrollDirection = null;
	_scrollbarRebuiltTimeouts = { sidebar: null, body: null, bodywide: null };



	// Step 2. Define Public Methods

	/**
	* Sets up the initial page state and event handlers
	*/
	this.init = function()
		{
		if (!!document.getElementById('globalContent') == false)
			{
			return;
			}

		// Add event handler to rebuild scrollbars on window resize
		window.onresize = function()
			{
			// Set the content area height
			_scrollbars.contentAreaHeight = (document.documentElement.clientHeight - document.getElementById('globalHeader').offsetHeight -  document.getElementById('globalFooter').offsetHeight);
			document.getElementById('globalContent').style.height = _scrollbars.contentAreaHeight + 'px';

			// Rebuild scrollbars
			if (document.getElementById('globalContentSidebar'))
				{
				clearTimeout(_scrollbarRebuiltTimeouts.sidebar);
				_scrollbarRebuiltTimeouts.sidebar = setTimeout("_scrollbars.refreshScrollbar(document.getElementById('globalContentSidebar'));", 500);
				}
			if (document.getElementById('globalContentBody'))
				{
				clearTimeout(_scrollbarRebuiltTimeouts.body);
				_scrollbarRebuiltTimeouts.body = setTimeout("_scrollbars.refreshScrollbar(document.getElementById('globalContentBody'));", 500);
				}
			if (document.getElementById('globalContentBodyWide'))
				{
				clearTimeout(_scrollbarRebuiltTimeouts.bodywide);
				_scrollbarRebuiltTimeouts.bodywide = setTimeout("_scrollbars.refreshScrollbar(document.getElementById('globalContentBodyWide'));", 500);
				}
			}

		// Set the content area height
		this.contentAreaHeight = (document.documentElement.clientHeight - document.getElementById('globalHeader').offsetHeight -  document.getElementById('globalFooter').offsetHeight);
		document.getElementById('globalContent').style.height = this.contentAreaHeight + 'px';

		// Check if the sidebar needs scroll bars
		if (document.getElementById('globalContentSidebar'))
			{
			if (this.contentAreaHeight < document.getElementById('globalContentSidebar').clientHeight)
				{
				addScrollbar(document.getElementById('globalContentSidebar'));
				}
			document.getElementById('globalContentSidebar').onclick = function()
				{
				_scrollbars.refreshScrollbar(this);
				}
			}

		// Check if the body needs scroll bars
		if (document.getElementById('globalContentBody'))
			{
			if (this.contentAreaHeight < document.getElementById('globalContentBody').clientHeight)
				{
				addScrollbar(document.getElementById('globalContentBody'));
				}
			document.getElementById('globalContentBody').onclick = function()
				{
				_scrollbars.refreshScrollbar(this);
				}
			_scrollbarRebuiltTimeouts.body = setTimeout("_scrollbars.refreshScrollbar(document.getElementById('globalContentBody'));", 500);
			}
		if (document.getElementById('globalContentBodyWide'))
			{
			if (this.contentAreaHeight < document.getElementById('globalContentBodyWide').clientHeight)
				{
				addScrollbar(document.getElementById('globalContentBodyWide'));
				}
			document.getElementById('globalContentBodyWide').onclick = function()
				{
				_scrollbars.refreshScrollbar(this);
				}
			}
		}


	/**
	* Scrollbars the target area of the scollbar up
	*
	* @param		id		The id of the scrollbar
	*/
	this.scrollUp = function(id)
		{
		// Scroll the target
		var newY = parseInt(this.scrollbars[id].target.style.top) + 20;
		if (0 < newY)
			{
			newY = 0;
			}
		this.scrollbars[id].target.style.top = newY + 'px';

		// Reposition the grabber
		var grabberY = Math.ceil((Math.abs(newY) / this.scrollbars[id].scrollRange) * this.scrollbars[id].grabberRange);
		document.getElementById('scrollbarGrabber' + id).style.top = grabberY + 'px';
		}


	/**
	* Scrollbars the target area of the scollbar down
	*
	* @param		id		The id of the scrollbar
	*/
	this.scrollDown = function(id)
		{
		// Scroll the target
		var newY = parseInt(this.scrollbars[id].target.style.top) - 20;
		if ((newY + this.scrollbars[id].scrollRange) < 0)
			{
			newY = this.scrollbars[id].scrollRange * -1;
			}
		this.scrollbars[id].target.style.top = newY + 'px';

		// Reposition the grabber
		var grabberY = Math.ceil((Math.abs(newY) / this.scrollbars[id].scrollRange) * this.scrollbars[id].grabberRange);
		document.getElementById('scrollbarGrabber' + id).style.top = grabberY + 'px';
		}


	/**
	* Processes and dispatches the Mouse Down event
	*
	* @param		event		the browser event object
	*/
	this.processMouseDown = function(event)
		{
		// Assign event for Internet Explorer
		if (!event)
			{
			event = window.event;
			}

		// Check if the left button was pressed
		if (event.which != 1 && event.button != 1)
			{
			// Middle or right click, so return
			return;
			}

		// Retrieve the object clicked on
		var obj = (!!(window.attachEvent && !window.opera) ? event.srcElement : event.target);

		if (obj.id == 'designThumbsScrollbarGrabber')
			{
			return;
			}

		// Store that the mouse button is down
		_leftButtonDown = true;
		_scrollDirection = 'vertical';

		// Left click on a draggable object, process drag start
		_dragStart(obj);
		}


	/**
	* Processes and dispatches the Mouse Move event
	*
	* @param		event		the browser event object
	*/
	this.processMouseMove = function(event)
		{
		// Check if an object is being dragged
		if (_grabberBeingDragged == false || _draggedObj == null || _scrollDirection != 'vertical')
			{
			return;
			}

		// Assign event for Internet Explorer
		if (!event)
			{
			event = window.event;
			}

		// Check if the mouse button is still down, if not release the object from dragging
		if (_leftButtonDown == false)
			{
			_dragEnd();
			return;
			}

		// Process the move event
		_dragMove(!!event.clientY ? event.clientY : event.pageY);
		}


	/**
	* Processes and dispatches the Mouse Up event
	*/
	this.processMouseUp = function()
		{
		// Check if an object is being dragged
		if (_grabberBeingDragged == false || _draggedObj == null || _scrollDirection != 'vertical')
			{
			return;
			}

		_scrollDirection = null;

		// Process the move event
		_dragEnd();
		}


	
	/**
	* Rebuilds the scrollbar for the specified element
	*
	* @param		target		The element to rebuild the scrollbar for
	*/
	this.refreshScrollbar = function(target)
		{
		if (this.contentAreaHeight < target.clientHeight)
			{
			removeScrollbar(target);
			addScrollbar(target);
			}
		else
			{
			removeScrollbar(target);
			}
		}



	// Step 3. Define Private Methods

	/**
	* Adds a scrollbar the specified target element
	*
	* @param		target		The element for create the scrollbar for
	*/
	function addScrollbar(target)
		{
		if (typeof _instance.scrollbars == 'undefined')
			{
			_instance.scrollbars = [];
			}
		_instance.scrollbars.push(
				{
				target: target,
				grabberRange: (_instance.contentAreaHeight - 40),
				scrollRange: ((target.offsetHeight - _instance.contentAreaHeight) < 0 ? 0 : (target.offsetHeight - _instance.contentAreaHeight))
				}
			);

		// Create scrollbar container
		var scrollbar = document.createElement('div');
		scrollbar.className = 'scrollbar';
		scrollbar.id = 'scrollbar' + (_instance.scrollbars.length-1);
		scrollbar.style.left = (YAHOO.util.Dom.getX(target) - YAHOO.util.Dom.getX('page') + parseInt(target.offsetWidth) - 9) + 'px';
		scrollbar.style.height = (_instance.contentAreaHeight) + 'px';

		if (target.id == 'globalContentSidebar')
			{
			scrollbar.style.top = '20px';
			scrollbar.style.height = (_instance.contentAreaHeight - 40) + 'px';
			}

		// Create scrollbar up button
		var scrollbarUp = document.createElement('div');
		scrollbarUp.className = 'scrollbarUp';
		scrollbarUp.id = 'scrollbarUp' + (_instance.scrollbars.length-1);
		scrollbarUp.onclick = function() { _scrollbars.scrollUp(this.id.replace('scrollbarUp','')); }
		scrollbar.appendChild( scrollbarUp );

		// Create scrollbar down button
		var scrollbarDown = document.createElement('div');
		scrollbarDown.className = 'scrollbarDown';
		scrollbarDown.id = 'scrollbarDown' + (_instance.scrollbars.length-1);
		scrollbarDown.onclick = function() { _scrollbars.scrollDown(this.id.replace('scrollbarDown','')); }
		scrollbar.appendChild( scrollbarDown );

		// Create scrollbar grabber
		var scrollbarGrabber = document.createElement('div');
		scrollbarGrabber.className = 'scrollbarGrabber';
		scrollbarGrabber.id = 'scrollbarGrabber' + (_instance.scrollbars.length-1);
		scrollbar.appendChild( scrollbarGrabber );

		// Add scrollbar to document
		document.getElementById('globalContent').appendChild( scrollbar );

		// Add event handlers
		scrollbarGrabber.onmousedown = function(event) { _scrollbars.processMouseDown(event); }
		YAHOO.util.Event.addListener(document, 'mousemove', _scrollbars.processMouseMove, _scrollbars);
		YAHOO.util.Event.addListener(document, 'mouseup', _scrollbars.processMouseUp, _scrollbars);

		// Set the initial scroll position on the target
		if (target.style.top == '')
			{
			// This is the first time the scrollbars have been added, so we need to set an initial top style
			target.style.top = '0px';
			}
		else
			{
			// Redisplayed scrollbars, reposition the grabber on the scrollbar to show the current scroll location
			var grabberY = Math.ceil((Math.abs(parseInt(target.style.top)) / _instance.scrollbars[_instance.scrollbars.length-1].scrollRange) * _instance.scrollbars[_instance.scrollbars.length-1].grabberRange);
			if (grabberY < 0)
				{
				grabberY = 0;
				}
			if ((_instance.contentAreaHeight - 40) < grabberY)
				{
				grabberY = _instance.contentAreaHeight - 40;
				}
			scrollbarGrabber.style.top = grabberY + 'px';
			}
		}


	/**
	* Removes the scrollbar from the specified target element
	*
	* @param		target		The element to remove the scrollbar from
	*/
	function removeScrollbar(target)
		{
		if (typeof _instance.scrollbars == 'undefined')
			{
			return;
			}
		for (var x = 0; x < _instance.scrollbars.length; x++)
			{
			if (_instance.scrollbars[x].target == target)
				{
				document.getElementById('globalContent').removeChild(document.getElementById('scrollbar'+x));
				_instance.scrollbars[x].target = null;
				}
			}
		}


	/**
	* Sets up the dragging of one of grabbers
	*
	* @param		obj						the object (grabber) clicked on
	*/
	function _dragStart(obj)
		{
		_draggedObj = obj;

		// Disable text selection
		document.onselectstart = function()
					{
					return false;
					}
		document.getElementById('page').style.MozUserSelect = 'none';
		document.getElementById('page').style.KhtmlUserSelect = 'none';
		document.getElementById('page').unselectable = 'on';


		// Store that a grabber is being dragged
		_grabberBeingDragged = true;
		}


	/**
	* Moves the grabber in the document
	*
	* @param		mousePosition		the mouse position at the time of the move event
	*/
	function _dragMove(mousePosition)
		{
		// Find the scrollbar id
		var id = _draggedObj.id.replace('scrollbarGrabber','');

		// Update the grabber position
		newY = mousePosition - 195;

		// Range check for top
		if (newY < 0)
			{
			newY = 0;
			}

		// Range check for bottom
		if (_instance.scrollbars[id].grabberRange < newY)
			{
			newY = _instance.scrollbars[id].grabberRange;
			}

		// Move the grabber
		_draggedObj.style.top = newY + 'px';

		// Scroll the target
		var targetY = Math.ceil((Math.abs(newY) / _instance.scrollbars[id].grabberRange) * _instance.scrollbars[id].scrollRange) * -1;
		_instance.scrollbars[id].target.style.top = targetY + 'px';
		}


	/**
	* Ends the object dragging
	*/
	function _dragEnd()
		{
		// Enable text selection
		document.onselectstart = null;
		document.getElementById('page').style.MozUserSelect = '';
		document.getElementById('page').style.KhtmlUserSelect = '';
		document.getElementById('page').unselectable = 'off';

		// Store that the grabber is no longer is being dragged
		_grabberBeingDragged = false;
		_draggedObj = null;
		_leftButtonDown = false;
		}



	// Step 4. Initialize class
	this.init();
	}
