
var BSDClass = {
	create: function() {
    	return function() {
    		if(this.initialize) {
	      		this.initialize.apply(this, arguments);
	      	} else if(this.className) {
				BSDLogUtils.error("Couldn't find initialize function for class " + this.className);		      	
			} else {
				BSDLogUtils.error("Couldn't find initialize function for class " + arguments);		      	
	      	}
    	}
  	}
}
BSDStringUtils = {
	DEPENDENCIES: new Array(),
	VERSION: 1.1,
	
	toCamelCaseRegex: /-([a-z])/,
	
	toCamelCase: function(value) {
		var regex = BSDStringUtils.toCamelCaseRegex;
		for(; regex.test(value); value = value.replace(regex, RegExp.$1.toUpperCase()) );
		return value;
	},
	
	trimRegex: /^\s+|\s+$/g,
	
	trim: function(value) {
		if(!value) {
			return null;
		}
		var regex = BSDStringUtils.trimRegex;
		value = value.replace(regex, '');
		return value;
	},
	
	equalsTrimmed: function(value1, value2) {
		if(!value1 && !value2) {
			return true;
		}
		if(!value1) {
			return false;
		}
		if(!value2) {
			return false;
		}
		value1 = BSDStringUtils.trim(value1);
		value2 = BSDStringUtils.trim(value2);
		return value1 == value2;
	},
	
	equalsIgnoreCase: function(value1, value2) {
		if(!value1 && !value2) {
			return true;
		}
		if(!value1) {
			return false;
		}
		if(!value2) {
			return false;
		}
		return value1.toLowerCase() == value2.toLowerCase();
	},

	startsWith: function(value, starting) {
		if(!value) {
			return false;
		}
		var regex = new RegExp("^" + starting, "g");
		if(regex.exec(value)) {
			return true;
		}
		return false;
	},
		
	endsWith: function(value, ending) {
		if(!value) {
			return false;
		}
		var regex = new RegExp(ending + "$", "g");
		if(regex.exec(value)) {
			return true;
		}
		return false;
	},
	
	stripWhitespace: function(value) {
		return value.replace(/\s/g, '');
	},
	
	stripHtml: function(value) {
		return value.replace(/<[^\s0-9\.\$\=>][^>]*>/g, '');
	},
	
	truncate: function(value, length) {
		if(value.length > length) {
			value = value.substring(0, length);
		}
		return value;
	},
	
	brToLB: function(value) {
		if(!value) {
			return value;
		}
		value = value.replace("<br/>", "\n");
		value = value.replace("<br>", "\n");
		return value;
	},
	
	lbToBR: function(value) {
		if(!value) {
			return value;
		}
		value = value.replace("\r\n", "<br/>");
		value = value.replace("\r", "<br/>");
		value = value.replace("\n", "<br/>");
		return value;
	}
	
	
}

BSDTypeUtils = {
	DEPENDENCIES: new Array(),
	
	isArray: function(value) {
	    return BSDTypeUtils.isObject(value) && value.constructor == Array;		
	},
	
	isBoolean: function(value) {	
		return typeof value == 'boolean';
	},
		
	isEmpty: function(value) {
	    var i, v;
	    if (isObject(value)) {
	        for (i in value) {
	            v = value[i];
	            if (BSDTypeUtils.isUndefined(v) && BSDTypeUtils.isFunction(v)) {
	                return false;
	            }
	        }
	    }
	    return true;
	}, 
	
	isFunction: function(value) {
	    return typeof value == 'function';	
	},
	
	isNull: function(value) {
		return value == nulll;
	},
	
	isNumber: function(value) {
		return typeof value == 'number'; // && BSDTypeUtils.isFinite(value);
	},
	
	isObject: function(value) {
		return (value && typeof value == 'object');
	},

	isString: function(value) {
		return typeof value == 'string';
	},
	
	isUndefined: function(value) {
		return typeof value == 'undefined';
	}
	
}

BSDBrowserUtils = {
	DEPENDENCIES: new Array(),

	getIsSafari: function() {
		if(!navigator.userAgent) {
			return false;
		}
		return navigator.userAgent.indexOf('Safari/') > -1;
	},
	
	getIsSafari3: function() {
		if(!navigator.userAgent) {
			return false;
		}
		return navigator.userAgent.indexOf('Safari/5') > -1;
	},
	
	getIsWebkit: function() {
		if(!navigator.userAgent) {
			return false;
		}
		return navigator.userAgent.indexOf('WebKit') > -1;
	},
	
	getIsMSIE: function() {
		if(!navigator.userAgent) {
			return false;
		}
		return navigator.userAgent.indexOf('MSIE') > -1;	
	},
	
	getIsMSIE8: function() {
		return BSDBrowserUtils.getIsMSIE() && document.documentMode;
	},
	
	getIsOpera: function() {
		return window.opera;
	},
	
	setCookie: function(name, value, days) {
		var expires;
		if(days) {
			var date = new Date();
			date.setTime(date.getTime()+(days*24*60*60*1000));
			expires = "; expires="+date.toGMTString();
		} else  {
			var expires = "";
		}
		document.cookie = name + "=" + value+expires + "; path=/";
	},

	getCookieValue: function(name) {
		var nameEQ = name + "=";
		var ca = document.cookie.split(';');
		for(var i = 0; i < ca.length; i++) {
			var c = ca[i];
			while(c.charAt(0) == ' ') {
				c = c.substring(1, c.length);
			}
			if(c.indexOf(nameEQ) == 0)  {
				return c.substring(nameEQ.length, c.length);
			}
		}
		return null;
	},

	eraseCookie: function(name) {
		createCookie(name, "", -1);
	}
	
			
	
	
}	
var bsdObjectsByClassHash;

