function init()
{
	resizePanels();
}

function resizePanels()
{
	var elements = getPanelsToResize();
	
	var maxHeight = getMaximumHeight(elements);
	
	setHeight(elements, maxHeight);
}

function setHeight(elements, height)
{
	for (var i = 0; i < elements.length; i++)
	{
		var element = elements[i];
		
		element.style.height = height + "px";
	}
}

function getMaximumHeight(elements)
{
	var maxHeight = 0;
	
	for (var i = 0; i < elements.length; i++)
	{
		var element = elements[i];
		
		var height = element.offsetHeight > element.clientHeight
				? element.offsetHeight : element.clientHeight;
		
		if (height > maxHeight)
		{
			maxHeight = height;
		}
	}
	
	return maxHeight;
}

function getPanelsToResize()
{
	var potential = getElementsWithAttribute("sb:resize");
	var matches = [];
	
	for (var i = 0; i < potential.length; i++)
	{
		var element = potential[i];
		
		var attribute = element.getAttribute("sb:resize");
		
		if (Boolean.isTrue(attribute))
		{
			matches.push(element);		
		}
	}
	
	return matches;
}

function getElementsWithAttribute(attributeName)
{
	
	var elements;
	var element;
	var attribute;
	var matchingElements;
	
	matchingElements = new Array();
	
	elements = document.getElementsByTagName("*");
	
	for (var i = 0; i < elements.length; i++)
	{
		element = elements[i];
		
		try
		{
			attribute = element.getAttribute(attributeName);
			
			if (attribute)
			{
				matchingElements.push(element);
			}
		}
		catch(e)
		{
			// IE7 seems to throw an error on tables.	
		}
	}
	
	return matchingElements;
}

// Takes a string and returns the object with the corresponding corresponding
// ID. If an object is passed in, the object is returned. This allows callers
// to accept either the name of an object or the object itself.

function getObject(param)
{
	if (typeof param == "object")
	{
		return param;
	}
	else
	{
		return document.getElementById(param);
	}
}

// getActiveStyle() takes a DOM object as a parameter and returns that object's
// current, computed style. Just calling object.style provides access to any
// style properties defined using the style="" HTML attribute. It does not
// account for CSS selectors (classes, ids, etc.).

function getActiveStyle(obj)
{
	// Ensure that we have an object and not just the ID of an HTML element.
	
	obj = getObject(obj);
	
	if (obj.currentStyle)
	{
		// Internet Explorer
		
		return obj.currentStyle;
	}
	else if (document.defaultView && document.defaultView.getComputedStyle)
	{
		// Mozilla/FireFox
		
		return document.defaultView.getComputedStyle(obj, null);
	}
	else
	{
		// Fall back to non-computed style.
		
		return obj.style;
	}
}

// Takes n arguments which are the IDs of elements whose style display mode will
// be toggled from none to block.

function toggleDisplay()
{
	for (var i = 0; i < arguments.length; i++)
	{
		var obj = getObject(arguments[i]);
		
		var objStyle = getActiveStyle(obj);
		
		// Since all elements are hidden with a value of "none", whereas each
		// element may have its own display value, we'll check for "none".
		
		if (objStyle.display == "none")
		{
			show(obj);
		}
		else
		{
			hide(obj);
		}
	}
}

function show(obj)
{
	obj.style.display = getDefaultDisplay(obj);
	
	obj.style.visibility = "visible";
}


function hide(obj)
{
	obj.style.display = "none";

	obj.style.visibility = "hidden";
}

// Determines the default display value for the object's HTML element type. For
// instance, a DIV would have a default display of "block". This method should
// ensure that we use the correct display value for each browser.

function getDefaultDisplay(obj)
{
	
	var value = "";
	
	// Create a new element with a tag name that corresponds to the object.
	
	var objCopy = document.createElement(obj.tagName);
	
	// Unless we add the element to the document, we won't know the actual
	// display value. IE will return an empty string; Firefox, "block".
	
	// By setting the visibility to hidden, we ensure that the user will not
	// see any such changes.
	
	objCopy.visibility = "hidden";
	
	document.body.appendChild(objCopy);
	
	value = getActiveStyle(objCopy).display;
	
	document.body.removeChild(objCopy);
	
	return value;
}

