/**
 * Simple test function to make sure we've loaded this.
 */
function myAlert(text)
{
	alert(text);
}

/**
 * Placeholder function.
 */
function noOp()
{
}

/**
 * Functions to get an element by ID on older browsers.
 */
function IE4GetElementById(id)
{
   return document.all[id];
}
function NN4GetLayerById(id)
{
  // see xbStyle on the evangelism site
  // for details on a possible implementation
  return null;
}

/**
 * Functions to get around the Microshaft/Unix wars.
 */
// Screen coordinates of left edge of screen (usually 0)
function GetScreenX(e)
{
	// W3C browser, we get only the top left corner of the window area
	if (typeof(this.screenX)!="undefined")
		return this.screenX;
	// Put it in the upper left corner of the screen
	return 0;
}
// Screen coordinates of top edge of screen (usually 0)
function GetScreenY(e)
{
	// W3C browser, we get only the top left corner of the window area
	if (typeof(this.screenY)!="undefined")
		return this.screenY;
	// Put it in the upper left corner of the screen
	return 0;
}
// Screen coordinates of left edge of browser client area
function GetClientX(e)
{
	// IE, we get only the top left corner of the client area
	if (typeof(this.screenLeft)!="undefined")
		return this.screenLeft;
	// Firefox, we get only the top left corner of the window
	if (e &&
		typeof(e.screenX)!="undefined" &&
		typeof(e.clientX)!="undefined"   ) {
		return e.screenX - e.clientX;
	}
	// Other W3C browser, this is the top left corner of the window
	if (typeof(this.screenX)!="undefined")
		return this.screenX;
	return 0;
}
// Screen coordinates of top edge of browser client area
function GetClientY(e)
{
	// IE, we get only the top left corner of the client area
	if (typeof(this.screenTop)!="undefined")
		return this.screenTop;
	// Firefox, we get only the top left corner of the window
	if (e &&
		typeof(e.screenY)!="undefined" &&
		typeof(e.clientY)!="undefined"   ) {
		return e.screenY - e.clientY;
	}
	// Other WS3COM, this is the top left corner of the window
	if (typeof(this.screenY)!="undefined")
		return this.screenY;
	return 0;
}
// Width of client area
function GetClientW()
{
	// Cross-browser compatible
	if (typeof(this.document.body.clientWidth)!="undefined")
		return this.document.body.clientWidth;
	return 100;
}
// Height of client area
function GetClientH()
{
	// Cross-browser compatible
	if (typeof(this.document.body.clientHeight)!="undefined")
		return this.document.body.clientHeight;
	// IE, this is client area minus scrollbars
	return 100;
}
// Screen coordinates of mouse event
function GetEventX(e)
{
	// Firefox, we get this directly
	if (typeof(e.screenX)!="undefined")
		return e.screenX;
	// IE, we get this relative to client
	if (typeof(e.clientX)!="undefined")
		return this.clientX(e) + e.clientX;
	return 0;
}
function GetEventY(e)
{
	// Firefox, we get this directly
	if (typeof(e.screenY)!="undefined")
		return e.screenY;
	// IE, we get this relative to client
	if (typeof(e.clientY)!="undefined")
		return this.clientY(e) + e.clientY;
	return 0;
}
// Attribute string to set left edge
function StrClientX(absX)
{
	// Both IE and FF interpret this as upper left corner of window
	if (typeof(this.screenX)!="undefined")
		return " screenX="+absX;
	if (typeof(this.screenLeft)!="undefined")
		return " left="+absX;
	return "";
}
function StrClientY(absY)
{
	// Both IE and FF interpret this as upper left corner of window
	if (typeof(this.screenY)!="undefined")
		return " screenY="+absY;
	if (typeof(this.screenTop)!="undefined")
		return " top="+absY;
	return "";
}
function StrClientW(absW)
{
	// Both IE and FF interpret this as size of client area
	return " width="+absW;
}
function StrClientH(absH)
{
	// Both IE and FF interpret this as size of client area
	return " height="+absH;
}


/**
 * Modify the browser model to provide modern DOM capability on older browsers.
 */
if (document.layers)
   document.getElementById = NN4GetLayerById;
else if (document.all && !document.getElementById)
	document.getElementById = IE4GetElementById;
	
/**
 * Move past the Microshaft/Unix wars.
 */
window.getScreenX = GetScreenX;
window.getScreenY = GetScreenY;
window.getClientX = GetClientX;
window.getClientY = GetClientY;
window.getClientW = GetClientW;
window.getClientH = GetClientH;
window.getEventX  = GetEventX;
window.getEventY  = GetEventY;
window.strClientX = StrClientX;
window.strClientY = StrClientY;
window.strClientW = StrClientW;
window.strClientH = StrClientH;