BSDDOMUtils = {
	DEPENDENCIES: new Array("BSDStringUtils", "BSDTypeUtils", "util/BSDBrowserUtils"),
	VERSION: 1.3,

	setElementValue: function(element, value) {
		if(element.innerHTML) {
			element.innerHTML = value;
		} else if(element.nodeName && element.nodeName == 'input') {
			element.value = value;
		} else if(element.nodeType == 1) {
			var children = element.childNodes;
			for(i = 0; children && i < children.length; i++) {
				var currentChild = children[i];
				element.removeChild(currentChild);
			}
			var newTextNode = document.createTextNode(value);
			element.appendChild(newTextNode);
		} else {
			alert("Couldn't set value for node type " + element.nodeType);
		}
	},

	getAttributeValue: function(element, attributeName) {

		if(!element) {
			return;
		}
		if(element.getAttribute) {
			var currentAttribute = element.getAttribute(attributeName);
			if(currentAttribute) {
				return currentAttribute;
			}
		} else if(element.attributes) {
			var currentAttr = element.attributes[attributeName];
			if(currentAttr) {
				return currentAttr.value;
			}
		} else {

		}	



		
	},
	
	setAttributeValue: function(element, attributeName, attributeValue) {
		element.setAttribute(attributeName, attributeValue);
	},

	removeAttribute: function(element, attributeName) {
		element.removeAttribute(attributeName);
	},

	getObjectById: function(id, doc) {
		if(!doc) {
			doc = document;
		}
		
	    if(doc.getElementById) {
	        return doc.getElementById(id);
	    } else if(doc.all) {
	        return doc.all[id];
	    } else if(doc.layers) {
	        return doc.layers[id];
	    }	
	},
	
	getParentObjectByClass: function(element, className) {
		if(BSDDOMUtils.containsClass(element, className)) {
			return element;
		} else if(element.parentNode) {
			return this.getParentObjectByClass(element.parentNode, className);
		} else {

		}		
	},

	getParentObjectById: function(element, objectId) {
		if(element.id == objectId) {
			return element;
		} else if(element.parentNode) {
			return this.getParentObjectById(element.parentNode, objectId);
		} else {

		}		
	},

	getParentObjectByNodeName: function(element, nodeName, includeCurrent) {
		if(includeCurrent && element.nodeName && element.nodeName.toLowerCase() == nodeName.toLowerCase()) {

			return element;
		}
		if(element.parentNode == element || !element.parentNode || !element.parentNode.nodeName) {

			return null;
		}
		if(element.parentNode.nodeName.toLowerCase() == nodeName.toLowerCase()) {

			return element.parentNode;
		} else {

			return BSDDOMUtils.getParentObjectByNodeName(element.parentNode, nodeName);
		}
	},
	
	getObjectByNodeNameFromParent: function(parent, nodeName, includeCurrent) {
		if(includeCurrent && parent.nodeName && parent.nodeName.toLowerCase() == nodeName) {
			return parent;
		}
		for(var i = 0; i < parent.childNodes.length; i++) {
			var currentChild = parent.childNodes[i];
			if(currentChild.nodeName && currentChild.nodeName.toLowerCase() == nodeName) {
				return currentChild;
			}
		}
		for(var i = 0; i < parent.childNodes.length; i++) {
			var result = BSDDOMUtils.getObjectByNodeNameFromParent(parent.childNodes[i], nodeName, true);
			if(result) {
				return result;
			}
		}
		
	},

	getObjectByIdFromParent: function(parent, id, elementClassToIgnore) {
		if(!parent) {
			return;
		}
		var children = parent.childNodes;
		if(!children) {
			return null;
		}
		if(arguments.length > 3) {
			elementClassToIgnore = new Array();
			for(var i = 2; i < arguments.length; i++) {
				BSDArrayUtils.append(elementClassToIgnore, arguments[i]);
			}
		}
		
		for(var i = 0; i < children.length; i++) {
			var currentChild = children[i];
			if(currentChild.id == id && (!elementClassToIgnore || !BSDDOMUtils.containsClass(currentChild, elementClassToIgnore))) {
				return currentChild;
			}
		}
		for(var i = 0; i < children.length; i++) {
			var currentChild = children[i];
			if(!elementClassToIgnore || !BSDDOMUtils.containsClass(currentChild, elementClassToIgnore)) {
				var childValue = BSDDOMUtils.getObjectByIdFromParent(currentChild, id, elementClassToIgnore);
				if(childValue != null) {
					return childValue;
				}
			}
		}
	    return null;
	}, 

	getObjectByIdPrefixFromParent: function(parent, idPrefix, elementClassToIgnore) {
		var children = parent.childNodes;
		if(!children) {
			return null;
		}
		
		if(arguments.length > 3) {
			elementClassToIgnore = new Array();
			for(var i = 2; i < arguments.length; i++) {
				BSDArrayUtils.append(elementClassToIgnore, arguments[i]);
			}
		}
		
		for(var i = 0; i < children.length; i++) {
			var currentChild = children[i];
			if(currentChild.id && currentChild.id.indexOf(idPrefix) == 0 && (!elementClassToIgnore || !BSDDOMUtils.containsClass(currentChild, elementClassToIgnore))) {
				return currentChild;
			}
		}
		for(var i = 0; i < children.length; i++) {
			var currentChild = children[i];
			if(!elementClassToIgnore || !BSDDOMUtils.containsClass(currentChild, elementClassToIgnore)) {
				var childValue = BSDDOMUtils.getObjectByIdPrefixFromParent(currentChild, idPrefix, elementClassToIgnore);
				if(childValue != null) {
					return childValue;
				}
			}
		}
	    return null;
	}, 

	getObjectsByClass: function(className, parentElement, elementArray, elementClassToIgnore) {
		if(parentElement || elementArray || elementClassToIgnore) {
			return BSDDOMUtils.getObjectsByClassInternal(className, parentElement, elementArray, elementClassToIgnore);
		}
		if(document.getElementsByClassName) {
			return document.getElementsByClassName(className);
		}
		if(!bsdObjectsByClassHash) {
			BSDDOMUtils.buildObjectsByClassHash();
		} 
		
		var elementArray = bsdObjectsByClassHash[className];
		if(!elementArray) {

			elementArray = new Array();
		} 
		
		return elementArray;		
	},

	buildObjectsByClassHash: function() {
		bsdObjectsByClassHash = new Array();
		BSDDOMUtils.buildObjectsByClassHashByElement(document, true);
	},

	buildObjectsByClassHashByElement: function(parentElement) {
		if(!parentElement) {
			BSDLogUtils.error("Got null parentElement for buildObjectsByClassHashByElement");
			return;
		}
		if(parentElement.className) {
	        var split = parentElement.className.split(/\s+/);
	        for(var j = 0; j < split.length; j++) {
	        	var currentClassName = split[j];
	        	if(currentClassName.length < 1) {
	        		continue;
	        	}
				var classElements = bsdObjectsByClassHash[currentClassName];
				if(!classElements) {
					classElements = new Array();
					bsdObjectsByClassHash[currentClassName] = classElements;
				}
				classElements[classElements.length] = parentElement;				
			}			
		}
		
		
		var childNodes = parentElement.childNodes;
		for(var i = 0; childNodes && i < childNodes.length; i++) {
			var currentChild = childNodes[i];
			BSDDOMUtils.buildObjectsByClassHashByElement(currentChild);
		} 
		
	},
	
	getObjectsByClassInternal: function(className, parentElement, elementArray, elementClassToIgnore) {
		if(!elementArray) {
			elementArray = new Array();
		}
		if(!className) {
			return elementArray;
		}
		if(!parentElement) {
			parentElement = document;
		}
	    var children = parentElement.childNodes;
	    if(!children) {
	   		return elementArray;
	    }
	    for(var i = 0; i < children.length; i++) {
	        var currentChild = children[i];
		    if(currentChild.nodeType != 1) {
			    continue;
	        }	
	        
	        var split = currentChild.className.split(/\s+/);
	        for(var j = 0; j < split.length; j++) {
	        	var currentClassName = split[j];
	        	if(!currentClassName || currentClassName.length < 1) {
	        		continue;
	        	}

			    if(currentClassName == className) {
			        var index = elementArray.length;
			        elementArray[index] = currentChild;
		        } else if(elementClassToIgnore && currentClassName == elementClassToIgnore) {

		        	continue;
		        }
		    }	        
	        
		    BSDDOMUtils.getObjectsByClass(className, currentChild, 
							elementArray, elementClassToIgnore);
	    }
	    return elementArray;
	},
	
	getObjectsById: function(id, parentElement, elementArray) {
		if(!elementArray) {
			elementArray = new Array();
		}
		if(!id) {
			return elementArray;
		}
		if(!parentElement) {
			parentElement = document;
		}
	    var children = parentElement.childNodes;
	    if(!children) {
	   		return elementArray;
	    }
	    for(var i = 0; i < children.length; i++) {
	        var currentChild = children[i];
		    if(currentChild.nodeType != 1) {
			    continue;
	        }	
		    if(currentChild.id == id) {
		        var index = elementArray.length;
		        elementArray[index] = currentChild;
	        }
		    BSDDOMUtils.getObjectsById(id, currentChild, 
							elementArray);
	    }
	    return elementArray;
	},

	getObjectsByNodeName: function(parentElement, nodeName, elementArray) {
		if(!elementArray) {
			elementArray = new Array();
		}
		if(!nodeName) {
			return elementArray;
		}
		if(!parentElement) {
			BSDLogUtils.error("ERROR: Got null parentElement for getObjectsByNodeName()");
			return;
		}
	    var children = parentElement.childNodes;
	    if(!children) {
	   		return null;
	    }
	    for(var i = 0; i < children.length; i++) {
	        var currentChild = children[i];
		    if(currentChild.nodeType != 1) {
			    continue;
	        }	
		    if(currentChild.nodeName == nodeName) {
		        var index = elementArray.length;
		        elementArray[index] = currentChild;
	        }
		    BSDDOMUtils.getObjectsByNodeName(currentChild, nodeName, 
							elementArray);
	    }
	    return elementArray;
	},

	getRootElement: function() {
		if(document.documentElement) {
			return document.documentElement;
		}
		return null;
	},
	
	getNextElementSibling: function(element) {
		var sibling = element.nextSibling;
		while(sibling && sibling.nodeType != 1) {
			sibling = sibling.nextSibling;
		}
		return sibling;
	},

	getPreviousElementSibling: function(element) {
		var sibling = element.previousSibling;
		while(sibling && sibling.nodeType != 1) {
			sibling = sibling.previousSibling;
		}
		return sibling;
	},
	
	getElementStyle: function(element, styleName) {
		if(!element.style) {

			return;
		}
		var ieStyleName = BSDStringUtils.toCamelCase(styleName);
		var styleValue = element.style[ieStyleName];
	    if(!styleValue) {
			if(document.defaultView && document.defaultView.getComputedStyle) {
	        	var cssStyleValue = document.defaultView.getComputedStyle(element, "");
	        	if(!cssStyleValue) {
	        		return null;
	        	}
	        	styleValue = cssStyleValue.getPropertyValue(styleName);

	      	} else if(element.currentStyle) {
	        	styleValue = element.currentStyle[ieStyleName];
	      	}
	  	}

		if(styleValue == 'auto') {
			return null;
		}
	  	return styleValue;
	},
	
 
	elementContainsStyle: function(element, stylePropertyName, stylePropertyValue) {
	    stylePropertyValue = stylePropertyValue.toLowerCase();
	    if(element.style && element.style[stylePropertyName] &&
						element.style[stylePropertyName].toLowerCase() == stylePropertyValue) {
			return true;
	    }
	    return false;
	},

	setElementStyle: function(element, stylePropertyName, stylePropertyValue) {
		BSDDOMUtils.changeElementStyle(element, stylePropertyName, stylePropertyValue);
	},
		
	changeElementStyle: function(element, stylePropertyName, stylePropertyValue) {
		if(!element) {
			return;
		}
	    var elementStyle = element.style;
	    if(elementStyle) {
	    	try {
			    elementStyle[stylePropertyName] = stylePropertyValue;
			} catch (err) {  


			}
		}
		if(stylePropertyName == 'background-color') {
			element.style.backgroundColor = stylePropertyValue;
		} else if(stylePropertyName == 'font-family') {
			element.style.fontFamily = stylePropertyValue;
		} else if(stylePropertyName == 'text-align') {
			element.style.textAlign = stylePropertyValue;
		}
	},
	
	cloneElementStyle: function(source, target, stylePropertyName) {
		if(stylePropertyName) {
			var value = BSDDOMUtils.getElementStyle(source, stylePropertyName);
			if(value) {

				BSDDOMUtils.changeElementStyle(target, stylePropertyName, value);
			}
			return value;
		}
	},
	
	cloneAllElementStyles: function(source, target) {
		for(var styleName in source.style) {
			if(styleName) {
				BSDDOMUtils.cloneElementStyle(source, target, styleName);
			}
		}
	
	},
	
	getElementMargin: function(source, tryChildren) {
		var margin = BSDDOMUtils.getElementStyle(source, 'margin');
		var iTop = 0;
		var iRight = 0;
		var iLeft = 0;
		var iBottom = 0;
		if(margin) {
			var split = margin.split(/\s*px\s*/i);
			if(split.length < 1 && margin.length > 0) {
				iTop = parseInt(margin);
			}
			if(split.length > 0) {
				iTop = parseInt(split[0]);
			}
			if(split.length > 1) {
				iRight = parseInt(split[1]);
			}
			if(split.length > 2) {
				iBottom = parseInt(split[2]);
			}
			if(split.length > 3) {
				iLeft = parseInt(split[3]);
			}			
		}
		
		var marginTop = BSDDOMUtils.getElementStyle(source, 'margin-top');
		if(marginTop && marginTop.length > 2) {
			iTop = marginTop.replace(/\s*px\s*/i, '');
		}
		var marginRight = BSDDOMUtils.getElementStyle(source, 'margin-right');
		if(marginRight && marginRight.length > 2) {
			iRight = marginRight.replace(/\s*px\s*/i, '');
		}
		var marginBottom = BSDDOMUtils.getElementStyle(source, 'margin-bottom');
		if(marginBottom && marginBottom.length > 2) {
			iBottom = marginBottom.replace(/\s*px\s*/i, '');
		}
		var marginLeft = BSDDOMUtils.getElementStyle(source, 'margin-left');
		if(marginLeft && marginLeft.length > 2) {
			iLeft = marginLeft.replace(/\s*px\s*/i, '');
		}

		if(tryChildren && iTop == 0 && iRight == 0 && iBottom == 0 && iLeft == 0) {

			var marginChild = null;
			for(var i = 0; i < source.childNodes.length; i++) {
				var currentChild = source.childNodes[i];
				if(currentChild.nodeType == 1 && !BSDVisibilityUtils.isObjectHidden(currentChild)) {
					if(!marginChild) {
						marginChild = currentChild;
					} else {
						marginChild = null;
						break;
					}
				}
				if(marginChild) { 
					return BSDDOMUtils.getElementMargin(marginChild, false);
				}
			}		
		}
		
		var margin = new Object();
		
		margin.margin = iTop + 'px ' + iRight + 'px ' + iBottom + 'px ' + iLeft + 'px';
		margin.top = iTop;
		margin.right = iRight;
		margin.bottom = iBottom;
		margin.left = iLeft;


		return margin;
	},

	
	getElementWidth: function(element) {
		var iWidth = element.offsetWidth;
		if(iWidth && iWidth > 0) {
			return iWidth;
		}
		var width = BSDDOMUtils.getElementStyle(element, 'width');
		if(width && width.length > 0) {
			width = width.replace(/\s*px\s*/i, '');
			return parseInt(width);
		}
		
		width = BSDDOMUtils.getAttributeValue(element, 'width');		
		if(width && width.length > 0) {
			return parseInt(width);
		}
		return 0;
	},
	
	setElementWidth: function(element, newWidth) {
		BSDDOMUtils.changeElementStyle(element, 'width', newWidth + 'px');
	},
	
	getElementHeight: function(element) {
		var iHeight = element.offsetHeight;
		if(iHeight && iHeight > 0) {
			return iHeight;
		}
		var height = BSDDOMUtils.getElementStyle(element, 'height');
		if(height && height.length > 0) {
			height = height.replace(/\s*px\s*/i, '');
			return parseInt(height);
		}
		height = BSDDOMUtils.getAttributeValue(element, 'height');
		if(height && height.length > 0) {
			return parseInt(height);
		}
		return 0;
	},
	
	setElementHeight: function(element, newHeight) {
		BSDDOMUtils.changeElementStyle(element, 'height', newHeight + 'px');
	},
	
	getDocumentWidth: function(doc) {
		if(!doc) {
			doc = document;
		}
		if(doc.body) {
			return doc.body.clientWidth;
		} else if(doc.documentElement) {
			return doc.documentElement.clientWidth;
		}
	},
	
	getDocumentHeight: function(doc) {
		if(!doc) {
			doc = document;
		}
		if(doc.body) {
			return doc.body.clientHeight;
		} else if(doc.documentElement) {
			return doc.documentElement.clientHeight;
		}
	},
	
	cloneElement: function(sourceElement, doShallowClone) {
		var deep = true;
		if(doShallowClone) {
			deep = false;
		}
		return sourceElement.cloneNode(deep);
	},    

	cloneElementDimensions: function(source, target, deltaWidth, deltaHeight) {
	    var newWidth = source.offsetWidth;
	    var newHeight = source.offsetHeight;
	    if(deltaWidth) {
			newWidth += deltaWidth;
	    }
	    if(deltaHeight) {
			newHeight += deltaHeight;
	    }
	    BSDDOMUtils.changeElementStyle(target, 'width', newWidth);
	    BSDDOMUtils.changeElementStyle(target, 'height', newHeight);
	},

	cloneDimensions: function(sourceDimensions, target) { 
	    BSDDOMUtils.changeElementStyle(target, 'width', sourceDimensions.width);
	    BSDDOMUtils.changeElementStyle(target, 'height', sourceDimensions.height);	
	},
	
	cloneElementMargins: function(source, target, tryChildren) {
		var margin = BSDDOMUtils.getElementMargin(source, tryChildren);
		BSDDOMUtils.changeElementStyle(target, 'margin', margin.margin);

		return margin.margin != '0px 0px 0px 0px';		

	},

	createElement: function(nodeName, parent, id, className) {
		return BSDDOMUtils.createElementByDoc(document, nodeName, parent, id, className);
	},

	createElementByDoc: function(doc, nodeName, parent, id, className) {

		var element = doc.createElement(nodeName);	
		if(parent) {
			parent.appendChild(element);
		}
		if(id) {
			element.id = id;
		}
		if(className) {
			element.className = className;
		}
		return element;
	},
	
	removeElement: function(element) {
		var parent = element.parentNode;
		if(!parent) {
			return;
		}
		if(element.nodeName == 'TR') {
			while(parent && parent.nodeName != 'TABLE') {
				parent = parent.parentNode;
			}
			if(parent) {
				parent.deleteRow(element.rowIndex);
			} else {
				BSDLogUtils.error("ERROR: Couldn't find table parent for row to remove");
			}
		} else {
			parent.removeChild(element);
		}
	},
	
	getPreviousSiblingElement: function(element) {
		var sibling = element.previousSibling;
		while(sibling && sibling.nodeType != 1) {
			sibling = sibling.previousSibling;
		}
		return sibling;
	},
	
	getNextSiblingElement: function(element) {
		var sibling = element.nextSibling;
		while(sibling && sibling.nodeType != 1) {
			sibling = sibling.nextSibling;
		}
		return sibling;
	},
	
	setCursor: function(element, cursorName) {
		BSDDOMUtils.changeElementStyle(element, 'cursor', cursorName);
	},

	setMoveCursor: function(element) {
		BSDDOMUtils.setCursor(element, 'move');
	},
	
	setDefaultCursor: function(element) {
		BSDDOMUtils.setCursor(element, 'default');
	},
	
	setClass: function(element, className) {
		element.className = className;
	},
	
	addClass: function(element, className, prepend) {
		if(element.className) {
			if(prepend) {
				element.className = className + " " + element.className;
			} else {
				element.className += " " + className;
			}
		} else {
			element.className = className;
		}
	},
	
	removeClass: function(element, className) {
		if(!element.className || element.className.length < 1) {
			return;
		}
		var newClassName = "";
		var split = element.className.split(/\s+/);
	    for(var i = 0; i < split.length; i++) {
	        var currentClassName = split[i];
	        if(!currentClassName || currentClassName.length < 1) {
	        	continue;
	        }

			if(currentClassName != className) {
				newClassName += currentClassName;
				if(i < split.length -1) {
					newClassName += " ";
				}
			}
		}
		element.className = newClassName;
	},
	
	containsClass: function(element, className) {
		if(!element.className || !className) {
			return false;
		}
		var multipleClasses = BSDTypeUtils.isArray(className);
        var split = element.className.split(/\s+/);
        for(var j = 0; j < split.length; j++) {
        	var currentClassName = split[j];
        	if(!currentClassName || currentClassName.length < 1) {
        		continue;
        	}

        	if(multipleClasses && BSDArrayUtils.contains(className, currentClassName)) {
        		return true;
		    } else if(currentClassName == className) {
		    	return true;
	        } 
	    }		
	    return false;
	},
	
	removeClassByClass: function(elementClass, classToRemove) {
		var elements = BSDDOMUtils.getObjectsByClass(elementClass);
		for(var i = 0; i < elements.length; i++) {
			BSDDOMUtils.removeClass(elements[i], classToRemove);
		}
	},
	
	addChild: function(element, child) {
		element.appendChild(child);
	},
	
	moveElement: function(element, newParent) {
		BSDDOMUtils.removeElement(element);
		BSDDOMUtils.addChild(newParent, element);
	},
	
	replaceElement: function(oldElement, newElement) {
		if(oldElement && oldElement.parentNode) {
			oldElement.parentNode.replaceChild(newElement, oldElement);
		}
	},
	
	replaceElementByIdAndHtml: function(oldElementId, newElementHtml) {
		var oldElement = BSDDOMUtils.getObjectById(oldElementId);
		if(!oldElement) {
			BSDLogUtils.warning("Couldn't find element to replace with id: " + oldElementId);
			return;
		}
		return BSDDOMUtils.replaceElementByHtml(oldElement, newElementHtml);
	},
	
	replaceElementByHtml: function(oldElement, newElementHtml) {
		newElementHtml = newElementHtml.replace(/scripx/g, 'script');

		oldElement.innerHTML = newElementHtml;
		var newNode;
		if(oldElement.childNodes && oldElement.childNodes.length && oldElement.childNodes.length == 1) {
			newNode = oldElement.childNodes[0];
			BSDDOMUtils.replaceElement(oldElement, newNode);
		}
		return newNode;
	},
	
	replaceElementByParentId: function(parentElementId) {
		var parentElement = BSDDOMUtils.getObjectById(parentElementId);
		if(!parentElement) {
			BSDLogUtils.warning("Couldn't find parent element to replace with id: " + parentElementId);
			return;
		}

		var elementsToMove = new Array();
		for(var i = 0; i < parentElement.childNodes.length; i++) {

			var currentElement = parentElement.childNodes[i];

			if(currentElement.nodeType != 1) {
				continue;
			}
			var targetId = BSDDOMUtils.getAttributeValue(currentElement, 'rid');
			if(!targetId) {
				BSDLogUtils.warning("Couldn't find target id for element to replace: " + currentElement.id);
				continue;
			}
			var target = BSDDOMUtils.getObjectById(targetId);
			if(!target) {
				BSDLogUtils.warning("Couldn't find target element to replace: " + targetId);
				continue;
			}
			
			var currentHolder = new Object();
			currentHolder.source = currentElement;
			currentHolder.target = target;
			elementsToMove[elementsToMove.length] = currentHolder;
		}
		for(var i = 0; i < elementsToMove.length; i++) {
			var currentHolder = elementsToMove[i];
			BSDDOMUtils.replaceElement(currentHolder.target, currentHolder.source);

		}
	

	},
	
	addText: function(element, text) {
		var textNode = document.createTextNode(text);
		element.appendChild(textNode);
	},
	
	setText: function(element, text) {
		if(!element || !element.childNodes) {
			BSDLogUtils.error("Cannot set text on null element");
			return;
		}
		if(element.nodeName && element.nodeName.toLowerCase() == 'input') {
			element.value = text;
		} else if(element.nodeName && element.nodeName.toLowerCase() == 'select') {
			if(!text || text.length < 1) {
				if(element.options && element.options.length > 0) {
					element.options[0].selected = true;
					return;
				}
			}
			for(var i = 0; i < element.childNodes.length; i++) {
				var currentChild = element.childNodes[i];
				var value = currentChild.value;
				if(value && value == text) {
					currentChild.selected = true;
					break;
				} else if(!value && BSDDOMUtils.getText(element) == text) {
					currentChild.selected = true;
					break;
				}
			}
		} else if(element.nodeType == 3) {
			element.nodeValue = text;
		} else {			
			for(var i = 0; i < element.childNodes.length; i++) {
				if(element.childNodes[i].nodeType == 3) {
					element.removeChild(element.childNodes[i]);
					i--;
				} 
			}
			BSDDOMUtils.addText(element, text);
		}
		
	},
	
	setTextById: function(elementId, text, parentElement) {
		var element;
		if(parentElement) {
			element = BSDDOMUtils.getObjectByIdFromParent(parentElement, elementId);
		} else {
			element = BSDDOMUtils.getObjectById(elementId);
		}
		if(!element) {
			return;
		}
		BSDDOMUtils.setText(element, text);
		return element;
	},
	
	setTextByClass: function(elementClass, text, parentElement) {
		var objects = BSDDOMUtils.getObjectsByClass(elementClass, parentElement);
		for(var i = 0; i < objects.length; i++) {
			BSDDOMUtils.setText(objects[i], text);
		}
		return objects;
	},
	
	getText: function(element) {
		var text = "";
		if(!element) {
			return text;
		}
		if(element.nodeName && element.nodeName.toLowerCase() == 'input') {
			return element.value;
		}
		
		if(element.nodeType == 3) {
			return element.nodeValue;
		} else if(!element.childNodes) {
			return text;
		}
		for(var i = 0; i < element.childNodes.length; i++) {
			if(element.childNodes[i].nodeType == 3) {
				text += element.childNodes[i].nodeValue;
			}		
		}
		return text;
	},
	
	getTextById: function(elementId, parentNode) {
		var element;
		if(parentNode) {
			element = BSDDOMUtils.getObjectByIdFromParent(parentNode, elementId);
		} else {
			element = BSDDOMUtils.getObjectById(elementId);
		}
		if(!element) {
			return;
		}
		return BSDDOMUtils.getText(element);	
	},
	
	appendElementToRoot: function(element) {
		if(document.body) {
			document.body.appendChild(element);
		} else {
			for(var i = 0; i < document.childNodes.length; i++) {
				document.childNodes[i].appendChild(element);
			}
		}
	},
	
	clear: function(element) {
		if(element.nodeName.toLowerCase() == 'table' && element.tBodies && element.tBodies.length > 0) {
			for(var i = 0; i < element.tBodies.length; i++) {

				BSDDOMUtils.clear(element.tBodies[i]);
			}
		} else {
		    while(element.childNodes.length > 0) {

				element.removeChild(element.childNodes[0]);
			}
		}	
	},
	
	getContainsChildElements: function(element, exceptionClass) {
		if(!element || !element.childNodes) {
			return false;
		}
		for(var i = 0; i < element.childNodes.length; i++) {
			var currentChild = element.childNodes[i];
			if(exceptionClass && BSDDOMUtils.containsClass(currentChild, exceptionClass)) {
				continue;
			}
			if(currentChild.nodeType == 1) {
				return true;
			}
		}
		return false;
	},
	
	insertAfter: function(existingElement, newElement) {
		var parentNode = existingElement.parentNode;
		if(!parentNode) {
			return false;
		}
		if(existingElement.nextSibling) {
			parentNode.insertBefore(newElement, existingElement.nextSibling);
		} else {
			parentNode.appendChild(newElement);
		}
		
		return true;
	},
	
	insertBefore: function(existingElement, newElement) {
		var parentNode = existingElement.parentNode;
		if(!parentNode) {
			return false;
		}

		if(existingElement.nodeName.toUpperCase() == 'TR' && !newElement.nodeName.toUpperCase() == 'TR') {
			var row = document.createElement('tr');
			if(!newElement.nodeName.toUpperCase() == 'TD') {
				var column = document.createElement('td');
				column.appendChild(newElement);
				row.appendChild(column);
			} else {
				row.appendChild(newElement);
			}
			newElement = row;
		} 

		parentNode.insertBefore(newElement, existingElement);
		
		return true;
	},
	
	insertChild: function(parentElement, newElement, index) {
		if(!parentElement) {
			BSDLogUtils.error("Got null parentElement for insertChild");
			return;
		}
		var childNodes = parentElement.childNodes;
		if(index >= 0 && childNodes.length > index) {
			BSDDOMUtils.insertBefore(childNodes[index], newElement);
		} else {
			BSDDOMUtils.addChild(parentElement, newElement);
		}
	},
	
	getElementParentIndex: function(element) {
		var parentNode = element.parentNode;
		for(var i = 0; i < parentNode.childNodes.length; i++){
			if(parentNode.childNodes[i] == element) {
				return i;
			}
		}
	},
	
	appendAsRow: function(table, rowContents) {
		var row = document.createElement('tr');
		var column = document.createElement('td');
		
		column.innerHTML = rowContents;
		table.tBodies[0].appendChild(row);
		row.appendChild(column);
	},
	
	setInnerHTML: function(element, content) {
  		if(element.nodeName.toUpperCase() == 'TABLE') {
  			BSDDOMUtils.clear(element);
  			if(BSDStringUtils.startsWith(content, '<tr') && element.tBodies && element.tBodies.length > 0) {
  				element.tBodies[0].innerHTML = content;
  			} else {
				BSDDOMUtils.appendAsRow(element, content);
			}
  		} else {
	  		element.innerHTML = content;
	  	}
	
	},
	
	getFrameDocument: function(frame) {
		if(frame.contentDocument) {
			return frame.contentDocument;
		} else if(frame.contentWindow && frame.contentWindow.document) {
			return frame.contentWindow.document;
		} else {
			return frame.document; //ie
		}
	},
	
	getRangeObject: function(selectionObject, doc) {
		if(selectionObject.getRng && selectionObject.getRng()) {
			return selectionObject.getRng();
		} else if(selectionObject.getRangeAt) {
			return selectionObject.getRangeAt(0);
		} else { // Safari!
			if(!doc) {
				doc = document;
			}
			var range = doc.createRange();
			if(selectionObject.anchorNode) {
				range.setStart(selectionObject.anchorNode,selectionObject.anchorOffset);
			}
			if(selectionObject.focusNode) {
				range.setEnd(selectionObject.focusNode,selectionObject.focusOffset);
			}
			return range;
		}
	},
	
	copyTable: function(source, target, removeExisting) {

		var tbody = null;
		for(var i = 0; i < target.childNodes.length; i++) {
			var currentChild = target.childNodes[i];
			if(currentChild.nodeName == 'TBODY') {
				tbody = currentChild;
			} else if(removeExisting) {
				BSDDOMUtils.removeElement(currentChild);
			}
		}

		if(tbody && removeExisting) {

			for(var i = 0; i < tbody.childNodes.length; i++) {
				BSDDOMUtils.removeElement(tbody.childNodes[i]);
			}	
		} else if(!tbody) {
			tbody = target;
		}
		for(var i = 0; i < source.childNodes.length; i++) {
			var currentChild = source.childNodes[i];
			if(currentChild.nodeName == 'TBODY') {
				for(var j = 0; j < currentChild.childNodes.length; j++) {
					tbody.appendChild(currentChild.childNodes[j]);

				}	
			} else {
				tbody.appendChild(currentChild);
			}
		}

	},
	
	wrapSelectionByElement: function(selectionObject, doc, newElement) {
		var range = BSDDOMUtils.getRangeObject(selectionObject, doc);
		if(!range || !range.startContainer || range.collapsed) {

			return null;
		}

		if(range.startContainer.nodeType == 3) { //text
			var text = BSDDOMUtils.getText(range.startContainer);
			if(text.length == range.startOffset - range.endOffset) { //the whole element is selected - return it
				return range.startContainer;
			}
			var startText; 
			var endText;
			var selectText;
			if(range.startOffset > 0) {
				startText = text.substring(0, range.startOffset);
			}
			if(range.endContainer == range.startContainer) {
				selectText = text.substring(range.startOffset, range.endOffset);
				endText = text.substring(range.endOffset);
			} else {
				selectText = text.substring(range.startOffset);
			}

			var startNode;
			if(startText && startText.length > 0) {
				startNode = doc.createTextNode(startText);
			}
			if(range.endContainer == range.startContainer) {
				var endNode;
				if(endText && endText.length > 0) {
					endNode = doc.createTextNode(endText);
				}
				BSDDOMUtils.setText(newElement, selectText);
				if(endNode) {
					BSDDOMUtils.insertAfter(range.startContainer, endNode);			
				}
				if(startNode) {
					BSDDOMUtils.insertAfter(range.startContainer, startNode);
				}
				BSDDOMUtils.insertAfter(range.startContainer, newElement);
			} else {
				if(startNode) {
					BSDDOMUtils.insertBefore(range.startContainer, startNode);
				}
				if(selectText) {
					var selectTextNode = doc.createTextNode(selectText);
					BSDDOMUtils.addChild(newElement, selectTextNode);
				}
				var nextSibling = range.startContainer.nextSibling;
				while(nextSibling) {


					if(nextSibling == range.endContainer && nextSibling.nodeType == 3) {
						var curText = BSDDOMUtils.getText(nextSibling);
						var endText1 = curText.substring(0, range.endOffset);
						var endNode1 = doc.createTextNode(endText1);
						BSDDOMUtils.addChild(newElement, endNode1);
						if(range.endOffset > curText.length) {
							var endText2 = curText.substring(range.endOffset);
							var endNode2 = doc.createTextNode(endText2);
							BSDDOMUtils.insertAfter(range.startContainer, endNode2);
						}
						BSDDOMUtils.removeElement(range.endContainer);						
						nextSibling = null;
					} else {
						var nextNextSibling = nextSibling.nextSibling;
						BSDDOMUtils.addChild(newElement, nextSibling);						
						if(nextSibling != range.endContainer) {
							nextSibling = nextNextSibling;
						} else {
							nextSibling = null;
						}
					}

				}
				BSDDOMUtils.insertBefore(range.startContainer, newElement);
			}
			

			BSDDOMUtils.removeElement(range.startContainer);

		} else if(range.startContainer && range.startContainer.nodeType == 1) {
			var hasInserted = false;
			if(!hasInserted) {
				BSDDOMUtils.insertChild(range.startContainer, newElement, range.startOffset);
			}
			if(range.startContainer.nodeList) {
				for(var i = range.startOffset; i < range.endOffset && i < range.startContainer.nodeList.length; i++) {
					var currentChild = range.startContainer.nodeList[i];
					BSDDOMUtils.removeElement(currentChild);
					newElement.appendChild(currentChild);
				}
			}
		}
		
		return newElement;
	},
	
	clearStyles: function(parent, removeEmptySpans) {
		if(parent.style) {

			parent.style.cssText = '';
		}
		var childNodes = parent.childNodes;
		for(var i = 0; i < childNodes.length; i++) {
			var currentChild = childNodes[i];
			if(currentChild.nodeType == 1) {
				BSDDOMUtils.clearStyles(currentChild, removeEmptySpans);
			}
		}
		if(removeEmptySpans && parent.nodeName == 'SPAN' && !parent.id && !parent.className) {
			for(var i = 0; i < childNodes.length; i++) {
				BSDDOMUtils.insertBefore(parent, childNodes[i]);			
			}
			BSDDOMUtils.removeElement(parent);
		}
	},
	
	convertDoubleBrToP: function(parent, doc, currentParent, depth) {




		if(!doc) {
			doc = parent.ownerDocument;
		}
		if(!depth) {
			depth = 0;
		}
		var prevBr;
		if(!currentParent) {
			currentParent = parent;
		}
		var childNodes = currentParent.childNodes;
		var moveArray = new Array();
		var moveParentArray = new Array();
		var deleteArray = new Array();
		var prevElement = parent;



		for(var i = 0; i < childNodes.length; i++) {
			var currentChild = childNodes[i];
			var isBr = currentChild.nodeName == 'BR';

			/*if(isBr) {
				alert("Got br");
			} else {
				alert("Got other: " + currentChild.nodeName + " " + currentChild.id + " " + currentChild.nodeValue);
			}*/

			if(isBr && prevBr) {
				BSDArrayUtils.append(deleteArray, currentChild);
				prevBr = null;
				continue; //skip this one, as we must have already created a p for the previous br
			} else if(isBr) {
				prevBr = currentChild;
				var newP = BSDDOMUtils.createElementByDoc(doc, "p");
				currentParent = newP;
				newP.bsdIndex = i;
				BSDArrayUtils.append(deleteArray, currentChild);

			} else if(currentChild.nodeName == 'DIV' && currentChild.id == '_mcePaste') {
				var hadParent = false;
				BSDArrayUtils.append(deleteArray, currentChild);
				/* as of 1/23/2010, webkit browsers send both divs like this and plain text nodes. ignore the divs and the plain text will get put into p nodes automatically
				continue;
				if(true) {
					continue;
				}
				if(currentChild.innerHTML == '<br style="">') {
					continue;
				}
				if(currentParent) {

					hadParent = true;
				}

				currentParent = BSDDOMUtils.createElementByDoc(doc, "p");				
				currentParent.innerHTML = currentChild.innerHTML;
				currentParent.id = i;


				BSDArrayUtils.append(moveArray, currentChild);
				BSDArrayUtils.append(moveParentArray, currentParent);

				prevElement = currentParent;
				if(hadParent) {
					currentParent = BSDDOMUtils.createElementByDoc(doc, "p");
				}
				*/
			} else if(currentChild.nodeType == 1) {

				prevElement = currentChild;
			}
			if(currentChild.nodeType == 3 && !isBr && currentParent && currentParent != parent && currentChild.nodeValue && BSDStringUtils.trim(currentChild.nodeValue).length > 0) { //move text nodes
				currentParent.innerHTML = currentChild.nodeValue;
				/*if(parent.parentNode) {
					BSDDOMUtils.insertAfter(prevElement, currentParent);					
				}*/
				/*if(!isBr && prevBr) {
					BSDArrayUtils.append(moveArray, prevBr);
					BSDArrayUtils.append(moveParentArray, currentParent);
				}*/

				BSDArrayUtils.append(moveArray, currentChild);
				BSDArrayUtils.append(moveParentArray, currentParent);
				prevElement = currentParent;
			}
			if(!isBr) {
				prevBr = null;				
			}

			
		}	

		for(var i = 0; i < moveArray.length; i++) {
			var currentChild = moveArray[i];
			var currentParent = moveParentArray[i];
			/*if(!currentChild.nodeValue && currentChild.childNodes.length < 1) {
				continue;
			}*/


			BSDDOMUtils.replaceElement(currentChild, currentParent);


			if(!currentParent.parentNode && !BSDBrowserUtils.getIsWebkit()) {
				parent.appendChild(currentParent); //ff doesn't have a parent for the pasted node
			}
		}	
		for(var i = 0; i < deleteArray.length; i++) {
			var currentChild = deleteArray[i];
			BSDDOMUtils.removeElement(currentChild);
		}

	},
	
	isBlockElement: function(currentChild) {
		return currentChild.nodeName == 'P' || currentChild.nodeName == 'DIV' || currentChild.nodeName == 'UL' 
				|| currentChild.nodeName == 'BLOCKQUOTE' || currentChild.nodeName == 'DL' || currentChild.nodeName == 'FORM'
				|| currentChild.nodeName == 'HR' || currentChild.nodeName == 'OL' || currentChild.nodeName == 'TABLE';
	},
	
	setLinkContent: function(className, prefix, content1, content2, content3) {
		var elements = BSDDOMUtils.getObjectsByClass(className);
		for(var i = 0; i < elements.length; i++) {
			var curElement = elements[i];
			curElement.href = prefix + content1 + content2 + content3;
			BSDDOMUtils.setText(curElement, content1 + content2 + content3);
		}
	}

}
BSDVisibilityUtils = {
	DEPENDENCIES: new Array("BSDDOMUtils"),
	VERSION: 1.1,
		
	switchById: function(current,next) {
	    var currentObj = BSDDOMUtils.getObjectById(current);
	    var nextObj = BSDDOMUtils.getObjectById(next);
	    if(!currentObj || ! nextObj) {
	    		return;
	    }
	    var nextObjDisplay = nextObj.style.display;
	    var nextObjVisibility = nextObj.style.visibility;
	    nextObj.style.display = currentObj.style.display;
	    nextObj.style.visibility = currentObj.style.visibility;
	    currentObj.style.display = nextObjDisplay;
	    currentObj.style.visibility = nextObjVisibility;
	},
	
	showByClass: function(className, parentNode) {
		var objects = BSDDOMUtils.getObjectsByClass(className, parentNode);
		for(var i = 0; i < objects.length; i++) {
			BSDVisibilityUtils.showObject(objects[i]);
		}
	},
	
	showByClassAndParentId: function(className, parentId) {
		var parent = BSDDOMUtils.getObjectById(parentId);	
		BSDVisibilityUtils.showByClassAndParent(className, parent);
	},
	
	showByClassAndParent: function(className, parent) {
		var objects = BSDDOMUtils.getObjectsByClass(className, parent);
		for(var i = 0; i < objects.length; i++) {
			BSDVisibilityUtils.showObject(objects[i]);
		}
	},
	
	hideByClass: function(className) {
		var objects = BSDDOMUtils.getObjectsByClass(className);
		for(var i = 0; i < objects.length; i++) {
			BSDVisibilityUtils.hideObject(objects[i]);
		}
	},
	
	hideByClassAndParentId: function(className, parentId) {
		var parent = BSDDOMUtils.getObjectById(parentId);
		BSDVisibilityUtils.hideByClassAndParent(className, parent);
	},
	
	hideByClassAndParent: function(className, parent) {
		var objects = BSDDOMUtils.getObjectsByClass(className, parent);
		for(var i = 0; i < objects.length; i++) {
			BSDVisibilityUtils.hideObject(objects[i]);
		}
	},
	
	showById: function(objectName, parent) {
	    var object;
	    if(!parent) {
	    	object = BSDDOMUtils.getObjectById(objectName);
	    } else {
	    	object = BSDDOMUtils.getObjectByIdFromParent(parent, objectName);
	    }
	    BSDVisibilityUtils.showObject(object);
	    return object;
	},
	
	showObject: function(object) {
		if(!object) {
			return;
		}
		object.style.display = "";
		object.style.visibility = "visible";
	},
	
	hideById: function(objectName, parent) {
	    var object;
	    if(!parent) {
	    	object = BSDDOMUtils.getObjectById(objectName);
	    } else {
	    	object = BSDDOMUtils.getObjectByIdFromParent(parent, objectName);
	    }
		BSDVisibilityUtils.hideObject(object);
		return object;
	},
	
	hideObject: function(object, ignoreDisplay) {
		if(!object) {
			return;
		}
		try {
			if(!ignoreDisplay) {
			    object.style.display = "none";
			} 
		    if((object.nodeName == 'TR' || object.nodeName == 'TD')) {
		    	object.style.visibility = "collapse";
		    } else {
			    object.style.visibility = "hidden";
		    }
		} catch (err) {
			try {
				if(object.nodeName == 'TR' || object.nodeName == 'TD') {
					object.style.visibility = 'hidden';
				} else {
					BSDLogUtils.error("Couldn't hide object: " + object.nodeName + " " + object.id + " " + err);
				}
		
			} catch (err2) {
				BSDLogUtils.error("Couldn't hide object: " + object.nodeName + " " + object.id + " " + err2);
			}
		}
	},
	
	showByObject: function(currentObj, nextObj) {
	    BSDVisibilityUtils.showObject(nextObj);
	    BSDVisibilityUtils.hideObject(currentObj);
	},
	
	isObjectHidden: function(object) {
	    if(object.style && object.style.display && object.style.display.toLowerCase() == 'none') {
			return true;
	    }
	    return false;
	},
	
	toggleObject: function(object) {
		if(BSDVisibilityUtils.isObjectHidden(object)) {
			BSDVisibilityUtils.showObject(object);
		} else {
			BSDVisibilityUtils.hideObject(object);		
		}
	},
	
	toggleById: function(elementId, parent) {
		var object;
		if(parent) {
			object = BSDDOMUtils.getObjectByIdFromParent(parent, elementId);
		} else {
			object = BSDDOMUtils.getObjectById(elementId);
		}
		if(object) {
			BSDVisibilityUtils.toggleObject(object);
		}
	},
	
	switchByNameAndJustify: function(switchObjectName, justifyObjectName) {
	    var switchObj = BSDDOMUtils.getObjectById(switchObjectName);
	    var justifyObj = BSDDOMUtils.getObjectById(justifyObjectName);
	
	    var existingHeight = 0;
	    if(!BSDVisibilityUtils.isObjectHidden(justifyObj)) {
			existingHeight = parseInt(justifyObj.style.height);
	    }
	    if(BSDVisibilityUtils.isObjectHidden(switchObj)) {
			showObject(switchObj);
			if(existingHeight > 0) { 
		    		switchObj.style.height = (existingHeight/2) + "%";
		    		justifyObj.style.height = (existingHeight/2) + "%";
			} 
	    } else {
	 		BSDVisibilityUtils.hideObject(switchObj);
			if(existingHeight > 0) { 
		    		switchObj.style.height = '0%';
		    		justifyObj.style.height = (existingHeight*2) + "%";
			} 
	    }
	},
	
	showIfSelected: function(object, searchValue, objectIdToShow) {

		if(object.value && object.value == searchValue) {
	       	BSDVisibilityUtils.showById(objectIdToShow);
	  	} else {
	       	BSDVisibilityUtils.hideById(objectIdToShow);
	   	}
	},

	showIfSelectedById: function(objectId, searchValue, objectIdToShow) {
		var object = BSDDOMUtils.getObjectById(objectId);
		BSDVisibilityUtils.showIfSelected(object, searchValue, objectIdToShow);
	}

}