// Add a trim() method to the String class.

String.prototype.trim  = function(str)
{
	str = this != window ? this : str;
	
	return str.replace(/^\s+/g, '').replace(/\s+$/g, '');
};

// This function can be used in place of a xor operator, which JavaScript is
// lacking.

Boolean.xor = function(a, b)
{
	return ( a && !b ) || ( !a && b );
};

Boolean.isTrue = function(value)
{
	var evalNumber = function(num)
	{
		// Need to check for NaN because typeof NaN is number.
		
		return num == 0 || isNaN(num) ? false : true;
	};
	
	if (typeof value == "boolean")
	{
		if (value)
		{
			return true;
		}
		else
		{
			return false;
		}
	}
	else if (typeof value == "number")
	{
		return evalNumber(value);
	}
	else if (typeof value == "string")
	{
		switch (value.toLowerCase())
		{
			case "true":
				return true;
			case "yes":
				return true;
			case "on":
				return true;
			default:
				return evalNumber(parseFloat(value));
		}
	}
	
	return false;
};

Date.isDate = function(value)
{
	return !isNaN(new Date(value));
};

/* Returns 0 if the two dates are the same. Returns -1 if date1 is less than
 * date2. Rturns 1 if date2 is less than date1. */

Date.compare = function(date1, date2)
{
	
	if (typeof date1 != "object")
	{
		date1AsDate = new Date(date1);
	}
	else
	{
		date1AsDate = date1;
	}
	
	if (typeof date2 != "object")
	{
		date2AsDate = new Date(date2);
	}
	else
	{
		date2AsDate = date2;
	}
	
	if (isNaN(date1AsDate))
	{
		throw("The value " + date1 + " cannot be converted to a date.");
	}
	
	if (isNaN(date2AsDate))
	{
		throw("The value " + date2 + " cannot be converted to a date.");
	}
	
	if (date1AsDate.valueOf() == date2AsDate.valueOf())
	{
		return 0;
	}
	else if (date1AsDate.valueOf() < date2AsDate.valueOf())
	{
		return -1;
	}
	else
	{
		return 1;
	}
	
};

/* Returns true if the date is less than the specified date. Returns false
 * otherwise. */

Date.prototype.lessThan = function(date)
{
	if (Date.compare(this, date) == -1)
	{
		return true;
	}
	else
	{
		return false;
	}
};

/* Returns true if the date is greater than the specified date. Returns false
 * otherwise. */

Date.prototype.greaterThan = function(date)
{
	if (Date.compare(this, date) == 1)
	{
		return true;
	}
	else
	{
		return false;
	}
};

/* Returns true if the date is equal to the specified date. Returns false
 * otherwise. */

Date.prototype.equals = function(date)
{
	if (Date.compare(this, date) == 0)
	{
		return true;
	}
	else
	{
		return false;
	}
};

Date.prototype.toUsDateFormat = function()
{
	return this.getMonth() + 1 + "/" + this.getDate() + "/" + this.getFullYear();
};

Math.dollarFormat = function(value)
{
	value = parseFloat(value);
	
	if(isNaN(value))
	{
		value = 0.00;
	}
	
	// Round off to the second decimal place. We can't just call
	// toFixed() because it always rounds down.
	
	value = (Math.round(value * 100) / 100).toFixed(2);
	
	var insertCommas = function()
	{
		var regEx = /^(.* )?([-+]?\d+)(\d{3}\b)/;
		
		var newValue = valueFormatted.replace(regEx, "$1$2,$3");
		
		if (newValue != valueFormatted)
		{
			valueFormatted = newValue;
			
			insertCommas();	
		}
	};
	
	var valueFormatted = value.toString();
	
	insertCommas();
	
	valueFormatted = "$" + valueFormatted;
	
	return valueFormatted;
};