/* common functions used by many modules go here */
function bindMethod (fn, object)
{
	if (!fn) throw "bindMethod: fn is not a valid function";
	var boundFn = fn;
	var boundObject = object;
	var outerargs = arguments;
	return function () {
		var newargs = Array (outerargs.length - 2 + arguments.length);
		for (var i = 0; i < outerargs.length - 2; i ++)
			newargs[i] = outerargs[i + 2];
		for (var i = 0; i < arguments.length; i ++)
			newargs[i + outerargs.length - 2] = arguments[i];

		return boundFn.apply (object, newargs);
	}
}
function bindFunction (fn)
{
	if (!fn) throw "bindFunction: fn is not a valid function";
	var boundFn = fn;
	var outerargs = arguments;
	return function () {
		var newargs = Array (outerargs.length - 1 + arguments.length);
		for (var i = 0; i < outerargs.length - 1; i ++)
			newargs[i] = outerargs[i + 1];
		for (var i = 0; i < arguments.length; i ++)
			newargs[i + outerargs.length - 1] = arguments[i];

		return boundFn.apply (null, newargs);
	}
}

function quote_for_xml (str)
{
	if (str == undefined || str == null) return "";
	return str.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace (/>/g, '&gt;').replace (/\"/g, "&quot;").replace (/\n/g, "&#10;").replace (/\r/g, "&#13;");
}

function make_adjacent_layer (component, alignment, dx, dy, cx, cy, overrideparent)
{
	spacer = document.getElementById ("toolbox_spacer");
	if (spacer)
		var miny = spacer.offsetHeight;
	else
		miny = 0;
	layer = document.createElement ("div");
	layer.style.position = "absolute";
	switch (alignment.charAt(0))
	{
		case 'T': y = component.offsetTop - dy - cy; break;
		case 't': y = component.offsetTop + dy; break;
		case 'm': y = component.offsetTop + component.offsetHeight/2 - cy/2; break;
		case 'b': y = component.offsetTop + component.offsetHeight - (cy + dy); break;
		case 'B': y = component.offsetTop + component.offsetHeight + dy; break;
		default: throw "Alignment must be of the format [T|t|m|b|B][L|l|m|r|R]";
	}
	switch (alignment.charAt(1))
	{
		case 'L': x = component.offsetLeft - dx - cx; break;
		case 'l': 
			x = component.offsetLeft + dx; 
			if (component.offsetWidth < cx + 20) x -= cx + 20 - component.offsetWidth;
			break;
		case 'm': x = component.offsetLeft + component.offsetWidth/2 - cx/2; break;
		case 'r': 
			x = component.offsetLeft + component.offsetWidth - (cx + dx); 
			if (component.offsetWidth < cx + 20) x += cx + 20 - component.offsetWidth;
			break;
		case 'R': x = component.offsetLeft + component.offsetWidth + dx; break;
		default: throw "Alignment must be of the format [T|t|m|b|B][L|l|m|r|R]";
	}

	offsetParent = component.offsetParent;
	while (offsetParent && offsetParent.tagName != "body")
	{
		x += offsetParent.offsetLeft;
		y += offsetParent.offsetTop;
		offsetParent = offsetParent.offsetParent;
	}

	var parent = overrideparent ? overrideparent : component;
	try
	{
		t = parent.offsetParent;
		while (t && t.tagName != "body")
		{
			if (t.style.position == "absolute" || t.style.position == "relative") {
				x -= t.offsetLeft;
				y -= t.offsetTop;
				break;
			}
			t = t.offsetParent;
		}
	}
	catch (e) { }
	if (x < 0) x = 0;
	if (y < miny) y = miny;
	layer.style.width = cx;
	layer.style.height = cy;
	layer.style.left = x;
	layer.style.top = y;
	layer.style.zIndex = 1;

	if (overrideparent)
		overrideparent.appendChild(layer);
	else
		component.appendChild (layer);
	return layer;
}

function getNodeText (node)
{
	return node ? (node.textContent != undefined ? node.textContent : node.innerText) : undefined;
}

var debugWindow = null;

function debugmsg (msg)
{
	if (debugWindow == null)
	{
		debugWindow = document.createElement ("div");
		debugWindow.style.width = "640px";
		debugWindow.style.height = "480px";
		debugWindow.style.position = "fixed";
		debugWindow.style.top = "1em";
		debugWindow.style.left = "1em";
		debugWindow.style.overflow = "scroll";
		debugWindow.style.background = "white";
		debugWindow.style.border = "1px solid black";
		debugWindow.style.padding = "4px";
		debugWindow.style.zIndex = "1000";
		debugWindow.innerHTML = "<A href='#' onclick='debugWindow.parentNode.removeChild(debugWindow);debugWindow=null;return false'>Close</A>";
		document.body.appendChild (debugWindow);
	}
	t = document.createElement ("pre");
	t.style.fontFamily = "Verdana";
	t.style.fontSize = "8pt";
	t.style.borderBottom = "1px solid black";
	t.appendChild (document.createTextNode (msg));
	debugWindow.appendChild (t);
}

function getElementPosition (el)
{
	pos = {
		x: el.offsetLeft,
		y: el.offsetTop,
		cx: el.offsetWidth != undefined ? el.offsetWidth : el.clientWidth,
		cy: el.offsetHeight != undefined ? el.offsetHeight : el.clientHeight
	}
	op = el.offsetParent;
	while (op && op.offsetParent)
	{
		pos.x += op.offsetLeft;
		pos.y += op.offsetTop;
		op = op.offsetParent;
	}
	return pos;
}

function getWindowGeometry ()
{
  var obj = new Object ();
  if( typeof( window.innerWidth ) == 'number' ) {
    //Non-IE
    obj.cx = window.innerWidth;
    obj.cy  = window.innerHeight;
  } else if( document.documentElement && ( document.documentElement.clientWidth || document.documentElement.clientHeight ) ) {
    //IE 6+ in 'standards compliant mode'
    obj.cx = document.documentElement.clientWidth;
    obj.cy = document.documentElement.clientHeight;
  } else if( document.body && ( document.body.clientWidth || document.body.clientHeight ) ) {
    //IE 4 compatible
    obj.cx = document.body.clientWidth;
    obj.cy = document.body.clientHeight;
  }
  if( typeof( window.pageYOffset ) == 'number' ) {
    //Netscape compliant
    obj.scrollY = window.pageYOffset;
    obj.scrollX = window.pageXOffset;
  } else if( document.body && ( typeof (document.body.scrollLeft) == 'number' || document.body.scrollTop ) ) {
    //DOM compliant
    obj.scrollY = document.body.scrollTop;
    obj.scrollX = document.body.scrollLeft;
  } else if( document.documentElement && ( typeof (document.documentElement.scrollLeft) == 'number' || document.documentElement.scrollTop ) ) {
    //IE6 standards compliant mode
    obj.scrollY = document.documentElement.scrollTop;
    obj.scrollX = document.documentElement.scrollLeft;
  } 
  return obj;
}

function scrollToElement (el)
{
	// if (el.scrollIntoView) { el.scrollIntoView(); return; }

	pos = getElementPosition(el);
	geo = getWindowGeometry ();

	if (geo.scrollX + geo.cx < pos.x + pos.cx + 16) geo.scrollX = pos.x + pos.cx - geo.cx + 16;
	if (geo.scrollX > pos.x - 16) geo.scrollX = pos.x - 16;
	if (geo.scrollY + geo.cy < pos.y + pos.cy + 16) geo.scrollY = pos.y + pos.cy - geo.cy + 16;
	if (geo.scrollY > pos.y - 90) geo.scrollY = pos.y - 90;
	
	window.scroll (geo.scrollX, geo.scrollY);
}

function newNode (tag, properties, styleproperties)
{
	var node = document.createElement (tag);
	if (properties)
	{
		for (propname in properties)
		{
			node[propname] = properties[propname];
			node.setAttribute (propname, properties[propname]);
		}
	}
	if (styleproperties)
	{
		for (propname in styleproperties)
			node.style[propname] = styleproperties[propname];
	}
	return node;
}
function addNode (container, tag, properties, styleproperties)
{
	var node = newNode (tag, properties, styleproperties);
	container.appendChild (node);
	return node;
}

function selectControlSelect (control, value)
{
	for (var i = 0; i < control.options.length; i++)
		control.options[i].selected = (control.options[i].value == value);
}

function getCookie ( cookie_name )
{
  var results = document.cookie.match ( cookie_name + '=(.*?)(;|$)' );

  if ( results )
    return ( unescape ( results[1] ) );
  else
    return null;
}

function newdiv (htmlstr)
{
	var div = document.createElement ("div");
	div.innerHTML = htmlstr;
	return div;
}

function new_xhr ()
{
	if (window.XMLHttpRequest) 
	{
		// We have an XMLHttpRequest class: use it.
		return new XMLHttpRequest();
	} 
	else if (window.ActiveXObject) 
	{
		// We have ActiveX: use it
		return new ActiveXObject("Microsoft.XMLHTTP");
	}
	return false;
}

function formEncode (val)
{
	return encodeURI(val).replace (/&/g, '%26').replace (/\#/g, '%23');
}

// if there's a toolbar, make it float, and resize the spacer so that it fits underneath it:
function floatToolbox ()
{
	var siteToolbox = document.getElementById ("toolbox");
	if (siteToolbox)
	{
		var spacer = document.getElementById ("toolbox_spacer");
		if (!spacer)
		{
			spacer = document.createElement ("div");
			siteToolbox.parentNode.insertBefore (spacer, siteToolbox);
		}
		spacer.innerHTML = "<img src='static/core/x.gif' width='1' height='" + (siteToolbox.offsetHeight) + "' alt=''>";
		siteToolbox.className = "floatingToolbox";
	}
}

function resizeToolboxSpacer ()
{
	var siteToolbox = document.getElementById ("toolbox");
	var spacer = document.getElementById ("toolbox_spacer");
	if (siteToolbox && spacer)
		spacer.innerHTML = "<img src='static/core/x.gif' width='1' height='" + (siteToolbox.offsetHeight) + "' alt=''>";
}

if (window.attachEvent) {
	window.attachEvent ("onload", floatToolbox);
	window.attachEvent ("onresize", resizeToolboxSpacer);
}
else {
	window.addEventListener ("load", floatToolbox, false);
	window.addEventListener ("resize", resizeToolboxSpacer, false);
}

function globalEvalAndCallback( data, callback ) {
	if (window.execScript) {
		window.execScript (data);
		callback ();
	}
	else if (navigator.appName.indexOf('AppleWebKit'))
	{
		// safari doesn't provide a synchronous global eval
		window.setTimeout (data, 0);
		window.setTimeout (callback, 1);
	}
	else {
		window.eval (data);
		callback ();
	}
}

function loadAndExecute (scriptUrl, callback)
{
	var xhr = new_xhr();
	var urlExtra = "";
	var testBase = "http://vengeance/";
	if (location.href.substring (0, testBase.length) == testBase)
		urlExtra = "?bypassCache=" + (new Date().getTime());
	xhr.open("GET", scriptUrl + urlExtra, true);
	xhr.onreadystatechange = function () {
		if (xhr.readyState == 4)
		{
			//alert ("loaded " + scriptUrl+urlExtra + ":\n" + xhr.responseText);
			globalEvalAndCallback (xhr.responseText, callback);
		}
	};
	xhr.send("");
}

function requireScript (module, callback)
{
	var found = false;
	try
	{
		if (mdLoadedModules[module])
			found = true;
	}
	catch (e)
	{
		mdLoadedModules = {};
	}

	//debugmsg ("requireScript: " + module + " " + (found ? "already" : "not") + " loaded");
	if (!found)
	{
		loadAndExecute ("static/" + module + ".js", callback);
	}
	else
	{
		callback ();
	}
}

function showNavigator (baseurl, staticbase)
{
	var loaded = false;
	try
	{
		if (mdLoadedModules['scriptlib/core/navigator'] &&
			mdLoadedModules['scriptlib/core/pageselector'])
		{
			loaded = true;
		}
	}
	catch (e)
	{
	}
	if (loaded)
	{
		new NavigatorDialog(baseurl, staticbase).show();
		return;
	}
	nle = bindMethod (navigatorLoadEvent, null, baseurl, staticbase);
	requireScript ("scriptlib/core/navigator", nle);
	requireScript ("scriptlib/core/pageselector", nle);
}

function navigatorLoadEvent (baseurl, staticbase)
{
	var loaded = false;
	try
	{
		if (mdLoadedModules['scriptlib/core/navigator'] &&
			mdLoadedModules['scriptlib/core/pageselector'])
		{
			loaded = true;
		}
	}
	catch (e)
	{
	}
	if (loaded)
	{
		new NavigatorDialog(baseurl, staticbase).show();
		return;
	}
}

function str2title (string)
{
	var s = "" + string;
	if (s.length == 0) return s;
	return s.charAt(0).toUpperCase() + s.substring (1);
}

imageCache = { };

function getImage (url)
{
	if (imageCache[url]) return imageCache[url];
	imageCache[url] = document.createElement("img");
	imageCache[url].src = url;
	imageCache[url].alt = "";
	return imageCache[url];
}

	function menu_open_id (id_dropdown, id_label, alignment, dx, dy)
	{
		var label = document.getElementById (id_label)
		var component = getElementPosition (label);
		var dropdown = document.getElementById (id_dropdown);
		if (dropdown.style.display == "block") return;
		dropdown.style.position = "absolute";
		dropdown.style.display = "block";
		var cx = dropdown.offsetWidth;
		var cy = dropdown.offsetHeight;
		var x, y;
		switch (alignment.charAt(0))
		{
			case 'T': y = component.y - dy - cy; break;
			case 't': y = component.y + dy; break;
			case 'm': y = component.y + component.cy/2 - cy/2; break;
			case 'b': y = component.y + component.cy - (cy + dy); break;
			case 'B': y = component.y + component.cy + dy; break;
			default: throw "Alignment must be of the format [T|t|m|b|B][L|l|m|r|R]";
		}
		switch (alignment.charAt(1))
		{
			case 'L': x = component.x - dx - cx; break;
			case 'l': 
				x = component.x + dx; 
				break;
			case 'm': x = component.x + component.cx/2 - cx/2; break;
			case 'r': 
				x = component.x + component.cx - (cx + dx); 
				break;
			case 'R': x = component.x + component.cx + dx; break;
			default: throw "Alignment must be of the format [T|t|m|b|B][L|l|m|r|R]";
		}
		
		dropdown.style.position = "absolute";
		dropdown.style.left = x + "px";
		dropdown.style.top = y + "px";

		var saved_label_mouseout = label.onmouseout;
		var saved_label_mouseover = label.onmouseover;

		var timerid = null;
		var menu_close_listener = function () { 
			label.onmouseout = saved_label_mouseout; 
			label.onmouseover = saved_label_mouseover; 
			dropdown.onmouseout = null;
			dropdown.onmouseover = null;
			menu_close_id (id_dropdown, menu_close_listener); 
			if (timerid != null) window.clearTimeout (timerid);
		}
		window.setTimeout (function () {
				if (document.body.attachEvent)
					document.body.attachEvent("onclick", menu_close_listener);
				else
					document.body.addEventListener ("click", menu_close_listener, false);
			}, 100);

		var menu_timeout_listener = function ()
		{
			timerid = null;
			menu_close_listener ();
		}

		var mouse_out_listener = function () {
			timerid = window.setTimeout (menu_timeout_listener, 500);
		}
		var mouse_in_listener = function () {
			if (timerid != null)
			{
				window.clearTimeout (timerid);
			}
		}
		dropdown.onmouseout = mouse_out_listener;
		label.onmouseout = mouse_out_listener;
		dropdown.onmouseover = mouse_in_listener;
		label.onmouseover = mouse_in_listener;

	}

	function menu_close_id (id_dropdown, listener)
	{
		var dropdown = document.getElementById (id_dropdown);
		dropdown.style.display = "none";
		if (document.body.attachEvent)
			document.body.detachEvent ("onclick", listener);
		else
			document.body.removeEventListener ("click", listener, false);
	}

// return the value of the radio button that is checked
// return an empty string if none are checked, or
// there are no radio buttons
function rb_getCheckedValue(radioObj) {
	if(!radioObj)
		return "";
	var radioLength = radioObj.length;
	if(radioLength == undefined)
		if(radioObj.checked)
			return radioObj.value;
		else
			return "";
	for(var i = 0; i < radioLength; i++) {
		if(radioObj[i].checked) {
			return radioObj[i].value;
		}
	}
	return "";
}

// set the radio button with the given value as being checked
// do nothing if there are no radio buttons
// if the given value does not exist, all the radio buttons
// are reset to unchecked
function rb_setCheckedValue(radioObj, newValue) {
	if(!radioObj)
		return;
	var radioLength = radioObj.length;
	if(radioLength == undefined) {
		radioObj.checked = (radioObj.value == newValue.toString());
		return;
	}
	for(var i = 0; i < radioLength; i++) {
		radioObj[i].checked = false;
		if(radioObj[i].value == newValue.toString()) {
			radioObj[i].checked = true;
		}
	}
}

try
{
	if (oojs_moduleLoaded) oojs_moduleLoaded ("core/scriptlib/jslib.js");
}
catch (e) { }