BSDLogUtils = {
	DEPENDENCIES: new Array("BSDDOMUtils", "BSDClass"),
	VERSION: 1.1,

	isLogWindowEnabled: false,
	
	debugEnabled: true,
	warningEnabled: true,
	errorEnabled: true,
	
	logStatements: new Array(),

	showLogWindow: function() {
		var logElement = BSDLogUtils.logElement;
		if(!logElement) {
			logElement = BSDDOMUtils.getObjectById("BSDLogWindow");
		}

		if(!logElement) {
			logElement = BSDDOMUtils.createElement("div");
			logElement.id = "BSDLogWindow";
			BSDDOMUtils.changeElementStyle(logElement, 'position', 'absolute');			
			BSDDOMUtils.changeElementStyle(logElement, 'text-align', 'left');	
			BSDLogUtils.logElement = logElement;
			document.body.appendChild(logElement);

			BSDLogUtils.showLogStatements();
		}
		BSDDOMUtils.changeElementStyle(logElement, "top", 0); // + currentScrollPosition.y);
		BSDDOMUtils.changeElementStyle(logElement, "left", 450); // + currentScrollPosition.x);
				
	},

	showLogStatements: function() {
		var logElement = BSDLogUtils.logElement;
		for(var i = 0; i < BSDLogUtils.logStatements.length; i++) {
			var currentStatement = BSDLogUtils.logStatements[i];
			if(currentStatement.isError && !BSDLogUtils.errorEnabled) {
				continue;
			} else if(currentStatement.isWarning && !BSDLogUtils.warningEnabled) {
				continue;
			} else if(currentStatement.isDebug && !BSDLogUtils.debugEnabled) {
				continue;
			}
			
			BSDLogUtils.displayLogStatement(currentStatement);
		}
	},
	
	displayLogStatement: function(statement) {
		var logElement = BSDLogUtils.logElement;

		var statementElement = BSDDOMUtils.createElement("div", logElement, null, "BSDLogStatement");			
		statementElement.statementId = statement.id;

		var statementDateElement = BSDDOMUtils.createElement("span", statementElement, null, "BSDLogStatementDate");
		statementDateElement.innerHTML = statement.date.getHours() + ":" + statement.date.getMinutes() + ":" + statement.date.getSeconds();

		var statementTypeElement = BSDDOMUtils.createElement("span", statementElement, null, "BSDLogStatementType");
		statementTypeElement.innerHTML = statement.type;
		
		var statementMsgElement = BSDDOMUtils.createElement("span", statementElement, null, "BSDLogStatementMessage");
		statementMsgElement.innerHTML = statement.message;

	},		
	
	error: function(message) {
		var newStatement = new BSDLogStatement(BSDLogUtils.logStatements.length, "ERROR", message);
		BSDArrayUtils.append(BSDLogUtils.logStatements, newStatement);
		if(BSDLogUtils.errorEnabled) {
			BSDLogUtils.displayLogStatement(newStatement);		
		}
		try {
			if(typeof console != 'undefined') {
				console.error(message);
			}
		} catch (err) {
			
		}
	},
	
	warning: function(message) {
		var newStatement = new BSDLogStatement(BSDLogUtils.logStatements.length, "WARNING", message);
		BSDArrayUtils.append(BSDLogUtils.logStatements, newStatement);
		if(BSDLogUtils.warningEnabled) {
			BSDLogUtils.displayLogStatement(newStatement);		
		}
		try {
			if(typeof console != 'undefined') {
				console.warn(message);
			}
		} catch (err) {
			
		}
	},
	
	debug: function(message) {
		var newStatement = new BSDLogStatement(BSDLogUtils.logStatements.length, "DEBUG", message);
		BSDArrayUtils.append(BSDLogUtils.logStatements, newStatement);
		if(BSDLogUtils.debugEnabled) {
			BSDLogUtils.displayLogStatement(newStatement);		
		}
		try {
			if(typeof console != 'undefined') {
				console.debug(message);
			}
		} catch (err) {
			
		}
	},
	
	registerEvent: function(element, type, func) {
	    if(element.addEventListener) {
			element.addEventListener(type, func, true);
	    } else if(element.attachEvent) {
			element.attachEvent('on' + type, func);
	    } else {
	    	alert("ERROR: Couldn't register event: " + type + " " + func);
	    }

	},
	
	recordImageTime: function(src) {
		var image = new Image();
		image.src = src;
		image.width = '1';
		image.height = '1';
		var breakBlock = BSDDOMUtils.getObjectById('kcmBreakBlock');
		if(!breakBlock) {
			breakBlock = document.body;
		}
		BSDDOMUtils.insertChild(breakBlock, image, 0);

	}
	
}

