/* 
	Cross-browser compatible method for retrieving page elements by ID 
*/
function getObject(sObjId) {
	if (document.layers)
		return document.layers[sObjId];
	else if (document.all)
		return document.all[sObjId];
	else if (document.getElementById)
		return document.getElementById(sObjId);
}

/* 
	Returns the name of the tag that represents the given element 
*/
function getTag(oElem) {
	if (oElem.localName) {
		var sName = oElem.localName;
	} else if (oElem.nodeName) {
		var sName = oElem.nodeName;
	} else {
		return null;
	}
	return sName.toLowerCase();
}

// Gets the specified attribute in a cross-browser way
function attribute(oElem, sAttr) {

	if (sAttr == 'for') {
		sAttr = 'htmlFor';
	}
	
	if (oElem[sAttr]) {
		return oElem[sAttr];
	} else if (oElem.getAttribute(sAttr)) {
		return oElem.getAttribute(sAttr);
	} else {
		return null;
	}
}

/*
	Cross-browser compatible add and remove event methods.
*/
function addEvent(elm, evType, fn, useCapture) {
	try {
		if (elm.addEventListener) {
			elm.addEventListener(evType, fn, useCapture);
			return true;
		} else if (elm.attachEvent) {
			return elm.attachEvent('on' + evType, fn);
		} else {
			// Handler could not be added via traditional methods
			var fEvFunct = eval('elm.on' + evType);
			if (typeof fEvFunct != 'function') {
				eval('elm.on' + evType + ' = fn;');
			} else {
				eval('elm.on' + evType + ' = function() { fEvFunct(); fn(); };');
			}
		}
	} catch (e) {
		// May want some sort of notification process in here.
	}
}

function removeEvent(elm, evType, fn, useCapture) {
	if (elm.removeEventListener) {
		elm.removeEventListener(evType, fn, useCapture);
		return true;
	} else if (elm.detachEvent) {
		return elm.detachEvent('on' + evType, fn);
	} else {
		// Handler could not be removed.
	}
}

/*
	Gets the target of the event
*/
function getTarget(e) {

	var oTarg = null;

	if (e.target) {
		oTarg = e.target;
	} else if (e.srcElement) {
		oTarg = e.srcElement;
	}
	
	// For Safari
	if (oTarg.nodeType == 3) {
		oTarg = oTarg.parentNode;
	}
	
	return oTarg;
}

/* 
	Removes all whitespace from both ends of a string.
*/
String.prototype.trim = function() {
	return this.replace( /^\s+|\s+$/, "" );
}

String.prototype.urlDecode = function() {
    var sStr = this.replace(new RegExp('\\+','g'),' ');
    return unescape(sStr);
}

String.prototype.urlEncode = function() {
    var sStr = escape(this);
    sStr = sStr.replace(new RegExp('\\+','g'),'%2B');
    return sStr.replace(new RegExp('%20','g'),'+');
}

/* 
	Decodes a string that was encoded using base-64 encoding. 
*/
String.prototype.base64_decode = function(bIsBinary) {
	var result = "";
	var i = 0;
	var x;
	var shiftreg = 0;
	var count = -1;
	
	for (i = 0; i < this.length; i++) {
		c = this.charAt(i);
		if ('A' <= c && c <= 'Z')
			x = this.charCodeAt(i) - 65;
		else if ('a' <= c && c <= 'z')
			x = this.charCodeAt(i) - 97 + 26;
		else if ('0' <= c && c <= '9')
			x = this.charCodeAt(i) - 48 + 52;
		else if (c == '+')
			x = 62;
		else if (c == '/')
			x = 63;
		else
			continue;

		count++;

		switch (count % 4) {
			case 0:
				shiftreg = x;
				continue;
			case 1:
				v = (shiftreg<<2) | (x >> 4);
				shiftreg = x & 0x0F;
				break;
			case 2:
				v = (shiftreg<<4) | (x >> 2);
				shiftreg = x & 0x03;
				break;
			case 3:
				v = (shiftreg<<6) | (x >> 0);
				shiftreg = x & 0x00;
				break;
		}

		if (!bIsBinary && (v < 32 || v > 126) && (v != 0x0d) && (v != 0x0a)) {
			result = result + "<";
			result = result + "0123456789ABCDEF".charAt((v/16)&0x0F);
			result = result + "0123456789ABCDEF".charAt((v/1)&0x0F);
			result = result + ">";
		} else {
			result = result + String.fromCharCode(v);
		}
	}
	return result.toString();
}