/**
 * This is what happens when objects are badly defined.
 */
function StopPropagation(e)
{
	if (e.stopPropagation)
		e.stopPropagation();
	else if (typeof(e.cancelBubble)!="undefined")
		e.cancelBubble = true;
}

/**
 * Unbelievable oversight.
 */
function formatFloat(value, precision)
{
	var txt = '';
	if (precision > 0) {
		var ipt, fpt;
		if (value >= 0.0) {
			ipt = Math.floor(value);
			fpt = 1.0 + value - ipt;
		} else {
			ipt = Math.ceil(value);
			fpt = 1.0 + ipt - value;
		}
		txt = txt + ipt;
		txt = txt + '.';
		while (precision-- > 0)
			fpt = fpt * 10;
		fpt = Math.round(fpt);
		txt = txt + String(fpt).substr(1);
	} else {
		txt = txt + Math.round(value);
	}
	return txt;
}

/**
 * Get an object in a browser-safe way.
 */
function getObject(id)
{
	var elm = null;
	if (document.getElementById)
		elm = document.getElementById(id);
	return elm;
}

/**
 * This is a useful function to get a style object for any object.
 */
function getStyleObject(id)
{
	var elm = getObject(id);
	var styleObject = null;
	if (elm)
	{
		if (elm.style)
			styleObject = elm.style;
		else if (document.layers)
			styleObject = elm;
	}
	return styleObject;
}

/**
 * Make object visible or invisible.
 */
function hideElement(id)
{
	var styleObject = getStyleObject(id);
	if (styleObject)
		styleObject.visibility = 'hidden';
}
function showElement(id)
{
	var styleObject = getStyleObject(id);
	if (styleObject)
		styleObject.visibility = 'visible';
}
function toggleVisibility(id)
{
	var styleObject = getStyleObject(id);
	if (styleObject)
		if (styleObject.visibility == 'hidden')
			styleObject.visibility = 'visible';
		else
			styleObject.visibility = 'hidden';
}

/**
 * Set the color of an object.
 */
function setColor(id, color)
{
	var styleObject = getStyleObject(id);
	if (styleObject)
		styleObject.color = color;
}

/**
 * Set the font-weight of an object.
 */
function setWeight(id, weight)
{
	var styleObject = getStyleObject(id);
	if (styleObject)
		styleObject.fontWeight = weight;
}

/**
 * Set the text content of an object.
 */
function setText(id, text)
{
	var object = getObject(id);
	if (object && object.childNodes[0])
		object.childNodes[0].nodeValue = text;
}

/**
 * Set the name of a control.
 */
function setControlName(id, name)
{
	var object = getObject(id);
	if (object) {
		var form = object.form;
		if (form && form.submit && ! form.doSubmit && name == 'submit')
			form.doSubmit = form.submit;
		object.name = name;	
	}
}

/**
 * Get the value of a forms control. I'm at a loss as to why HTML developers
 * did this the way they did, but they did. Use name rather than id for the
 * group controls, like radio buttons.
 */
function getControlValue(name)
{
	var value = -1;
	var forms = document.forms;
	if (forms && forms.length > 0)
	{
		var els = forms[0].elements;
		if (els && els.length > 0)
		{
			for (ii = 0; ii < els.length; ii++)
			{
				if (els[ii].name != name)
					continue;
				switch (els[ii].type) {
				case 'checkbox':
					value = (els[ii].checked) ? 1 : 0;
					break;
				case 'radio':
					if (els[ii].checked)
						value = els[ii].value;
					break;
				case 'select-one':
					value = els[ii].selectedIndex;
					break;
				default:
					value = els[ii].value;
					break;
				}
			}
		}
	}
	return value;
}

/**
 * Set the value of a forms control. Use name rather than id for the grouped
 * controls, like radio buttons.
 */
function setControlValue(name, value)
{
	var forms = document.forms;
	if (forms && forms.length > 0)
	{
		var els = forms[0].elements;
		if (els && els.length > 0)
		{
			for (ii = 0; ii < els.length; ii++)
			{
				if (els[ii].name != name)
					continue;
				switch (els[ii].type) {
				case 'checkbox':
					els[ii].checked = (value != 0) ? 1 : 0;
					break;
				case 'radio':
					els[ii].checked = (els[ii].value == value);
					break;
				case 'select-one':
					els[ii].selectedIndex = value;
					break;
				default:
					els[ii].value = value;
					break;
				}
			}
		}
	}
}