if(BSDLogUtils.isLogWindowEnabled) {
	BSDLogUtils.registerEvent(window, "load", BSDLogUtils.showLogWindow);
}


BSDLogStatement = BSDClass.create();
BSDLogStatement.prototype = {

	className: "BSDLogStatement",
	initialize: function(id, type, message) {
		this.id = id;
	    this.type = type;
		this.message = message;
		this.date = new Date();
	},
	
	isError: function() {
		if(this.type == 'ERROR') {
			return true;
		}
		return false;
	},

	isWarning: function() {
		if(this.type == 'WARNING') {
			return true;
		}
		return false;
	},

	isDebug: function() {
		if(this.type == 'DEBUG') {
			return true;
		}
		return false;
	}

}


BSDEventUtils = {
	DEPENDENCIES: new Array("BSDLogUtils"),

	registerEvent: function(element, type, func) {
	    if(element.addEventListener) {
			element.addEventListener(type, func, true);			
	    } else if(element.attachEvent) {
			element.attachEvent('on' + type, func);
	    } else {
	    	BSDLogUtils.error("ERROR: Couldn't register event: " + type + " " + func);
	    	return false;
	    }
		return true;
	},
	
	stopPropagation: function(event) {	    
	    if(event.stopPropagation) {
	    	event.stopPropagation(); 
		} else {
	    	event.cancelBubble = true; 
	  	}

	  	if(event.preventDefault) {
	      	event.preventDefault(); 
	  	} else {
	      	event.returnValue = false; 
		}
	},
	
	removeEvent: function(element, type, func) {
		if(element.removeEventListener) {
			element.removeEventListener(type, func, true);
		} else if(element.detachEvent) { //was: && element['on' + type]) {
			element.detachEvent('on' + type, func);
		} else {
			BSDLogUtils.error("Couldn't removeEvent: " + element.detachEvent + " " + element[type]);
			return false;
		}	
		return true;
	},
	
	
	fixEventTarget: function(event) {
	    if(!event) {
			event = window.event;
	    }
	
	    if(event.target) {
			if(event.target.nodeType == 3) {
			    event.target = event.target.parentNode;
			}
		} else if(event.srcElement) {
			event.target = event.srcElement
	    }
	    return event.target;
	},

	getKeyPressed: function(event) {
	    var nbr;
	    if(window.event) {
			nbr = event.which;
	    } else { 
			nbr = event.keyCode;
	    }
	    var keyChar = String.fromCharCode(nbr);
		return keyChar;	
	},

	handleKeyPress: function(event, targetKeyCode) {
	    var nbr;
	    if(window.event) {
			nbr = event.which;
	    } else { 
			nbr = event.keyCode;
	    }

		
		for(var i = 1; i < arguments.length; i++) {
			var currentCode = arguments[i];

			if(nbr == currentCode) {
				return true;
			}
		}
		
		return false;
	},
	
	getIsLeftClick: function(event) {
		var nbr;
		if(event.which) {
			nbr = event.which;			
		} else {
			nbr = event.button;					
		}

		if(nbr == 1) {
			return true;
		}
		return false;
	},
	
	getIsRightClick: function(event) {
		var nbr;
		if(event.which) {
			nbr = event.which;			
		} else {
			nbr = event.button;					
		}
		if(nbr == 3) {
			return true;
		}
		return false;
	
	},
	
	registerDOMLoadEvent: function(newEvent) {
		if(!document.bsdDOMLoadInitialized) {
			BSDEventUtils.initializeDOMLoadEvents();
		}
		document.bsdDOMLoadEvents[document.bsdDOMLoadEvents.length] = newEvent;
	},
	
	initializeDOMLoadEvents: function() {
		document.bsdDOMLoadInitialized = true;
		if(!document.bsdDOMLoadEvents) {
			document.bsdDOMLoadEvents = new Array();
		}

		/*@cc_on @*/
		/*@if (@_win32)
		document.write("<script id=__ie_onload defer src=javascript:void(0)><\/script>");
		var script = document.getElementById("__ie_onload");
		script.onreadystatechange = function() {
			if (this.readyState == "complete") {
		    	BSDEventUtils.doDOMLoadEvents(); // call the onload handler
		  	}
		};
		/*@end @*/
		
		if(/WebKit/i.test(navigator.userAgent)) { // sniff
			var _timer = setInterval(function() {
				if(/loaded|complete/.test(document.readyState)) {
					clearInterval(_timer);
					BSDEventUtils.doDOMLoadEvents(); // call the onload handler
			    }
			}, 10);
		} else if(document.addEventListener) { // for Mozilla browsers
			document.addEventListener("DOMContentLoaded", BSDEventUtils.doDOMLoadEvents, false);
		}
	},
	
	doDOMLoadEvents: function() {
		if(!document.bsdDOMLoadEvents) {
			return;
		} 
		for(var i = 0; i < document.bsdDOMLoadEvents.length; i++) {
			document.bsdDOMLoadEvents[i].call();
		}
		
		document.bsdDOMLoadEvents = null;
	}

}