/*
	Generates a unique ID value. Always good to have one of these around.
*/
function getUniqueId() {
	var oDate = new Date();
	return Math.floor(Math.random() * (oDate.getSeconds().toString() + oDate.getMilliseconds().toString()));
}

/*
	Used in striping and sorting functions to retrieve the number of rows
	that comprise a row group, as specified in the class declaration of the
	parent table element.
*/
function getRowGroupLen(sClassName, oElem) {
	var oRegexp = new RegExp(sClassName + '-?(\\d)*');
	var aResults = oRegexp.exec(oElem.className);
	if (aResults[1]) {
		return aResults[1];
	} else {
		return 1;
	}
}

var __aToggledItems = new Object;

/*
	Toggles the visibility of the element whose ID is given.
*/
function toggleVis(sId, bAsInline) {
	var oStyle = getStyleObject(sId);
	if (isVisible(sId)) {
		__aToggledItems[sId] = oStyle.display;
		oStyle.display = 'none';
	} else {
		if (__aToggledItems[sId] != null) {
			oStyle.display = __aToggledItems[sId];
		} else {
			if (bAsInline) {
				oStyle.display = 'inline';
			} else {
				oStyle.display = 'block';
			}
		}
	}
	return false;
}

function isVisible(sId) {
	var oStyle = getStyleObject(sId);
	return (oStyle.display == '' || oStyle.display == 'block' || oStyle.display == 'inline');
}

/*
	Cross-browser compatible method of retrieving an element's 'style'
	attribute.
*/
function getStyleObject(sId) {
	var oElem = getObject(sId);
	if (oElem) {
		if (document.getElementById || document.all) {
			return oElem.style;
		} else if (document.layers) {
			return oElem;
		}
	}
	return false;
}

/* 
	Dynamically removes a CSS class name from an element.
*/
function removeCSSClass(oElem, sClassName) {
	if (typeof oElem == "string") {
		var oElem = getObject(oElem);
	}
	oElem.className = oElem.className.replace(sClassName, "" ).trim();
}

/* 
	Dynamically adds a CSS class name to an element. 
*/
function addCSSClass(oElem, sClassName) {
	if (typeof oElem == "string") {
		var oElem = getObject(oElem);
	}
	oElem.className = (oElem.className + ' ' + sClassName).trim();
}

/*
	Tells if the element in question is empty.
*/
function isEmpty(oElem) {
	if (typeof oElem == "string") {
		var oElem = getObject(oElem);
	}

	var bRet = false;
	
	// For now, skip elements that are not found, such as those that are
	// in address entry fields. Will need to fix this later...
	if (oElem != null) {
		switch (oElem.type) {
			case 'select-one':
			case 'select-multiple':
				if (oElem.options.selectedIndex <= 0) {
					bRet = !(oElem.options.selectedIndex == 0 && oElem.options[0].value != '')
				} else {
					bRet = false;
				}
				break;
			case 'radio':
			case 'checkbox':
				bRet = oElem.checked;
				break;
			case 'password':
			case 'text':
			case 'textarea':
			case 'hidden':
				bRet = (oElem.value.trim() == '');
				break;
			default:
				break;
		}
	}
	
	return bRet;
}