/**
 * Enable or disable a control.
 */
function enableControl(name, enable)
{
	var forms = document.forms;
	if (forms && forms.length > 0)
	{
		var els = forms[0].elements;
		if (els && els.length > 0)
		{
			for (ii = 0; ii < els.length; ii++)
			{
				if (els[ii].name != name)
					continue;
				els[ii].disabled = ! enable;
				if (els[ii].type == 'checkbox')
				{
					var aux = getObject(name + 'chk');
					if (aux && aux.type == 'hidden')
					{
						if (enable)
							aux.value = '-1';
						else
							aux.value = (els[ii].checked) ? '1' : '0';
					}
					setColor(name + 'Prompt', (enable) ? 0x000000 : 0xA0A0A0);
				}
			}
		}
	}
}

/**
 * Disable all submit controls on the page.
 */
function disableSubmit()
{
	var forms = document.forms;
	if (forms && forms.length > 0)
	{
		for (jj = 0; jj < forms.length; jj++)
		{
			var els = forms[jj].elements;
			if (els && els.length > 0)
			{
				for (ii = 0; ii < els.length; ii++)
				{
					if (els[ii].type == 'submit')
						els[ii].disabled = true;
				}
			}
		}
	}
}

/**
 * Call this to submit a form using onclick='...'.
 */
var submitted = false;	// protection against multiple submits
function doSubmit()
{
	// If there are no forms in document, do nothing
	var form = document.forms[0];
	if (! form)
		return false;

	// Don't allow this to happen twice
	if (submitted)
		return false;
	submitted = true;	// disable second use
	disableSubmit();	// disable all other submit buttons
	
	// Give preference to our override, if present
	if (form.doSubmit) {
		form.doSubmit();
		return true;
	}
	if (form.submit) {
		form.submit();
		return true;
	}
	return false;
}

/**
 * Do an onclick='...' submission from a file upload button.
 */
function doUploadImg(id, img)
{
	// Replace the image with the wait image, and then submit on load
	var obj = getObject(id);
	obj.onload = doSubmit;
	obj.src = img;
	// Return value does not matter
	return false;
}

/**
 * Do an onclick='...' submission from a file upload button.
 */
function doUploadText(id, msg)
{
	// Replace the text, then submit
	setText(id, msg);
	doSubmit();
	// Return value does not matter
	return false;
}

function doBack()
{
	window.history.back();
	return false;
}

function clickButton(id)
{
	var btn = getObject(id);
	if (btn && btn.click) btn.click();
	return false;
}

function doSubmitOnce(btn, name, hdn, chain)
{
	// Must capture 'submit' function in form context BEFORE renaming button as 'submit'
	var form = getObject(btn).form;
	form.doSubmit = form.submit;
	// Chain to any other operations first
	if (chain) chain();
	getObject(btn).disabled = true;
	getObject(hdn).name = name;
	// Must make explicit call: IE7 ignores return value because Enter button disabled
	form.doSubmit();
	// Return value does not matter
	return false;
}

function doSubmitBar(bar, btn, hdn, text)
{
	// Must capture 'submit' function in form context BEFORE renaming button as 'submit'
	var form = getObject(btn).form;
	form.doSubmit = form.submit;
	// Modify the form
	getObject(btn).disabled = true;		// disable the submit btn
	getObject(hdn).name = 'continue';	// rename the hidden btn
	setText(bar, text);					// set the message text
	// Must make explicit call: IE7 ignores return value because Enter button disabled
	form.doSubmit();
	// Return value does not matter
	return false;
}

/**
 * Open a popup window with absolute size and position.
 * Pass the event as 'event' from a legacy callback.
 */
var globalWin = null;
function openPopupAbs(e, absX, absY, absW, absH, attr, URL)
{
	// Process input values, enforce basic rules
	if (attr == null)
		attr =	"status=no, toolbar=no, menubar=no, location=no,"+
				" scrollbars=yes, resizable=yes";
	if (absW < 20)
		absW = 20;
	if (absH < 20)
		absH = 20;
	if (absW > screen.availWidth)
		absW = screen.availWidth;
	if (absH > screen.availHeight)
		absH = screen.availHeight;
	if (absX < 0)
		absX = 0;
	if (absY < 0)
		absY = 0;
	if (absX > screen.availWidth - absW)
		absX = screen.availWidth - absW;
	if (absY > screen.availHeight - absH)
		absY = screen.availHeight - absH;
	// Open new, or use old
	if (globalWin == null || globalWin.closed) {
		// Create the popup window
		if (attr.length > 0 && attr.charAt(attr.length-1) != ',')
			attr = attr + ",";
		attr = attr +
			window.strClientW(absW)+","+
			window.strClientH(absH)+","+
			window.strClientX(absX)+","+
			window.strClientY(absY);
		globalWin = window.open(URL, "", attr);
		globalWin.resizeTo(absW, absH);
		globalWin.moveTo(absX, absY);
	} else {
		// Change the contents
		globalWin.location = URL;
		globalWin.resizeTo(absW, absH);
		globalWin.moveTo(absX, absY);
		globalWin.focus();
	}
	return globalWin;
}