BSDColorUtils = {
	DEPENDENCIES: new Array(),
	
	rgbColorToHex: function(rgb) {  
		if(!rgb) {
			return;
		}
		var color = '#';  
  		if(rgb.slice(0,4) == 'rgb(') {  
    			var cols = rgb.slice(4, rgb.length-1).split(',');  
    			var i=0; do { color += this.toColorPart(parseInt(cols[i])) } while (++i<3);  
  		} else {  
    			if(rgb.slice(0,1) == '#') {  
	      			if(rgb.length==4) { 
	      				for(var i=1;i<4;i++) {
	      					color += (rgb.charAt(i) + rgb.charAt(i)).toLowerCase();  
	      				}
	      			}
	      			if(rgb.length==7) {
	      				color = rgb.toLowerCase();  
	      			}
    			}  
  		}  
  		if(color.length == 7) {
  			return color;
  		}
  		return rgb;
	},
	
	toColorPart: function(intValue) {
	    var digits = intValue.toString(16);
	    if (intValue < 16) return '0' + digits;
	    return digits;
  	},
  	
  	rgbRegex: /\s*rgba?\s*\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*,?\s*(\d+)?\s*\)\s*/,
  	
  	incrementRGBColor: function(rgbColor, incrementValue) {
  		if(!incrementValue) {
  			incrementValue = 50;
  		}

  		var rIncrementValue = incrementValue;
  		var gIncrementValue = incrementValue;
  		var bIncrementValue = incrementValue;
  		if(incrementValue.length && incrementValue.length > 2) {
  			rIncrementValue = incrementValue[0];
  			gIncrementValue = incrementValue[1];
  			bIncrementValue = incrementValue[2];
  		}
  		
  		var regexResult = rgbColor.match(BSDColorUtils.rgbRegex);
  		if(regexResult != null && regexResult.length > 0) {
  			var r = parseInt(regexResult[1]);
  			var g = parseInt(regexResult[2]);
  			var b = parseInt(regexResult[3]);
  			if(regexResult.length > 4) {
  				var a = parseInt(regexResult[4]);
  				if(a == 0 || (r > 245 && g > 245 && b > 245)) {
  					rIncrementValue = -1 * Math.abs(rIncrementValue);
  					gIncrementValue = -1 * Math.abs(gIncrementValue);
  					bIncrementValue = -1 * Math.abs(bIncrementValue);
  					r = 255;
  					g = 255;
  					b = 255;
  				}
  			}
  			r += rIncrementValue;
  			g += gIncrementValue;
  			b += bIncrementValue;

  			rgbColor = "rgb(" + r + "," + g + "," + b + ")";
  		} else if(rgbColor.toLowerCase() == "transparent") {
  			var r = 255 - Math.abs(rIncrementValue);
  			var g = 255 - Math.abs(gIncrementValue);
  			var b = 255 - Math.abs(bIncrementValue);
  			rgbColor = "rgb(" + r + ", " + g + ", " + b + ")";
  		} else {
  			BSDLogUtils.debug("No rgb match: [" + rgbColor + "]");
  		}
  		return rgbColor;
  	}

}	
BSDHighlightUtils = {
	DEPENDENCIES: new Array("BSDColorUtils", "BSDDOMUtils", "BSDLogUtils"),
	VERSION: 1.1,

	highlightElement: function(element, newColor, incrementValue) {
		if(element.oldBGColor) {
			return;
		}
		var currentBGColor = BSDDOMUtils.getElementStyle(element, 'background-color');

		if(!element.oldBGColor) {
			element.oldBGColor = BSDColorUtils.rgbColorToHex(currentBGColor);
		}
		if(!newColor) {
			newColor = BSDColorUtils.incrementRGBColor(currentBGColor, incrementValue);
			newColor = BSDColorUtils.rgbColorToHex(newColor);
		} 
		element.style.backgroundColor = newColor;

	},
	
	unHighlightElement: function(element) {
		var oldBGColor = element.oldBGColor;
		if(!oldBGColor) {
			oldBGColor = null;
		}	

		element.style.backgroundColor = oldBGColor;
		element.oldBGColor = null;
	},
	
	highlightText: function(element, newColor, incrementValue) {
		if(element.oldFGColor) {
			return;
		}
		var currentFGColor = BSDDOMUtils.getElementStyle(element, 'color');

		if(!element.oldFGColor) {
			element.oldFGColor = BSDColorUtils.rgbColorToHex(currentFGColor);
		}
		if(!newColor) {
			newColor = BSDColorUtils.incrementRGBColor(currentFGColor, incrementValue);
			newColor = BSDColorUtils.rgbColorToHex(newColor);
		} 
		element.style.color = newColor;

	},
	
	setMoveCursor: function(element) {
		if(element.oldCursor) {
			return;
		}
		var oldCursor = BSDDOMUtils.getElementStyle(element, 'cursor');
		if(!oldCursor) {
			oldCursor = "default";
		}
		element.style.cursor = "move";
		element.oldCursor = oldCursor;

	},
	
	unSetMoveCursor: function(element) {
		var oldCursor = element.oldCursor;
		element.style.cursor = oldCursor;
		element.oldCursor = null;

	},
	
	setBorderOnElement: function(element, width, newColor, incrementValue) {
		if(element.oldBorder) {
			return;
		}
		
		if(!width) {
			width = 1;
		}
		if(!newColor) {
			var currentBGColor = BSDDOMUtils.getElementStyle(element, 'background-color');
			if(!currentBGColor) {
				hexColor = "#555";
			} else {
				newColor = BSDColorUtils.incrementRGBColor(currentBGColor, incrementValue);
				newColor = BSDColorUtils.rgbColorToHex(newColor);
			}
		}
		var oldBorder = BSDDOMUtils.getElementStyle(element, "border");
		if(oldBorder) {
			element.oldBorder = oldBorder;
		}
		var newBorder = " " + width + "px solid " + newColor;

		BSDDOMUtils.changeElementStyle(element, "border", newBorder);
		BSDLogUtils.debug("Set element border: " + newBorder);

		
	},
	
	unSetBorderOnElement: function(element) {
		var oldBorder = element.oldBorder;
		if(!oldBorder) {
			oldBorder = "none";
		}
		BSDDOMUtils.changeElementStyle(element, "border", oldBorder);
		element.oldBorder = null;
	},
	
	highlightElementByOverlay: function(element) {
		if(element.bsdHighlightOverlay) {
			return;
		}
		var highlightElement = BSDDOMUtils.createElement("div", document.body);
		highlightElement.className = 'BSDHighlightedBox';
		var positionX = BSDLocationUtils.getObjectLocationX(element);
		var positionY = BSDLocationUtils.getObjectLocationY(element);
		var adjustX = 5;
		if(positionX < adjustX) {
			adjustX = positionX;
		}
		var adjustY = 5;
		if(positionY < adjustY) {
			adjustY = positionY;
		}
		var width = 5 + adjustX;
		var height = 5 + adjustY;
		BSDLocationUtils.makeElementAbsolutelyPositioned(highlightElement);
		BSDLocationUtils.cloneElementLocation(element, highlightElement, -adjustX, -adjustY, width, height);
		element.bsdHighlightOverlay = highlightElement;
	},
	
	unHighlightElementByOverlay: function(element) {
		if(!element.bsdHighlightOverlay) {
			return;
		}
		BSDDOMUtils.removeElement(element.bsdHighlightOverlay);
		element.bsdHighlightOverlay = null;
	}
	
	
	
}
BSDArrayUtils = {
	DEPENDENCIES: new Array("BSDTypeUtils"),
	
	insert: function(array, value, index) {
		if(array.splice && BSDTypeUtils.isArray(value)) {
			for(var i = 0; i < value.length; i++) {
				array.splice(index + i, 0, value[i]);
			}		
		} else if(array.splice) {
			array.splice(index, 0, value);
		} else if(BSDTypeUtils.isArray(value)) {
			for(var i = array.length - 1 + value.length; i > index; i--) {
				array[i] = array[i-1];			
			}
			for(var i = 0; i < value.length; i++) {
				array[index + i] = value[i];
			}		
		} else {
			for(var i = array.length; i > index; i--) {
				array[i] = array[i-1];			
			}
			array[index] = value;
		}
	},
	
	append: function(array, value) {
		if(array.push && !BSDTypeUtils.isArray(value)) {
			array.push(value);
		} else if(BSDTypeUtils.isArray(value)) {
			var j = 0;
			var newLength = array.length + value.length;
			for(var i = array.length; i < newLength; i++) {
				array[i] = value[j];
				j++
			}
		} else {	
			array[array.length] = value;
		}
	},
	
	deleteElement: function(array, index, count) {
		if(!count) {
			count = 1;
		}
		if(array.splice) {
			array.splice(index, count);
			return array;
		} else {
			var newArray = new Array();
			for(var i = 0; i < array.length; i++) {
				if(i < index && i >= index + count) {
					BSDArrayUtils.append(newArray, array[i]);
				}
			}
			return newArray;
		}
	}, 
	
	replace: function(array, index, value) {
		array[index] = value;
	},
	
	copy: function(sourceArray, targetArray) {
		var j = targetArray.length;
		for(var i = 0; i < sourceArray.length; i++) {
			targetArray[j + i] = sourceArray[i];
		}
	},
	
	toCommaDelimitedString: function(sourceArray) {
		var value = "";
		for(var i = 0; i < sourceArray.length; i++) {
			value += sourceArray[i];
			if(i < sourceArray.length - 1) {
				value += ",";
			}
		}	
		return value;
	},
	
	insertUnique: function(array, value, index) {
		for(var i = 0; i < array.length; i++) {
			if(array[i] == value) {
				BSDArrayUtils.deleteElement(array, i);
				break;
			}
		}
		BSDArrayUtils.insert(array, value, index);
	},
	
	contains: function(array, value) {
		for(var i = 0; i < array.length; i++) {
			if(array[i] == value) {
				return true;
			}
		}
		return false;
	}
}