/*
	Retrieves the selected value(s) from any type of form field.
*/
function getValue(oElem) {
	if (typeof oElem == "string") {
		var oElem = getObject(oElem);
	}
	
	var oRet = null;
	switch (oElem.type) {
		case 'select-one':
			if (oElem.options.selectedIndex > -1) {
				oRet = oElem.options[oElem.options.selectedIndex].value;
			}
			break;
		case 'select-multiple':
			// Return something... a list of values
			oRet = new Array();
			for (var i = 0; i < oElem.options.length; i++) {
				if (oElem.options[i].selected) {
					oRet.push(oElem.options[i].value);
				}
			}
			break;
		case 'radio':
		case 'checkbox':
			if (oElem.checked) {
				oRet = oElem.value;
			}
			break;
		case 'password':
		case 'text':
		case 'textarea':
		case 'hidden':
			oRet = oElem.value.trim();
			break;
		default:
			break;
	}
	return oRet;
}

/* Clears any entered values or selected items within a form element */

function clearValue(oElem) {
	if (typeof oElem == 'string') {
		var oElem = getObject(oElem);
	}
	switch (oElem.type) {
		case 'select-one':
		case 'select-multiple':
			oElem.options.selectedIndex = -1;
			break;
		case 'radio':
		case 'checkbox':
			oElem.checked = false;
			break;
		case 'password':
		case 'text':
		case 'textarea':
		case 'hidden':
			oElem.value = '';
			break;
		default:
			break;
	}
}


function openWindow(where, width, height, directories, location, menubar, resizeable, screenX, screenY, scroll, status, toolbar) {
	
	var aArguments = new Array();
	var iCount = 0;
	
	if (width != null) {
		aArguments[iCount++] = 'width=' + width;
	}
	
	if (height != null) {
		aArguments[iCount++] = 'height=' + height;
	}
	
	if (directories != null) {
		aArguments[iCount++] = 'directories=' + (directories == '1' ? 'yes':'no');
	}
	
	if (location != null) {
		aArguments[iCount++] = 'location=' + (location == '1' ? 'yes':'no');
	}
	
	if (menubar != null) {
		aArguments[iCount++] = 'menubar=' + (menubar == '1' ? 'yes':'no');
	}
	
	if (resizeable != null) {
		aArguments[iCount++] = 'resizeable=' + (resizeable == '1' ? 'yes':'no');
	}
	
	if (screenX != null) {
		aArguments[iCount++] = 'screenX=' + screenX + ',left=' + screenX;
	}
	
	if (screenY != null) {
		aArguments[iCount++] = 'screenY=' + screenY + ',top=' + screenY;
	}
	
	if (scroll != null) {
		aArguments[iCount++] = 'scroll=' + (scroll == '2' ? 'auto': (scroll == '1' ? 'yes':'no'));
	}
	
	if (status != null) {
		aArguments[iCount++] = 'status=' + (status == '1' ? 'yes':'no');
	}
	
	if (toolbar != null) {
		aArguments[iCount++] = 'toolbar=' + (toolbar == '1' ? 'yes':'no');
	}

	var sArguments = aArguments.join(',');

	var oWin = window.open(
		where, 
		'ChildWin', 
		sArguments	
	);
	return oWin;
}

windowFitHeight = function() {
	var bIsNetscape = (navigator.appName == "Netscape");
		
	var iHeight = (bIsNetscape) ? window.innerHeight : document.documentElement.clientHeight;
		
	if (document.body.offsetHeight) {
		iHeight = document.body.offsetHeight - iHeight;
	}
				
	window.resizeBy(0, iHeight);
	self.focus();
}

function windowFit() {
	var bIsNetscape = (navigator.appName == "Netscape");
	
	var iWindowWidth = (bIsNetscape) ? window.innerWidth : document.documentElement.clientWidth;
	var iWindowHeight = (bIsNetscape) ? window.innerHeight : document.documentElement.clientHeight;
	
	var oWrap = document.getElementById('fit-wrap');
	
	var iWrapWidth = oWrap.style.width.replace(/px/, '');
	var iWrapHeight = oWrap.style.height.replace(/px/, '');
	
	var iWidth = iWrapWidth - iWindowWidth;
	var iHeight = iWrapHeight - iWindowHeight;
	
	if (document.body.offsetHeight) {
		iHeight = document.body.offsetHeight - iWindowHeight;
	}
			
	window.resizeBy(iWidth, iHeight);
	self.focus();
 };
