function __levelheight_init(){
	var getFunctionName = function(f){
		/*
		Parameters:
			f (string|function) - The function or function text to get the name from.
		Purpose:
			To get the name of a function passed.
		Returns:
			A string, representing the name of the function.
		*/
		var value = null;
		var re = /^function (.+?)\(.*?\)/i;
		var result = null;
		if (typeof f){
			value = f.name; //Some browsers provide a name property on the function object, so we'll use that if we can.
			if (value != null)return value;
			f = f.toString();
		};
		result = re.exec(f);
		if (result != null)value = result[1];
		return value;
	};
	var object_type = function(){
		/*
		Parameters:
			If no parameters are specified, this method will return a string of the name of the object determined.
			If any parameters are specified; they are passed to the constructor of the object, and the new object created is returned.
		Purpose:
			Use this on any Object to determine it's type, far more precisely than the built in JavaScript typeof operator.
			If the object type is determined to be an HTML element, the arguments passed are expected to be name=value pairs, designating attributes to be set on the new object.
			If constructor arguments are passed, and the return object can not be created; a string of the name of the object is returned instead.
		Returns:
			Either a string with the name of the object found; or a new object of the type found.
			Objects Recognized:
				object
				array
				boolean
				date
				enumerator (IE Specific)
				error
				function
				number
				regexp
				string
				*UDF Objects (returns the name of the constructor function)
			Will return null if could not determine object type.
		*/
		var value = null;
		var constructor = this.constructor;
		switch (typeof this){
			case "object":
				switch (constructor){
					case Object:
						value = (arguments.length > 0 ? new Object(arguments[0]) : "object");
						break;
					case String:
						value = (arguments.length > 0 ? new String(arguments[0]) : "string");
						break;
					case Number:
						value = (arguments.length > 0 ? new Number(arguments[0]) : "number");
						break;
					case Boolean:
						value = (arguments.length > 0 ? new Boolean(arguments[0]) : "boolean");
						break;
					case Array:
						value = (arguments.length > 0 ? new Array(arguments) : "array");
						break;
					case Date:
						value = (arguments.length > 0 ? new Date(arguments) : "date");
						break;
					case Error:
						value = (arguments.length > 0 ? new Error(arguments[0],arguments[1]) : "error");
						break;
					case RegExp:
						value = (arguments.length > 0 ? new RegExp(arguments[0],arguments[1]) : "regexp");
						break;
					default:
						var cName = getFunctionName(constructor)
						if (cName != null){
							value = (arguments.length > 0 ? constructor.call(arguments) : cName);
						}
				}
				break;
			case "function":
				switch (constructor){
					case RegExp:
						value = (arguments.length > 0 ? new RegExp(arguments[0],arguments[1]) : "regexp");
						break;
					case Function:
						value = (arguments.length > 0 ? new Function(arguments) : "function");
						break;
				}
				break;
			case "string":
			case "number":
			case "boolean":
			case "array":
			case "date":
			case "error":
			case "regexp":
				value = typeof this;
				break;
			default:
				try {
					value = (returnObj ? null : "undetermined");
				}
				catch(e){
					value = "undetermined";
				}
		}
		if (value == null){
			// If after all that we didn't find what we're looking for, let's try some browser specific objects.
			try{
				if (constructor == Enumerator)value = (arguments.length > 0 ? new Enumerator(arguments[0]) : "enumerator");
			}
			catch (e){
			};
		}
		return value;
	};
	var getElementsByAttribute = function(attribute,value,start){
		/*
		Parameters:
			attribute (variant) - Either a string which is an exact attribute or a regular expression.
				This parameter can also be an array of strings or regular expressions, for matches of more than one attribute.
			value (variant) - Either a string or a regular expression, of the value of the attribute to retrieve elements of. Default is null.
				If attribute is an array, this must be an array of equal length (or null).
			start (variant) - Either the ID of the element to start looking under or the element reference itself. Default is body.
		Purpose:
			This function returns an array of all matching elements which match the specified attributes or values.
		Returns:
			An array of elements, or a zero length array if no elements contain the specific attribute and value passed.
		*/
		var array = [];
		start = (start == null ? document.body : start);
		var recurse = function(el,attribute,value){
			if (el.nodeType == 1){
				var attr = attribute;
				if (object_type(attribute) == "regexp"){
					var attrs = el.attributes;
					for (var i=0; i<attrs.length; i++){
						var result = attribute.test(attrs[i].nodeName);
						if (result){
							attr = attrs[i].nodeName;
							break;
						};
					};
				}
				var condition1 = (el.getAttributeNode(attr) != null);
				var condition2 = (value == null || (condition1 && value != null && ((object_type(value) == "string" && el.getAttributeNode(attr).nodeValue == value) || (object_type(value) == "regexp" && new RegExp(value.source,(value.global ? "g" : "")+(value.ignoreCase ? "i" : "")+(value.multiline ? "m" : "")).test(el.getAttributeNode(attr).nodeValue)))));
				if (condition1 && condition2)array[array.length] = el;
			};
			for (var i=0; i<el.childNodes.length; i++)recurse(el.childNodes[i],attribute,value);
		};
		if (attribute != null){
			if ((object_type(attribute) == "array" && value != null && object_type(value) == "array" && value.length == attribute.length) || (object_type(attribute) == "array" && value == null) || (object_type(attribute) != "array")){
				if (object_type(attribute) == "array"){
					for (var i=0; i<attribute.length; i++)recurse(start,attribute[i],value[i]);
				}
				else recurse(start,attribute,value);
			}
			else Object.error("getElementsByAttribute(): When passing attribute as an array, if value is also being checked; it must be an equal length array.");
		}
		else Object.error("getElementsByAttribute(): No attribute was specified.");
		return array;
	};
	var elements = getElementsByAttribute("levelheight");
	for (var i=0; i<elements.length; i++){
		var el = elements[i];
		var levelize = el.getAttribute("levelheight");
		var array = levelize.split(",");
		for (var z=0; z<array.length; z++){
			var el2 = document.getElementById(array[z]);
			var height = Math.max(el.offsetHeight,el2.offsetHeight);
		};
	};
	for (var i=0; i<elements.length; i++){
		var el = elements[i];
		el.style.height = height+"px";
	};
};

if (window.addEventListener != null){
	window.addEventListener("load",__levelheight_init,false);
	window.addEventListener("resize",__levelheight_init,false);
};
if (window.attachEvent != null){
	window.attachEvent("onload",__levelheight_init);
	window.attachEvent("onresize",__levelheight_init);
};