var bsdValidatedFormList = {};
var bsdValidatedFormIndex = 0;
BSDValidatedForm = BSDClass.create();
BSDValidatedForm.DEPENDENCIES = new Array("BSDClass", "BSDDOMUtils", "BSDVisibilityUtils", "BSDEventUtils", "BSDLogUtils", "BSDHighlightUtils", "BSDArrayUtils");
BSDValidatedForm.VERSION = 1.2;

BSDValidatedForm.prototype = {

	className: "BSDValidatedForm",
	initialize: function(formName, submitButtonId, validationFields, validationOptions) {

		this.formName = formName;
		this.form = document.forms[formName];
		
		this.options = validationOptions;
		if(!this.options) {
			this.options = this.getDefaultOptions();
		}
		if(!this.options.messageHash) {
			this.options.messageHash = new BSDFormMessageHash();
		}
		
		if(validationFields && validationFields.length > 0) {
			this.fields = validationFields;
		} else {
			this.fields = new Array();
		}

		if(!this.form) {
			BSDLogUtils.error("ERROR: Couldn't find form for validation: " + formName);
			for(var i = 0; i < document.forms.length; i++) {
				BSDLogUtils.debug("Form: " + document.forms[i].name);
			}
			return;
		}

		var initSuccess = this.initializeForm();
		if(!initSuccess) {
			this.form = this.retryInitializeForm();
		}
		if(!this.form) {
			return;
		}
		this.initializePageErrorMessage();
		this.initializeFields();
		
		bsdValidatedFormList[this.formName] = this;
		this.bsdIndex = bsdValidatedFormIndex++;
		BSDLogUtils.debug("Initialized validation form " + formName + " " + this.bsdIndex + " " + this.form.bsdIndex + " " + (bsdValidatedFormList[this.formName] == this) );
		this.form.bsdIndex = this.bsdIndex;
  	},
  	

	doFormSubmit: function(e) {

		var form = this.form;
		if(this.shouldSkipValidation()) {
			return true;
		}
		if(typeof tinyMCE != 'undefined') {
			tinyMCE.triggerSave();
		}
		
		var result = this.doValidation();

		if(result.isValid) {

			form.hasError = false;
			return true;
		}
		
		if(this.pageErrorMessageTextElement && result.pageMessage) {
			var pageMessage = this.options.messageHash.getMessage(result.pageMessage);
			this.pageErrorMessageTextElement.innerHTML = pageMessage;
			BSDVisibilityUtils.showObject(this.pageErrorMessageContainer);
			for(var i = 0; i < this.pageErrorMessageContainer.parentNode.childNodes.length; i++) {
				var currentChild = this.pageErrorMessageContainer.parentNode.childNodes[i];
				if(currentChild != this.pageErrorMessageElemen
							&& currentChild.id 
							&& currentChild.id.indexOf(this.pageErrorMessageContainer.id) > 0) {
					this.pageErrorMessageContainer.parentNode.removeChild(currentChild);
				}
			}
		}

		if(e) {
			BSDEventUtils.stopPropagation(e);
		}
		form.hasError = true;
		BSDNavigationUtils.navigateTo("#" + form.name);
		return false;
		
	},
	
	shouldSkipValidation: function() {
		var form = this.form;
		if(form.skipValidation || BSDDOMUtils.getAttributeValue(form, 'skip-validation') == 'true') {
			return true;
		}
		try {
		if(typeof skipPageFormValidation == 'function') {
			return skipPageFormValidation();
		} else {
			return false;
		}
		} catch (err) {
			alert(err);
			return false;
		}
		
	
	},
  	

	doValidation: function() {

		var listFieldsInPageMessage = this.options.listFieldsInPageMessage;
		var fieldPageMessageEnabled = this.options.fieldPageMessageEnabled;

		var pageMessage = this.options.defaultPageMessage;
		var pageMessagePrefix = this.options.pageMessagePrefix;
		if(!pageMessagePrefix) {
			pageMessagePrefix = "";
		}
		var pageMessageSuffix = this.options.pageMessageSuffix;
		if(!pageMessageSuffix) {
			pageMessageSuffix = "";
		}

		var isValid = true;
		for(var i = 0; i < this.fields.length; i++) {
			var currentField = this.fields[i];

			var result = currentField.validate();
			if(result && !result.isValid) {
				isValid = false;


				if(listFieldsInPageMessage && currentField.getLabel()) {
					pageMessage += pageMessagePrefix + currentField.getLabel + pageMessageSuffix;
				} else if((fieldPageMessageEnabled || currentField.forcePageMessage) && result.pageMessage) {
					var resultMessage = this.options.messageHash.getMessage(result.pageMessage);
					pageMessage += pageMessagePrefix + resultMessage + pageMessageSuffix;				
				} 
			}

		}

		
		var result = new BSDValidatedFormResult(isValid, null, pageMessage);				

		return result;
	},
	
	getDefaultOptions: function() {
		var options = new Object();
		options.defaultPageMessage = "There are some problems with your submission.  Please fix them and try again:";
		options.pageMessagePrefix = "<br/>";
		options.validateFieldsOnChange = true;
		options.fieldHighlightStyle = "fieldError";
		options.labelHighlightStyle = "fieldLabelError";
		
		return options;
	},
  	
  	addValidationField: function(validationField) {

  		this.initializeField(validationField);
  		BSDArrayUtils.append(this.fields, validationField);


  	},
  	
  	addField: function(fieldElementId, validator, messageElementId, labelElementId) {
  		var validationField = new BSDValidatedFormField(this.options, fieldElementId, validator, messageElementId, labelElementId);
  		this.addValidationField(validationField);
  	},
  	
  	removeField: function(fieldElementId) {
  		for(var i = 0; i < this.fields.length; i++) {
  			if(this.fields[i].fieldElement && this.fields[i].fieldElement.id == fieldElementId) {
  				BSDArrayUtils.deleteElement(this.fields, i);
  			}
  		}

  	},
  	
  	initializePageErrorMessage: function() {
  		var errorMessageContainerId = "ERROR_MESSAGE_ROW";
  		if(this.options.errorMessageContainerId) {
  			errorMessageContainerId = this.options.errorMessageContainerId;
  		}
  		var containerElement = BSDDOMUtils.getObjectByIdFromParent(this.form, errorMessageContainerId);
  		if(!containerElement) {
  			containerElement = BSDDOMUtils.getObjectById(errorMessageContainerId);
  		}
  		if(!containerElement) {
  			BSDLogUtils.error("ERROR: Couldn't find error message container for form validator [" + errorMessageContainerId + "]");  		
  			return;  		
  		}
  		this.pageErrorMessageContainer = containerElement;

  		var errorMessageTextId = "ERROR_MESSAGE_TEXT";
  		if(this.options.errorMessageTextId) {
  			errorMessageTextId = this.options.errorMessageTextElementId;
  		}
  		var textElement = BSDDOMUtils.getObjectById(errorMessageTextId);
  		if(!textElement) {
  			BSDLogUtils.error("ERROR: Couldn't find error message text element for form validator");  		
  			return;  		
  		}
  		this.pageErrorMessageTextElement = textElement;

  	},
  	
  	initializeForm: function() {
  		var formValidator = this;
  		if(this.form.isValidationHandlerInitialized) {
  			return true;
  		}
		function formOnSubmitHandler(e) {

			return formValidator.doFormSubmit(e);			
		}   


		var success = BSDEventUtils.registerEvent(this.form, "submit", formOnSubmitHandler);
		if(success) {
			this.form.isValidationHandlerInitialized = true;
		}
		return success;
  	},
  	
  	retryInitializeForm: function() {

		this.form = BSDDOMUtils.getObjectById(this.formName);
		if(!this.form || !this.initializeForm()) {
			BSDLogUtils.error("Couldn't initialize form " + this.formName + " by id");
			return;
		}

		if(this.form.bsdIndex && this.form.bsdIndex <= bsdValidatedFormIndex) {

			var formList = BSDDOMUtils.getObjectsById(this.formName, document);

			for(var i = 0; i < formList.length; i++) {
				if(!formList[i].bsdIndex) {
					this.form = formList[i];
					BSDLogUtils.debug("Got form from list: " + this.form.name);
					break;
				}
			}
		} 
		return this.form; 	
  	},
  	
  	initializeFields: function() {  	
  		for(var i = 0; i < this.fields.length; i++) {
  			var currentField = this.fields[i];
  			this.initializeField(currentField);
  		}
  	},
  	
  	initializeField: function(field) {
		field.initializeElements(this.form, this.options);  		
  	}, 
  	
  	replaceValidator: function(fieldId, newValidator) {
  		for(var i = 0; i < this.fields.length; i++) {
  			var currentField = this.fields[i];

  			if(currentField.fieldElementId == fieldId) {  				
  				for(var j = 0; j < currentField.validators.length; j++) {
  					var currentValidator = currentField.validators[j];
  					if(currentValidator.className != newValidator.className) {
  						continue;
  					}
  					if(newValidator.fieldMessage) {
  						newValidator.fieldMessage = currentValidator.fieldMessage;
  					}
  					if(newValidator.pageMessage) {
  						newValidator.pageMessage = currentValidator.pageMessage;
  					}
  					BSDArrayUtils.replace(currentField.validators, j, newValidator);
  					return currentField;
  				}
  			}
  		}
		return;  	
  	} 	
}