/**
 * Open a popup window relative to cursor, with absolute window size.
 * Pass the event as 'event' from a legacy callback.
 */
function openPopupCur(e, relX, relY, absW, absH, attr, URL)
{
	// Capture the current window location, and decide where to put the popup
	absX = window.getEventX(e) + relX;
	absY = window.getEventY(e) + relY;
	return openPopupAbs(e, absX, absY, absW, absH, attr, URL);	
}

/**
 * Open a popup window relative to client area, with absolute window size.
 * Pass the event as 'event' from a legacy callback.
 */
function openPopup(e, relX, relY, absW, absH, attr, URL)
{
	// Capture the current window location, and decide where to put the popup
	absX = window.getScreenX(e) + relX;
	absY = window.getScreenY(e) + relY;
	return openPopupAbs(e, absX, absY, absW, absH, attr, URL);	
}

/**
 * Open a popup window in the left part of the client area.
 */
function openPopupLeft(e, absW, URL)
{
	// Capture the current window location, and decide where to put the popup
	if (absW < 250) absW = 250;
	absH = window.getClientH();
	relX = 0;
	relY = 0;
	return openPopup(e, relX, relY, absW, absH, null, URL);
}

/**
 * Open a popup window in the right part of the client area.
 */
function openPopupRight(e, absW, URL)
{
	// Capture the current window location, and decide where to put the popup
	if (absW < 250) absW = 250;
	absH = window.getClientH();
	relX = window.getClientW() - absW;
	relY = 0;
	return openPopup(e, relX, relY, absW, absH, null, URL);
}

/**
 * Open a popup window on the left side of the screen.
 */
function openPopupLeftScreen(e, absW, URL)
{
	// Capture the current window location, and decide where to put the popup
	if (absW < 250) absW = 250;
	absH = screen.availHeight;
	absX = 0;
	absY = 0;
	return openPopup(e, absX, absY, absW, absH, null, URL);
}

/**
 * Open a popup window on the right side of the screen.
 */
function openPopupRightScreen(e, absW, URL)
{
	// Capture the current window location, and decide where to put the popup
	if (absW < 250) absW = 250;
	absH = screen.availHeight;
	absX = screen.availWidth - absW;
	absY = 0;
	return openPopup(e, absX, absY, absW, absH, null, URL);
}

/**
 * Somewhat-useful function for displaying the properties of some objects
 * in JavaScript.
 */
function shredNode(node, s, d)
{
	var p = "";
	while (p.length < 2*(d+1))
		p += " ";
	s += "\r\n";
	for (prop in node) {
		s += p+prop+"("+typeof(node[prop])+")=";
		switch (typeof(node[prop])) {
			case "object":
				if (prop == "parent") {
					s += "loop\r\n";
				} else
				if (node[prop] == null) {
					s += "null\r\n";
				} else
				if (node[prop] == node) {
					s += "this\r\n";
				} else
				if (typeof(node.propertyIsEnumerable)!="undefined" &&
					node.propertyIsEnumerable(prop)) {
					s = shredNode(node[prop], s, d+1);
				} else {
					s += "non-enumerable\r\n";
				}
				break;
			case "string":
				s += "'"+node[prop]+"'\r\n";
				break;
			case "number":
			case "boolean":
				s += node[prop]+"\r\n";
				break;
			case "function":
				break;
				if (node[prop] == null) {
					s += "null\r\n";
				} else {
					s += node[prop].toString()+"\r\n";
				}
				break;
			default:
				s += "\r\n";
				break;
		}
	}
	return s;
}
function shred(object)
{
	var s = "<pre>";
	s = shredNode(object, s, 0);
	openPopup(null, 0, 0, 500, 300, null, "");
	globalWin.document.open();
	globalWin.document.write(s);
	globalWin.document.close();
	alert('done');
}