BSDValidatedFormUtils = {
	reinitializeForms: function() {

		for(var formName in bsdValidatedFormList) {
			var currentForm = bsdValidatedFormList[formName];

			currentForm.initializeFields();
		}
	},
	
	replaceValidator: function(fieldId, newValidator) {

		for(var formName in bsdValidatedFormList) {
			var currentForm = bsdValidatedFormList[formName];

			var validatedField = currentForm.replaceValidator(fieldId, newValidator);
			if(validatedField) {
				return validatedField;
			}
		}

	}
}

BSDValidatedFormField = BSDClass.create();
BSDValidatedFormField.prototype = {

	initialize: function(validationOptions, fieldElementId, messageElementId, labelElementId, validator) {

		this.options = validationOptions;
		this.fieldElementId = fieldElementId;
		this.messageElementId = messageElementId;
		this.labelElementId = labelElementId;

		this.validators = new Array();
		if(validator) {
			this.addValidator(validator);
		}
	},
	
	initializeElements: function(parentFormElement, options) {
		if(parentFormElement) {
			this.parentFormElement = parentFormElement;
		}

  		if(!this.options) {
  			this.options = options;
  		}  	
  		if(this.fieldElementId) {
  			var element = BSDDOMUtils.getObjectByIdFromParent(this.parentFormElement, this.fieldElementId);
  			if(!element) {
  				BSDLogUtils.error("ERROR: Couldn't find field element with id " + this.fieldElementId);
  				this.fieldElement = null;
  			} else {
  				element.bsdIndex = this.bsdIndex;
  				this.fieldElement = element;

  			}
  		}
  		if(this.labelElementId) {
  			var element = BSDDOMUtils.getObjectByIdFromParent(this.parentFormElement, this.labelElementId);
  			if(!element) {
  				BSDLogUtils.error("ERROR: Couldn't find field label with id " + this.labelElementId);
  			} else {
  				this.labelElement = element;
  			}  		
  		}
  		if(this.messageElementId) {
  			var element = BSDDOMUtils.getObjectByIdFromParent(this.parentFormElement, this.messageElementId);
  			if(!element) {
  				BSDLogUtils.error("ERROR: Couldn't find field message with id " + this.messageElementId);
  			} else {
  				this.messageElement = element;
  			}    			
  		}
  		
  		if(this.options && this.options.validateFieldsOnChange && this.fieldElement) {
			this.initializeOnChange(this);  			
  		}
  		
  		this.bsdIndex = this.bsdIndex;
	
	},
	
  	initializeOnChange: function(field) {
  		
		function fieldOnChangeHandler(e) {
			BSDLogUtils.debug("Got field onchange event");
			var validationResult = field.validate();
		}   
		
		function fieldOnKeydownHandler(e) {
			field.clearError();			
		}	
		
		BSDEventUtils.registerEvent(field.fieldElement, "change", fieldOnChangeHandler);		
		BSDEventUtils.registerEvent(field.fieldElement, "keydown", fieldOnKeydownHandler);		
  	},	
	
	addValidator: function(newValidator) {	
		BSDArrayUtils.append(this.validators, newValidator);
	},
	
	validate: function() {
		var result;
		for(var i = 0; i < this.validators.length; i++) {
			result = this.validateByValidator(this.validators[i]);
			if(!result.isValid) {
				return result;
			}
		}
		return result;
	},
	
	validateByValidator: function(validator) {
		BSDLogUtils.debug("validateByValidator: BEGIN " + this.fieldElementId + " " + this.fieldElement);
		if(!this.fieldElement && this.fieldElementId) {
			this.initializeElements();
		}
		if(!this.fieldElement || this.fieldElement.skipValidation) {
			var result = new Object();
			result.isValid = true;
			return result;
		}
		var value = BSDFormUtils.getFieldValue(this.fieldElement);

		var result = validator.validate(value);

		if(result.newValue && result.newValue.length > 0) {

			this.fieldElement.value = result.newValue;
		}
		/* This doesn't work because the response doesn't come back until the current thread is finished.   Need to rework messaging to happen asyncronously
		var beginTime = new Date();
		var currentTime = new Date();
		
  		BSDLogUtils.debug("Checking is pending: " + result.isPending + " " + (currentTime.getTime() - beginTime.getTime()));
  		while(result.isPending && currentTime.getTime() - beginTime.getTime() < 2000) { //2 second timeout
  			BSDLogUtils.debug("Is pending, looping: " + (currentTime.getTime() - beginTime.getTime()));
			var x = "y" + "z" + "w";
			var y = x + "A";		
			currentTime = new Date();
					
  		}
  		*/


		if(this.fieldElement && !result.isValid && this.options.fieldHighlightStyle) {
			BSDDOMUtils.addClass(this.fieldElement, this.options.fieldHighlightStyle);
		}

		if(this.messageElement && !result.isValid && result.fieldMessage) {
			var resultMessage = this.options.messageHash.getMessage(result.fieldMessage);
		  	this.messageElement.innerHTML = resultMessage;

			for(var i = 0; i < this.messageElement.childNodes.length; i++) {
				var currentChild = this.messageElement.childNodes[i];
				if(currentChild.nodeType == 1 && !BSDVisibilityUtils.isObjectHidden(currentChild)) {
					BSDVisibilityUtils.hideObject(currentChild);
					currentChild.hiddenByValidator = true;
				}				
			}
		}
		
		if(this.labelElement && !result.isValid && this.options.labelHighlightStyle) {
			BSDDOMUtils.addClass(this.labelElement, this.options.labelHighlightStyle);
		}
		
		if(this.isError && result.isValid) {			
			this.clearError();		
		}
		this.isError = !result.isValid;


		return result;		
	},

	
	clearError: function() {

		if(this.fieldElement && this.options.fieldHighlightStyle) {
			BSDDOMUtils.removeClass(this.fieldElement, this.options.fieldHighlightStyle);
		}
		
		if(this.messageElement) {
			this.messageElement.innerHTML = "";
			for(var i = 0; i < this.messageElement.childNodes.length; i++) {
				var currentChild = this.messageElement.childNodes[i];
				if(currentChild.nodeType == 1 && currentChild.hiddenByValidator) {
					BSDVisibilityUtils.showObject(currentChild);
					currentChild.hiddenByValidator = false;
				}				
			}
		}
		
		if(this.labelElement && this.options.labelHighlightStyle) {
			BSDDOMUtils.removeClass(this.labelElement, this.options.labelHighlightStyle);
		}
	}
	
	
}


BSDValidatedFormResult = BSDClass.create();
BSDValidatedFormResult.prototype = {

	initialize: function(isValid, fieldMessage, pageMessage) {
		this.isValid = isValid;
		this.isPending = false;
		this.fieldMessage = fieldMessage;
		this.pageMessage = pageMessage;
	},
	
	
	handleValidationResponse: function(data) {
		var successful = BSDAjaxUtils.doNavigationReply(data, true);

		if(!successful) {
			BSDLogUtils.error("Ajax validation request failed: " + data);
	    } else if(data.errorMessage) {
	    	this.isValid = false;
		} else {
			this.isValid = true;
		}	
		this.isPending = false;
	}	
	
}


BSDRegexFormFieldValidator = BSDClass.create();
BSDRegexFormFieldValidator.prototype = {
	
	initialize: function(isRequired, fieldMessage, pageMessage, regex) {
		this.regex = new RegExp(regex);
		this.fieldMessage = fieldMessage;
		this.isRequired = isRequired;
		this.pageMessage = pageMessage;
	},
	
	validate: function(value) {
		var result;

		if(this.isRequired && (!value || value.length < 1)) {
			result = new BSDValidatedFormResult(false, this.fieldMessage, this.pageMessage);				
		} else if(value && value.length > 0 && this.regex && this.regex.exec && this.regex.exec(value) == null) {
			result = new BSDValidatedFormResult(false, this.fieldMessage, this.pageMessage);							
		} else {
			result = new BSDValidatedFormResult(true);									
		}
		return result;
	}

}


BSDRequiredFormFieldValidator = BSDClass.create();
BSDRequiredFormFieldValidator.prototype = {
	
	initialize: function(isRequired, fieldMessage, pageMessage) {
		this.isRequired = isRequired;
		this.fieldMessage = fieldMessage;
		this.pageMessage = pageMessage;
	},
	
	validate: function(value) {
		var result;

		
		if(!value && this.isRequired) {
			result = new BSDValidatedFormResult(false, this.fieldMessage, this.pageMessage);		
		} else if(this.minLength && value && value.length < this.minLength) {
			result = new BSDValidatedFormResult(false, this.minLengthErrorMessage, this.pageMessage);										
		} else {
			result = new BSDValidatedFormResult(true);									
		}
		return result;
	}

}


BSDCardCodeFormFieldValidator = BSDClass.create();
BSDCardCodeFormFieldValidator.prototype = {
	
	initialize: function(isRequired, fieldMessage, pageMessage) {
		this.isRequired = isRequired;
		this.fieldMessage = fieldMessage;
		this.pageMessage = pageMessage;
		this.regex = new RegExp(/[\d]{3,4}/);
	},
	
	validate: function(value) {
		var result;
		if(!value && this.isRequired) {
			result = new BSDValidatedFormResult(false, this.fieldMessage, this.pageMessage);		
		} else if(this.minLength && value && value.length < this.minLength) {
			result = new BSDValidatedFormResult(false, this.minLengthErrorMessage, this.pageMessage);										
		} else if(value && value.indexOf('*') > -1) {
			result = new BSDValidatedFormResult(true);									
		} else if(value) {
			var typeId = BSDCardNumberFormFieldValidator.getCardTypeId();
			if(!typeId) {
				result = new BSDValidatedFormResult(false);
			} else if(typeId == 15 && value.length != 4) {
				result = new BSDValidatedFormResult(false, this.fieldMessage, this.pageMessage);		
			} else if(value.length != 3) {
				result = new BSDValidatedFormResult(false, this.fieldMessage, this.pageMessage);		
			} else if(this.regex && this.regex.exec && this.regex.exec(value) == null) {
				result = new BSDValidatedFormResult(false, this.fieldMessage, this.pageMessage);		
			} else {
				result = new BSDValidatedFormResult(true);												
			}
		}
		return result;
	}

}



BSDCardNumberFormFieldValidator = BSDClass.create();
BSDCardNumberFormFieldValidator.prototype = {
	
	initialize: function(isRequired, fieldMessage, pageMessage) {
		this.isRequired = isRequired;
		this.fieldMessage = fieldMessage;
		this.pageMessage = pageMessage;
		
	},
	
	validate: function(value) {
		var result;
		if(!value && this.isRequired) {
			result = new BSDValidatedFormResult(false, this.fieldMessage, this.pageMessage);		
		} else if(this.minLength && value && value.length < this.minLength) {
			result = new BSDValidatedFormResult(false, this.minLengthErrorMessage, this.pageMessage);										
		} else if(value && value.indexOf('*') > -1) {
			result = new BSDValidatedFormResult(true);									
		} else if(value) {
			value = value.replace(/[\D]+/g, "");
			var typeId = BSDCardNumberFormFieldValidator.getCardTypeId();
			if(!typeId) {
				result = new BSDValidatedFormResult(false);
			} else if(!validateCardNumber(value, typeId)) { //this function is inserted into the page html by java
				result = new BSDValidatedFormResult(false, this.fieldMessage, this.pageMessage);		
			} else {
				result = new BSDValidatedFormResult(true);												
			}
		}
		return result;
	}

}

BSDCardNumberFormFieldValidator.getCardTypeId = function() {
	var typeIdElement = BSDDOMUtils.getObjectById("PAYMENT_METHOD_TYPE_ID");
	if(typeIdElement && typeIdElement.value && typeIdElement.value.length > 0) {
		return new typeIdElement.value;
	}
	
	var buttons = BSDDOMUtils.getObjectsByClass('PAYMENT_METHOD_TYPE_RADIO_BUTTON');
	for(var i = 0; i < buttons.length; i++) {
		var currentButton = buttons[i];
		if(currentButton.checked && currentButton.value && currentButton.value.length > 0) {
			return currentButton.value;
		} 
	}

	BSDLogUtils.error("Couldn't find PAYMENT_METHOD_TYPE_ID field value for form validation");
	return null;
		
}

BSDCardNumberFormFieldValidator.validateCardNumberLength = function(cardNumber) {
	for(var i = 1; i < arguments.length; i++) {
		if(cardNumber.length == arguments[i]) {
			return true;
		}
	}
	return false;
}

BSDCardNumberFormFieldValidator.validateCardNumberPrefix = function(cardNumber) {
	for(var i = 1; i < arguments.length; i++) {
		var value = arguments[i] + '';
		if(cardNumber.indexOf(value) == 0) {
			return true;
		}
	}

	return false;
}

BSDCardNumberFormFieldValidator.validateMod10 = function(cardNumber) {
	var total = 0;
	var j = 1;	
	for(var i = cardNumber.length - 1; i >= 0; i--) {
		var digit = cardNumber.charAt(i);
		if(j % 2 == 0) {
			var multDigit = parseInt(digit) * 2;
			if(multDigit > 9) {
				var strMultDigit = multDigit + '';
				var digit1 = parseInt(strMultDigit.charAt(0));
				var digit2 = parseInt(strMultDigit.charAt(1));
				total += digit1 + digit2;
			} else {
				total += multDigit;
			}
		} else {
			total += parseInt(digit);
		}
		j++;
	}
	return total % 10 == 0;
}

BSDExerciseValidator = BSDClass.create();
BSDExerciseValidator.prototype = {
	
	initialize: function(isRequired, fieldMessage, pageMessage) {
		this.isRequired = isRequired;
		this.fieldMessage = fieldMessage;
		this.pageMessage = pageMessage;
		
	},
	
	validate: function(value) {
		var result = new BSDValidatedFormResult(true, this.fieldMessage, this.pageMessage);
		if(!value || value.length < 1) {
			return result;
		} 
		
		var parts = value.split(/\|/);
		if(parts.length < 4) {
			return result;
		}
		
		var algorithm = parts[1];
		var expressionResult = '';
		if(algorithm == 'eval') {
			expressionResult = eval(parts[3]);
		}
		value = parts[0] + "|" + parts[1] + "|" + parts[2] + "|" + parts[3] + "|" + expressionResult;
		result.newValue = value;
		return result;
	}

}
		


BSDSupportedFileTypeValidator = BSDClass.create();
BSDSupportedFileTypeValidator.prototype = {
	
	className: "BSDSupportedFileTypeValidator",
	initialize: function(fieldMessage, pageMessage, validImageFileExtensions, validVideoFileExtensions, validAudioFileExtensions, validDocumentFileExtensions, validFlashFileExtensions) {
		this.fieldMessage = fieldMessage;
		this.pageMessage = pageMessage;
		this.validFileExtensions = new Array();
		BSDArrayUtils.append(this.validFileExtensions, validImageFileExtensions);
		BSDArrayUtils.append(this.validFileExtensions, validVideoFileExtensions);

		BSDArrayUtils.append(this.validFileExtensions, validDocumentFileExtensions);
		BSDArrayUtils.append(this.validFileExtensions, validFlashFileExtensions);
		
		if(!this.fieldMessage) {
			this.fieldMessage = "This type of file isn't supported";
		}
		if(!this.pageMessage) {
			this.pageMessage = "One of your files has an unsupported format.  Valid file types include: <ul>";
			if(validImageFileExtensions && validImageFileExtensions.length > 0) {
				this.pageMessage += "<li>Images:  " + this.getFileExtensionMessage(validImageFileExtensions) + "</li>";
			}
			if(validVideoFileExtensions && validVideoFileExtensions.length > 0) {
				this.pageMessage += "<li>Video:  " + this.getFileExtensionMessage(validVideoFileExtensions) + "</li>";
			}
			if(validAudioFileExtensions && validAudioFileExtensions.length > 0) {
				this.pageMessage += "<li>Audio:  " + this.getFileExtensionMessage(validAudioFileExtensions) + "</li>";
			}
			if(validDocumentFileExtensions && validDocumentFileExtensions.length > 0) {
				this.pageMessage += "<li>Documents:  " + this.getFileExtensionMessage(validDocumentFileExtensions) + "</li>";
			}
			if(validFlashFileExtensions && validFlashFileExtensions.length > 0) {
				this.pageMessage += "<li>Flash:  " + this.getFileExtensionMessage(validFlashFileExtensions) + "</li>";
			}
			this.pageMessage += "</ul>";
		}
	},
	
	validate: function(value) {
		var result;
		if(!value || value.length < 1) {
			return new BSDValidatedFormResult(true);		
		} 
		
		var fileParts = value.split(".");
		var extension = fileParts[fileParts.length - 1];
		BSDLogUtils.debug("Got file type result: " + extension + " [" + this.fieldMessage + "][" + this.pageMessage + "] " + this.validFileExtensions);
		if(!extension || extension.length < 1) {
			result = new BSDValidatedFormResult(false, 'This file is missing its file extension (e.g. .jpg)', this.pageMessage);		
		} else if(!BSDArrayUtils.contains(this.validFileExtensions, extension.toLowerCase())) {
			result = new BSDValidatedFormResult(false, this.fieldMessage, this.pageMessage);				
		} else {
			return new BSDValidatedFormResult(true);		
		}
		return result;
	},
	
	getFileExtensionMessage: function(extensions) {
		var message = "";
		for(var i = 0; i < extensions.length; i++) {
			message += extensions[i];
			if(i < extensions.length - 1) {
				message += ", ";
			}
		}
		return message;
	}
}

BSDFormMessageHash = BSDClass.create();
BSDFormMessageHash.prototype = {
	
	initialize: function(hash) {
		this.hash = hash;
	},
	
	getMessage: function(messageId) {
		if(!messageId) {
			return messageId;
		}
		var newMessage = this.hash[messageId];
		if(newMessage) {
			return newMessage;
		}
		return messageId;
	}

}

