function createIEaddEventListeners()
{
    if (document.addEventListener || !document.attachEvent)
        return;

    function ieAddEventListener(eventName, handler, capture)
    {
        if (this.attachEvent)
            this.attachEvent('on' + eventName, handler);
    }

    function attachToAll()
    {
        var i, l = document.all.length;

        for (i = 0; i < l; i++)
            if (document.all[i].attachEvent)
                document.all[i].addEventListener = ieAddEventListener;
    }

    var originalCreateElement = document.createElement;

    document.createElement = function(tagName)
    {
        var element = originalCreateElement(tagName);
        
        if (element.attachEvent)
            element.addEventListener = ieAddEventListener;

        return element;
    }
    
    window.addEventListener = ieAddEventListener;
    document.addEventListener = ieAddEventListener;

    var body = document.body;
    
    if (body)
    {
        if (body.onload)
        {
            var originalBodyOnload = body.onload;

            body.onload = function()
            {
                attachToAll();
                originalBodyOnload();
            };
        }
        else
            body.onload = attachToAll;
    }
    else
        window.addEventListener('load', attachToAll);
}

createIEaddEventListeners();


MajicDoc.prototype.getWindowHeight = function()
{
	return window.innerHeight?window.innerHeight:document.body.offsetHeight;
}


MajicDoc.prototype.getWindowWidth = function()
{
	w = window.innerWidth?window.innerWidth:document.body.offsetWidth;
	
//	ofs = window.scrollWidth-window.innerWidth;
	
//	w -= ofs;
	
	return w;
}

//! hide an object on the page
/*!
  \param objName string DOM id.
  \sa show()
*/
MajicDoc.prototype.hide = function(objName)
{
	obj = this.getDocObj(objName);

	if (!obj) return;
		
	this.objdisplay[objName] = new Array();
	this.objdisplay[objName]['display'] = obj.style.display;
	this.objdisplay[objName]['visibility'] = obj.style.visibility;
	this.objdisplay[objName]['width'] = obj.style.width;
	this.objdisplay[objName]['height'] = obj.style.height;
	this.objdisplay[objName]['border'] = obj.style.border;
	this.objdisplay[objName]['overflow'] = obj.style.overflow;
	
//	this.objdisplay[objName]['mozOpacity'] = obj.style.mozOpacity;
//	this.objdisplay[objName]['filter'] = obj.style.filter;

	if (obj.style)
	{
		if (obj.tagName == 'IFRAME')
		{
	//		obj.style.display="none";
			obj.style.height="0px";
			obj.style.visibility="hidden";
	//		obj.style.height = "0px";
			obj.style.border = "0px";
		}
		else if (obj.tagName == "TR" || obj.tagName == "TD")
		{
			obj.style.display='none';	
		}
		else 
		{	
			//if (this.bw.ie) 
			obj.style.display="none";
	//		obj.style.overflow="hidden";
	//		obj.style.visibility="hidden";
	//		obj.style.height="0px";
//			obj.style.height="0px";

		}
	}
}

//! show an object on the page that was hidden using hide()
/*!
  \param objName string DOM id.
  \sa hide()
*/
MajicDoc.prototype.show = function(objName)
{
	obj = this.getDocObj(objName);
	
	if (typeof(this.objdisplay[objName]) == "object")
	{
		obj.style.display = this.objdisplay[objName]['display'];
		obj.style.visibility = this.objdisplay[objName]['visibility'] = "visible";
		obj.style.width = this.objdisplay[objName]['width'];
		obj.style.height = this.objdisplay[objName]['height'];
		obj.style.border = this.objdisplay[objName]['border'];
		obj.style.overflow = this.objdisplay[objName]['overflow'];
//		obj.style.mozOpacity = this.objdisplay[objName]['mozOpacity'];
//		obj.style.filter = this.objdisplay[objName]['filter'];
	}
	else if (obj) if (obj.style)
	{
		obj.style.display = "";
		obj.style.visibility = "visible";
	}
	
	if (obj.tagName == 'IFRAME')
	{
		obj.style.height = "100%";
		//FRP.removeClass(obj,"iframeHidden");
	}
}


//! get object height in pixels
/*!
  \param objName string DOM id.
  \sa getObjHeight()
*/
MajicDoc.prototype.getDocObjHeight = function(objName)
{
	return this.getObjHeight(this.getDocObj(objName));
}

//! get object height in pixels
/*!
  \param obj DOM element reference.
  \sa getDocObjHeight()
*/
MajicDoc.prototype.getObjHeight = function(obj)
{	
	var h,tbl,padval;

	h = obj.clientHeight?obj.clientHeight:obj.offsetHeight;
	
	if (obj.tagName == "TD") 
	{
		h = obj.clientHeight;

		tbl = obj.parentNode;
		while (tbl && tbl.tagName != "TABLE") tbl = tbl.parentNode;
		
		if (!tbl) alert("no table for td element -- Please submit a problem report with the steps taken to cause this error.");
		
		padval = tbl.getAttribute('cellpadding');
		
		if (padval) h -= 2*padval;
	}

	return h;
}



//! get object width in pixels
/*!
  \param objName string DOM id.
  \sa getObjWidth()
*/
MajicDoc.prototype.getDocObjWidth = function(objName)
{
	return this.getObjWidth(this.getDocObj(objName));
}

//! get object width in pixels
/*!
  \param obj DOM element reference.
  \sa getDocObjWidth()
*/
MajicDoc.prototype.getObjWidth = function(obj)
{	
	var w,tbl,padval;

	if (!obj) return 0;

	w = obj.clientWidth?obj.clientWidth:obj.offsetWidth;
	
	if (obj.tagName == "TD" || obj.tagName == "TH") 
	{
		tbl = obj.parentNode;
		while (tbl && tbl.tagName != "TABLE") tbl = tbl.parentNode;
		
		if (!tbl) alert("no table for td element -- Please submit a problem report with the steps taken to cause this error.");
		
		padval = tbl.getAttribute('cellpadding');
		
		if (padval) w -= 2*padval;
	}

	return w;
}


//! fit an object into it's containing object, seperate show/hide stages allow you to chain nested resize commands, optional parent id
/*!
  \param objName string DOM id of object to fit.
  \param resize_state string value "hide" or "show" for chained resize
  \param parentName string DOM id of parent container to fit to
*/
MajicDoc.prototype.fitObj = function(objName,resize_state,parentName)
{
	obj = this.getDocObj(objName);

	if (!obj) 
	{
		debugprint("fitObj called for non-existant object: "+objName);
		return;
	}
	
	par = (typeof(parentName)!='undefined')?this.getDocObj(parentName):obj.parentNode;
	
	
	if (!par) alert("No parent for layout height ["+objName+(parentName?(","+parentName):"")+"] -- Please submit a problem report with the steps taken to cause this error.");
	
	
	if ((resize_state == "hide" || typeof(resize_state) == 'undefined'))
	{	
		this.hide(objName);
	
		// hide stage, just return
		if (resize_state == "hide")
		{
			return;
		}
		
		// single stage show/hide method, state not defined so we immediately re-show the object since it's not part of a resize chain
		if (typeof(resize_state) == 'undefined')
		{
			this.fitObj(objName,"show",parentName);	
		}
	}
	
	
	
	h = this.getObjHeight(par);
	w = this.getObjWidth(par);

/*
	debugprint("fit object ["+objName+"] par["+par+"]");
	
	while (par)
	{
	debugprint("  |- parent ["+par.tagName+":"+par.id+"] w:" +this.getObjWidth(par) +" h:"+ this.getObjHeight(par));
		if (!par.parentNode) break;
		par = par.parentNode;
	}
/*	*/
		
	this.objdisplay[objName]['width'] = "100%"; //  w+"px"; / "100%"; ?
	this.objdisplay[objName]['height'] = h+"px";
	this.show(objName);
}


// fit obj within visibile extents, pad by a little bit
MajicDoc.prototype.fitObjZoom=function(objName,resize_state,parentName)
{
	obj = this.getDocObj(objName);
	par = parentName?this.getDocObj(parentName):obj.parentNode;
	
	if (!par) alert("no parent for layout height -- Please submit a problem report with the steps taken to cause this error.");
	
	if ((resize_state == "hide" || typeof(resize_state) == 'undefined'))
	{	
		this.hide(objName);
	
		if (resize_state == "hide")
		{
			return;
		}
	}
	
	h = this.getObjHeight(par);
	
	var frameheight;
	if (self.innerHeight)
	{
		frameheight = self.innerHeight;
	}
	else if (document.documentElement && document.documentElement.clientHeight)
	{
		frameheight = document.documentElement.clientHeight;
	}
	else if (document.body)
	{
		frameheight = document.body.clientHeight;
	}
	
//	if(h > frameheight)
//	{
	h = Math.round(frameheight * 0.75);
//	}

	this.objdisplay[objName]['width'] = "75%";
	this.objdisplay[objName]['height'] = h+"px";
	this.show(objName);
}


// beta func to center an element, please "majic"-ify
MajicDoc.prototype.centerElement = function(objName)
{
	var obj = this.getDocObj(objName);
	
	if(obj)
	{
		var x = this.findIt(objName)[0];
		var y = this.findIt(objName)[1];
		var w = obj.clientWidth;
		var h = obj.clientHeight;
		
		var framewidth,frameheight;
		if (self.innerHeight)
		{
			framewidth = self.innerWidth;
			frameheight = self.innerHeight;
		}
		else if (document.documentElement && document.documentElement.clientHeight)
		{
			framewidth = document.documentElement.clientWidth;
			frameheight = document.documentElement.clientHeight;
		}
		else if (document.body)
		{
			framewidth = document.body.clientWidth;
			frameheight = document.body.clientHeight;
		}
		
		frameheight = document.body.parentNode.clientHeight;
		
		_majicipc.debugprint("4 frameheight=["+document.body.parentNode.clientHeight+"] nodename=["+document.body.parentNode.nodeName+"]");
		_majicipc.debugprint("4 frameheight=["+document.body.parentNode.innerHeight+"] nodename=["+document.body.parentNode.nodeName+"]");
		
		
		if(frameheight&&framewidth)
		{
			var newx = Math.round(framewidth/2) - Math.round(w/2); 
			var newy = Math.round(frameheight/2) - Math.round(h/2); 
			
			_majicipc.debugprint("placing element at "+newx+","+newy+" , have a nice day w=["+w+"] h=["+h+"] fh=["+frameheight+"] fw=["+framewidth+"]");
			this.placeIt(objName,newx,newy);
		}
	}
}


//! retrieve the internal height of an iframe.
/*!
  \param objName string DOM id of object to fit.
  \param minimum simple override, if frame is less than minimum than return minimum.
*/
MajicDoc.prototype.getFrameHeight = function(objName,minimum)
{
	if (!minimum) minimum = 0;
	
	frmdoc = this.getFrameDoc(objName);
	obj = this.getDocObj(objName);
	
	if(this.bw.moz)
	{
		if (!frmdoc.body) return minimum;
		
		bwidth=frmdoc.body.scrollWidth
		bheight=frmdoc.body.scrollHeight
	} 
	else
	{
		if (frmdoc.body == null)
		{
			bwidth=1;
			bheight=minimum;
		}
		else
		{
			bwidth=frmdoc.body.scrollWidth;
			bheight=frmdoc.body.scrollHeight;
		}
	}

	if (minimum && bheight < minimum) bheight = minimum;
	
	return bheight;
}

MajicDoc.prototype.getServiceURL = function(postfix)
{
	return this.doc.location.href.substring(0,document.location.href.lastIndexOf('/'))+"/"+(postfix?postfix:"");
}

MajicDoc.prototype.getServiceApp = function()
{
	var requesturl,ar,urlstr;

	requesturl = window.location.toString();
	ar = requesturl.split("/");
	if (!ar.length) return;
	urlstr = ar[ar.length-1];
	ar = urlstr.split("?");
	return this.getServiceURL(ar[0]);
}


MajicDoc.prototype.fetchTo = function(objName,url,params,method)
{
	obj = this.getDocObj(objName);
	fdoc = this.getFrameDoc(objName);
	
	obj.src = url;
}


MajicDoc.prototype.doNothingFunc = function()
{
	// placeholder for null function assignment
}


//! blocking request, fetch the given url directly to innerHTML of specified object
/*!
	\param objName string DOM id of object to set resultant innerHTML value.
	\param url URL to fetch from.
	\param params can be a url string, form name from the current document or an associative array of key/value pairs
	\param method string of either "POST" or "GET", defaults to "POST"
*/
MajicDoc.prototype.fetchToInnerHTML = function(objName,url,params,method,isAsync,asyncfunc)
{	
	obj = this.getDocObj(objName);
	
	obj.innerHTML = this.fetch(url,params,method);	
}


//! dynamic request, fetch the given url directly to innerHTML of specified object with callback function for completion
/*!
	\param objName string DOM id of object to set resultant innerHTML value.
	\param url URL to fetch from.
	\param params can be a url string, form name from the current document or an associative array of key/value pairs
	\param method string of either "POST" or "GET", defaults to "POST"
	\param asyncfunc if isAsync is set to true this is the function that will be called upon completion of innerHTML set
*/
MajicDoc.prototype.fetchToInnerHTMLAsync = function(objName,url,params,method,asyncfunc)
{
	var asyncId;
	
	asyncId = this.fetch(url,params,method,true,asyncfunc);
	
	this.asyncrequests[asyncId]['targetobj'] = objName;
}



//! builds a request string from a form for POST'ing to a server
/*!
	\param frmName name of the form to build the request string from.
*/
MajicDoc.prototype.buildFormQuery = function(frmName) 
{
	frmObj = this.doc.forms[frmName];
	
	var i;
	var qs = '';
	
	for (i = 0; i < frmObj.elements.length; i++)
	{
		elem = frmObj.elements[i];

		//
		// updated by maciek
		// - support singleton checks/radios
		// - fix value overwrite bug
		// - fix interpretation of ".value" when singletons are used
		//
		if (elem.name != '')
		{
			//
			// singleton radio buttons
			//
			if (elem.type == 'radio' && !elem.multiple)
			{
				if (elem.checked)
				{
					qs += (qs?'&':'')+elem.name+'='+encodeURIComponent(elem.value);
				}
			}
			//
			// singleton checkboxes
			//
			else if(elem.type == 'checkbox' && !elem.multiple)
			{
				if (elem.checked && !elem.multiple)
				{
					qs += (qs?'&':'')+elem.name+"=1";
				}
				else
				{
					qs += (qs?'&':'')+elem.name+"=";
				}
			}
			//
			// other singleton elements
			//
			else if(!elem.multiple)
			{
				qs += (qs?'&':'')+elem.name+'='+encodeURIComponent(elem.value);
			}
			//
			// multipled (non-singleton) elements
			//
			else if(elem.multiple)
			{
				for (j = 0; j < elem.length; j++)
				{
					if (elem.options[j].selected)
					{
						qs += (qs?'&':'')+elem.name+'[]='+encodeURIComponent(elem.options[j].value);
					}
				}
			}
		}
	}
			
	return qs;
}



//! dynamic or static request, fetch the given url
/*!
	\param url URL to fetch from.
	\param params can be a url string, form name from the current document or an associative array of key/value pairs
	\param method string of either "POST" or "GET", defaults to "POST"
	\param isAsync boolean true/false, set to true to make this request asynchronous
	\param asyncfunc if isAsync is set to true this is the function that will be called when the request is completed
*/
MajicDoc.prototype.fetch = function(requesturl, params, method, isAsync, asyncfunc)
{	
	// note: this was put in to fix IE, why was undefined not detected as false?
	
	if (typeof(isAsync)=='undefined') { isAsync = false; }
	
	ret = this.fetchRequest(requesturl,params,method,isAsync,asyncfunc);
	
	if (isAsync) this.asyncrequests[ret]['responsetype'] = "HTML";
	return isAsync?ret:ret.responseText;
}


//! dynamic or static request, fetch the given url as HTML
/*!
	\sa fetch()
*/
MajicDoc.prototype.fetchHTML = MajicDoc.prototype.fetch;


//! dynamic or static request, fetch the given url as XML
/*!
	\sa fetch()
*/
MajicDoc.prototype.fetchXML = function(requesturl, params, method, isAsync, asyncfunc)
{	
	var ret;
	
	ret = this.fetchRequest(requesturl,params,method,isAsync,asyncfunc);
	
	if (isAsync) this.asyncrequests[ret]['responsetype'] = "XML";
	
	return isAsync?ret:ret.responseXML;
}


// return string representing the object. this is not recursive
MajicDoc.prototype.createXMLRequestFromObj = function(obj)
{
	if(typeof(obj)!='object') throw "createXMLRequestFromObj(): obj is not an object";

	//i.replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;') + "\"";
	var s = "<o>";
	for(var i in obj) 
	{
		if(typeof(obj[i])=='undefined') debugprint("obj["+i+"] is undefined");
		if(typeof(obj[i])!='string' && typeof(obj[i])!='number') debugprint("obj["+i+"] is not a string or number, type is ["+typeof(obj[i])+"], js sees it as ["+obj[i]+"]");
		var strKey = i.toString().replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');
		if(obj[i]==null)
		{
			obj[i] = "";
		}
		var strVal = obj[i].toString().replace(/&/g, '&amp;').replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/\"/g, '&quot;');
		s += "<a k=\""+(strKey)+"\" v=\""+(strVal)+"\"/>";
	}
	return s + "</o>";
}


//
//	fetchRequest - generic XMLHTTPRequest processor, not to be called directly, used internally
//
//	requesturl - url to post/get
//	params - a string of parameters in GET format, an associative array of elements or a form name
//	method - POST or GET, defaults to POST
//	isAsync	- Perform request asynchronously
//	asyncfunc - function to call when request has completed.  function will be called with returned data as a parameter
//
MajicDoc.prototype.fetchRequest = function(requesturl, params, method, isAsync, asyncfunc)
{
	var i,bp,isAsync,asyncId,xmlHttp;
	
	if (typeof(isAsync)=='undefined') isAsync = false;

	// default method of POST if none specefied
	if (!method) method = "POST";

	// build the query string
	qs = '';
	if (typeof(params)=='object')	// associative array passed
	{
		// build request from associative array
		for (i in params)
		{
//			qs += escape(i);
			qs += encodeURIComponent(i);
			qs += '=';
//			qs += escape(params[i]);
			qs += encodeURIComponent(params[i]);
			qs += "&";
		}
	}
	else if (typeof(params) != 'undefined' || typeof(params)=='string')	// string passed
	{
		// string could be GET params or the name of a form, we'll check for a form name first.
		
		if (this.doc.forms[params]) // form name matched, use form data
		{
			qs += this.buildFormQuery(params);
			if (!requesturl) requesturl = this.doc.forms[params].getAttribute("action");
		}
		else	// directly passed a query string, use it as-is
		{
			qs += params;
		}
	}

	
	if (!requesturl) // if all else fails submit to where we came from, same behaviour as form
	{
		requesturl = window.location.toString();
		ar = requesturl.split("/");
		if (!ar.length) return;
		urlstr = ar[ar.length-1];
		ar = urlstr.split("?");
		requesturl = this.getServiceURL(ar[0]);
	} 

	
	// GET method provides query string in the URL
	if (method == "GET")
	{
		requesturl += "?"+qs;
	}
	
	// Asynchronous
	if (isAsync)
	{	
		// each asynch request needs it's own instance of HTMLHttpRequest
		var xmlHttpAsync = document.all ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();

		asyncId = ++this.asynccount;
		
		//debugprint("Async requested, created request ["+asyncId+"] call func ["+asyncfunc+"]");
		
		debugprint_info("----------- CREATING ASYNC REQUEST -------------");
		this.asyncrequests[asyncId] = new Array();
		debugprint_info("----------- ASYNC REQUEST ["+asyncId+"] "+this.asyncrequests[asyncId]+" -------------");
		
	
		// store request obj for reference
		xmlHttp = this.asyncrequests[asyncId]['requestobj'] = xmlHttpAsync;
		this.asyncrequests[asyncId]['callfunc'] = asyncfunc;
	}
	else
	{
		// synchronous request, use the global xmlhttprequest object
		if (!this.xmlHttp)
		{
			this.xmlHttp = document.all ? new ActiveXObject("Microsoft.XMLHTTP") : new XMLHttpRequest();
		}

		xmlHttp = this.xmlHttp;
	}
	
	if (isAsync)	
	{
		function makeAsyncReturnClosure(asyncId)
		{
		    return function() { _mjDoc.asyncReturn(asyncId); };
		}
		// bind async return function
		xmlHttp.onreadystatechange = makeAsyncReturnClosure(asyncId);
	}
	else
	{
		// synchronous, no state change available
	}

	if(requesturl==null)
	{
		throw "Required parameter requesturl is null while attempting AJAX transaction (did you check that the form had an URL in the action field?)";
	}
		
	xmlHttp.open(method, requesturl, isAsync);

	if (method == "POST")
	{
		xmlHttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
		xmlHttp.send(qs);
	}
	else
	{
		xmlHttp.send("");		
	}
	
	// Async returns reference id, synch returns global request object
	if (isAsync)
	{
		return asyncId;
	}
	else
	{
		return xmlHttp;
	}
}


//
// asyncReturn function - process active async requests
//
MajicDoc.prototype.asyncReturn = function(asyncId)
{
	
	if (typeof(this.asyncrequests[asyncId]) == 'undefined') 
	{
		debugprint("Error: AsyncId ["+asyncId+"] made request after it was finished, req.readyState["+req.readyState+"] req.status["+req.statusText+"]");	
		return;
	}
	
	var req = this.asyncrequests[asyncId]['requestobj'];
	var responseType = this.asyncrequests[asyncId]['responsetype'];

	if (req.readyState == 4)
	{
		if (req.status==200) 
		{
			var funcToCall = this.asyncrequests[asyncId]['callfunc'];
//			debugprint_warn("maad6:funcToCall(asyncId=["+asyncId+"])==["+funcToCall+"]");
			
			
			
			
			if (typeof(this.asyncrequests[asyncId]['targetobj']) != 'undefined')
			{
				this.getDocObj(this.asyncrequests[asyncId]['targetobj']).innerHTML = req.responseText;
				
				if (typeof(funcToCall) == 'function') 
				{
//					debugprint_warn("maad6: funcToCall from 1");
					funcToCall((responseType == "HTML")?req.responseText:req.responseXML);
				}
			}
			else if (typeof(funcToCall) == 'function')
			{
//				debugprint_warn("maad6: funcToCall from 2, responseType=["+responseType+"]");
				if(responseType=="HTML")
				{
//					debugprint_warn("maad6: sending responseText=["+req.responseText+"]");
					funcToCall(req.responseText);
				}
				else if(responseType=="XML")
				{
//					debugprint_warn("maad6: sending responseXML=["+req.responseXML+"]");
					funcToCall(req.responseXML);
				}
			}
			else
			{
				debugprint("Warning: AsyncId ["+asyncId+"] had no particular hopes and dreams (funcToCall = undefined, target = none).");	
			}
			
			// request is complete, kill req object
			delete this.asyncrequests[asyncId]['requestobj'];
			delete this.asyncrequests[asyncId];
		}
		else
		{
			alert("async call failed, id: "+asyncId);
			//	funcToCall(false);	
		}
	}
}


MajicDoc.prototype.setCellWidths = function(tableDst,arWidths,ofs)
{
	var w;
	
	tbldst = this.getDocObj(tableDst);
	
	tr_dst = tbldst.firstChild;
	while (tr_dst && tr_dst.tagName != "TR") tr_dst = tr_dst.firstChild; 
	
	if (!tr_dst) return;
	
	td_dst = tr_dst.getElementsByTagName("TD");
	
	// th's
	if (td_dst.length == 0) td_dst = tr_dst.getElementsByTagName("TH");
	
	if (td_dst.length == 0) return;
	
	w = 0;
	if (!ofs) ofs = 0;
	for (i = 0; i < arWidths.length; i++)
	{
		if (i <= ofs) 
		{
			w += arWidths[i];
			if (i != ofs) continue;
		}
		else
		{
			w = arWidths[i];
		}
		
		if (i-ofs < 0 || i-ofs >= td_dst.length) continue;
		
		td_dst.item(i-ofs).style.width = (w) + "px";
		w = 0;
	}
}

MajicDoc.prototype.tableAlign = function(tableDst,tableSrc)
{
	tblsrc = this.getDocObj(tableSrc);	
	tbldst = this.getDocObj(tableDst);
	
	tr_src = tblsrc.firstChild;
	while (tr_src && tr_src.tagName != "TR") tr_src = tr_src.firstChild; 
	
	tr_dst = tbldst.firstChild;
	while (tr_dst && tr_dst.tagName != "TR") tr_dst = tr_dst.firstChild; 
	
	if (!tr_src) return;
	if (!tr_dst) return;
	
	td_dst = tr_dst.getElementsByTagName("TD");
	td_src = tr_src.getElementsByTagName("TD");
	
	// th's
	if (td_dst.length == 0) td_dst = tr_dst.getElementsByTagName("TH");
	
	if (td_src.length == 0 || td_dst.length == 0) return;
	
	var w=0, tw=0;
	
	for (i = 0; i < td_src.length; i++)
	{
		tw += this.getObjWidth(td_src.item(i));
	}
	
	for (i = 0; i < td_dst.length; i++)
	{
		w = this.getObjWidth(td_src.item(td_src.length-i-1));
		tw -= w;
				
		if (i == td_dst.length-1) w += tw;
				
		td_dst.item(td_dst.length-i-1).style.width = w + "px";			
		debugprint("w:"+td_dst.item(td_dst.length-i-1).style.width);
	}
}


MajicDoc.prototype.getFrameDoc = function(id)
{
	iframe = this.getDocObj(id);

	if (iframe.contentDocument) 
	{
		// For NS6
		doc = iframe.contentDocument; 
	} 
	else if (iframe.contentWindow) 
	{
		// For IE5.5 and IE6
		doc = iframe.contentWindow.document;
	} 
	else if (iframe.document) 
	{
		// For IE5
		doc = iframe.document;
	} 
	else 
	{
		alert("Error: iframe not found! -- Please submit a problem report with the steps taken to cause this error.");
		return true;
	}
	
	return doc;
}



function MajicDoc(doc_in)
{
	this.document = doc_in;
	this.doc = doc_in;
	
	this.mjParent = null;
	this.ipcname = "";
	
	this.bw=new this.bwcheck()
	this.helptips=new Array();
	this.helptippos=new Array();
	this.selhide=new Array();
	this.children=new Array();
	this.hooks=new Array();
	this.watches=new Array();
	this.objdisplay=new Array();
	this.resizeobjs=new Array();
	this.resizehooks=new Array();
	this.resizecache=new Array();
	this.asyncrequests=new Array();
	this.asynccount=0;
	this.childResizeCallback = null;
	this.lastWidth = 0;
	this.lastHeight = 0;
	
	scripts = document.getElementsByTagName("SCRIPT");
	this.scriptPath = "";
	this.includePath = "";

	for (i = 0; i < scripts.length; i++)
	{
		scr = scripts.item(i);
		script_filename = scr.getAttribute("src");
		if (script_filename)
		{
			script_path = script_filename.split("/");
			if (script_path[script_path.length-1] == 'majicdoc.js')
			{
				for (j = 0; j < script_path.length-1; j++)
				{
					this.scriptPath += script_path[j]+"/";
					if (j < script_path.length-2)
					{
						this.includePath += script_path[j]+"/";
					}
				}
				
			}
		}
	}
}


MajicDoc.prototype.bwcheck=function()
{
	this.ver=navigator.appVersion
	this.agent=navigator.userAgent
	this.dom=document.getElementById?1:0

	if (this.op=window.opera)
	{
		this.op5=(this.agent.indexOf("opera 5")>-1 || this.agent.indexOf("opera/5")>-1)
		this.op6=(this.agent.indexOf("opera 6")>-1 || this.agent.indexOf("opera/6")>-1)
		this.op7=this.dom&&!this.op5&&!this.op6 //So all higher opera versions will use it
	}

	this.moz=(this.agent.indexOf("gecko")>-1 || window.sidebar)
	this.opera5=this.agent.indexOf("Opera 5")>-1
	this.ie5=(this.ver.indexOf("MSIE 5")>-1 && this.dom && !this.opera5)?1:0; 
	this.ie6=(this.ver.indexOf("MSIE 6")>-1 && this.dom && !this.opera5)?1:0;
	this.ie4=(document.all && !this.dom && !this.opera5)?1:0;
	this.ie=this.ie4||this.ie5||this.ie6
	this.mac=this.agent.indexOf("Mac")>-1
	this.ns6=(this.dom && parseInt(this.ver) >= 5) ?1:0; 
	this.ns4=(document.layers && !this.dom)?1:0;
	this.bw=(this.ie6 || this.ie5 || this.ie4 || this.ns4 || this.ns6 || this.opera5)

	this.usedom= this.ns6||this.op7//Use dom creation
	this.reuse = this.ie||this.op7||this.usedom //Reuse layers
	this.px=this.dom&&!this.op5?"px":""

	return this
}


MajicDoc.prototype.getDocObjStr=function(elem,parent) 
{
	if (this.doc.layers) 
	{
		if (parent) 
		{
			return "this.doc."+parent+".document."+elem;
		}
		else 
		{
			return "this.doc."+elem;
		}
	} 
	else if (this.doc.all) 
	{
		return "this.doc.all."+ elem;
	}
	else if (this.doc.getElementById) 
	{
		return "this.doc.getElementById('"+elem+"')";
	}
}


MajicDoc.prototype.getStyleObjStr=function(elem,parent) 
{
	if (this.doc.layers) 
	{
		if (parent) 
		{
			return "this.doc."+parent+".document."+elem;
		}
		else 
		{
			return "this.doc."+elem + ".style";
		}
	}
	else if (this.doc.all) 
	{
		return "this.doc.all."+elem + ".style";
	}
	else if (this.doc.getElementById) 
	{
		return "this.doc.getElementById('"+elem+"').style";
	}
}


MajicDoc.prototype.placeIt=function(elem,leftPos,topPos) 
{
		docObj = this.getStyleObj(elem);
		
		if (this.bw.ns4 || this.bw.ns6) 
		{
			docObj.left = leftPos;
			docObj.top= topPos;
		}
		else if (this.bw.ie) 
		{
			docObj.pixelLeft = leftPos;
			docObj.pixelTop = topPos;
		}
}


// find left X coordinate of a DOM object (Quirksmode solution, but modified to fix for Safari)
MajicDoc.prototype.findPosX = function(DOMobj)
{
	var curleft = 0;
	if(DOMobj.offsetParent)
	{
		while(1) 
		{
			curleft += DOMobj.offsetLeft;
			if(!DOMobj.offsetParent) break;
			DOMobj = DOMobj.offsetParent;
		}
	}
	else if(DOMobj.x)
	{
		curleft += DOMobj.x;
	}
	return curleft;
}


// find top Y coordinate of a DOM object (Quirksmode solution, but modified to fix for Safari)
MajicDoc.prototype.findPosY = function(DOMobj)
{
	var curtop = 0;
	if(DOMobj.offsetParent)
	{
		while(1)
		{
			curtop += DOMobj.offsetTop;
			if(!DOMobj.offsetParent) break;
			DOMobj = DOMobj.offsetParent;
		}
	}
	else if(obj.y)
	{
		curtop += DOMobj.y;
	}
	return curtop;
}


MajicDoc.prototype.findIt = function(objname)
{
	s = "";

	x=0; y=0; 
	var el,temp
	el = this.getDocObj(objname);
	
	if(el.offsetParent)
	{
		temp = el

		while(temp.offsetParent)
		{ //Looping parent elements to get the offset of them as well
			temp=temp.offsetParent;
			x+=temp.offsetLeft
			y+=temp.offsetTop;
		}
	}
	
	x+=el.offsetLeft
	y+=el.offsetTop

	return [x,y]
}


MajicDoc.prototype.getDocObj=function(elem,parent)
{
	return eval(this.getDocObjStr(elem,parent));
}


MajicDoc.prototype.getStyleObj=function(elem,parent)
{
	return eval(this.getStyleObjStr(elem,parent));
}


MajicDoc.prototype.hideTip=function(objId)
{
	this.helptips[objId].style.visibility = "hidden";
	
	if (this.bw.ie) this.showSelects();
	$(objId).removeChild(this.helptips[objId]);	// rebuild each time for new position
}


MajicDoc.prototype.helpTip=function(objId,TipTitle,TipMessage,clr)
{
	
	// if (this.helptips[objId])
	// {
	// 	this.helptips[objId].style.visibility = "visible";
	// }
	// else
	{
		var pos = this.findIt(objId);
		var obj = this.getDocObj(objId);
				
		x = pos[0]+obj.offsetWidth+4;
		y = pos[1]-6;
		bw = this.doc.body.scrollWidth;
			
		elem = this.doc.createElement("div");
		elem.style.height="0px";
		elem.style.position="absolute";
		elem.style.overflow="visible";
		elem.style.left=x;
		
		elem.innerHTML = "<div class='helptip_box'><p class='helptip_title'>"+TipTitle+"</p><p class='helptip'>"+TipMessage+"</p></div>";
		
		$(objId).appendChild(elem);
		
		w = elem.firstChild.offsetWidth;
		h = elem.firstChild.offsetHeight;

		if ( (x + 100) > bw || ( x + 200 > bw && TipMessage.length > 100))
		{
			$(objId).removeChild(elem);
			
			w = 200;
			x = pos[0] - obj.offsetWidth - w;

			elem.innerHTML = "<div class='helptip_box' style='width:" + w + "px;'><p class='helptip_title'>"+TipTitle+"</p><p class='helptip'>"+TipMessage+"</p></div>";

			elem.style.left=x;
	
			h = elem.firstChild.offsetHeight;
			$(objId).appendChild(elem);
		}

		
		this.helptips[objId] = elem;
		this.helptippos[objId] = [x, y, w, h];
	}
	
	elem = this.helptips[objId];
	pos = this.helptippos[objId];
	
	if (this.bw.ie) this.hideSelects(pos[0],pos[1],pos[2],pos[3]);
}


MajicDoc.prototype.showSelects = function()
{
	if (!this.selhide.length) return;
	
  var sel=this.sel

	while (this.selhide.length)
	{
		elem = sel[this.selhide.pop()];	
		elem.style.visibility="visible";
	}
}


MajicDoc.prototype.hideSelects = function(x,y,w,h)
{
    var selx,sely,selw,selh,i;
    
    if(!this.sel)
    {
      this.sel=this.doc.getElementsByTagName("SELECT")
    }
    
    var sel=this.sel
    
    for(i=0;i<sel.length;i++)
    {
			var selp;
			
			selx=0; sely=0; 
			
			if(sel[i].offsetParent)
			{
				selp=sel[i]; 
				
				while(selp.offsetParent)
				{
					selp=selp.offsetParent;
					selx+=selp.offsetLeft;
					sely+=selp.offsetTop;
				}
			}
		
			selx+=sel[i].offsetLeft;
			sely+=sel[i].offsetTop;
			selw=sel[i].offsetWidth;
			selh=sel[i].offsetHeight;
			
			//intersect
			if( selx + selw > x && selx < (x + w) && sely + selh > y && sely < (y + h))
			{
				if(sel[i].style.visibility!="hidden")
				{
					sel[i].style.visibility="hidden"; 
					this.selhide.push(i);
				}
    	}
    }
  }


MajicDoc.prototype.setObjClass = function(objName,className)
{
	obj = this.getDocObj(objName);
	if(!obj) throw "MajicDoc.setObjClass(): Could not find object with objName=('"+objName+"')";
	obj.className = className;
}


MajicDoc.prototype.populateFormXML = function(frmName,xmlData)
{
	var i,j,rootNode;

	frmObj = this.doc.forms[frmName];
	
	selectNodes = xmlData.getElementsByTagName("select");
	
	for (i = 0; i < selectNodes.length; i++)
	{
		iNode = selectNodes.item(i);
		elemName = iNode.getAttribute('name');

		if (typeof(frmObj[elemName]) == 'undefined') 
		{
			debugprint("Error: Unable to populate select box "+elemName+", does not exist here, skipping...");
			continue;
		}
		
		elem = frmObj[elemName];			
		
		optNodes = iNode.getElementsByTagName("option");
		jLen = optNodes.length;
		
		// grab current selection
		if (elem.selectedIndex != -1) selValue = elem.options[elem.selectedIndex].value; 
		else selValue = "";
		
		selIndex = -1;
	
		// Input new selections
		for (j = 0; j < jLen; j++)
		{
			jNode = optNodes.item(j);
			
			if (jNode.firstChild) txt = jNode.firstChild.nodeValue; else txt = "";
			val = jNode.getAttribute('value');
			
			if (val == selValue) selIndex = j;
			
			elem.options[j] = new Option(txt,val);
		}
		
		// Remove any leftovers
		for (j = elem.options.length; j >= jLen; j--)
		{
			elem.options[j] = null;
		}
		
		// Reset selection to previous
		if(selIndex != -1)		elem.options[selIndex].selected = true;
	}
}


MajicDoc.prototype.addLayoutObj = function(objName,parentName)
{
	this.addResizeObj(objName,parentName);
}

MajicDoc.prototype.addResizeObj = function(objName,parentName)
{
	layout_obj = new Array();
	layout_obj['type'] = 'obj';
	layout_obj['name'] = objName;
	layout_obj['parent'] = parentName;
	
	this.resizeobjs.push(layout_obj);
}

MajicDoc.prototype.removeResizeObj = function(objName,parentName)
{
	for (i in this.resizeobjs)
	{
		if (this.resizeobjs[i]['name'] == 'objName')
		{
			this.resizeobjs[i] = null;
		}
	}
}

MajicDoc.prototype.addResizeHook = function(func_in)
{
	hook_obj = new Array();
	hook_obj['type'] = 'hook';
	hook_obj['func'] = func_in;
	
	this.resizeobjs.push(hook_obj);
}


MajicDoc.prototype.doResize  = function(bForce)
{
	var w, h;
	
	w = this.getWindowWidth();
	h = this.getWindowHeight();
	
	if (this.lastWidth && this.lastHeight && w == this.lastWidth && h == this.lastHeight && !bForce)
	{
		return;
	}

	this.lastWidth = w;
	this.lastHeight = h;
	
	window.onresize=null;
	
	var j,i;
	
	if (this.resizeobjs.length)
	{
		var modes = ["hide","show"];
		var firstObj = 0;
		
		for (j = 0; j < 2; j++)
		{			
			for (i = 0; i < this.resizeobjs.length; i++)
			{
				objName = null;
				parName = null;
				if (this.resizeobjs[i] == null) continue;
				
				if (this.resizeobjs[i]['type'] == 'hook')
				{
					retVal = this.resizeobjs[i]['func']();
					
					if (!retVal) continue;
					
					if (typeof(retVal) == 'object')
					{
						objName = retVal[0];
						parName = retVal[1];
					}
					else
					{
						objName = retVal;
						parName = null;
					}
					
				}
				else if (this.resizeobjs[i]['type'] == 'obj')
				{
					objName = this.resizeobjs[i]['name'];
				}
				
				if (parName) this.fitObj(objName,modes[j],parName);
				else this.fitObj(objName,modes[j]);
			}
		}
	}
	if (window.parent && window.parent._mjDoc && window.parent._mjDoc.childResizeCallback) window.parent._mjDoc.childResizeCallback();
//	debugprint("resized - "+window.location);
	window.onresize=__doResize;
}

/*
stacktrace = function()
{
	var s = "";
	for (var a = arguments.callee; a !=null; a = a.caller) 
	{	
	  s += "->"+this.funcname(a.caller) + "\n";
	  if (a.caller == a) {s+="*"; break;}
	}
	return s;
}

funcname = function(f)
{
	var s = f.toString().match(/function (\w*)/)[1];
	if ((s == null) || (s.length==0)) return "anonymous";
	return s;
}
*/

MajicDoc.prototype.doLoad = function()
{
	//alert("doLoad");
	this.doResize();
}


/* async freeze-wait-and-thaw, adapted from CJ's top.html hold()+resume() */
// get AJAX XML response from strURL and cal fnCallback with the results.
// strHoldMsg is only used IF fnFreeze and fnThaw are null!
// assumes POST, assumes no XML is being sent, just vars already encoded into strURL
// assumes if fnFreeze is a function, so is fnThaw
MajicDoc.prototype.fetchXMLWithFreeze = function(strURL,fnCallback,fnFreeze,fnThaw,strHoldMsg)
{
	this.fetchXMLWithFreezeAndData(strURL,fnCallback,fnFreeze,fnThaw,strHoldMsg,null);
}
MajicDoc.prototype.fetchXMLWithFreezeAndData = function(strURL,fnCallback,fnFreeze,fnThaw,strHoldMsg,strData)
{
	if(typeof(fnCallback)!="function") throw "fetchXMLWithFreeze: fnCallback must be a javascript function object reference.";
	if(typeof(fnFreeze)=="function" && typeof(fnThaw)!="function") throw "fetchXMLWithFreeze: if fnFreeze is a function object reference, fnThaw must also be one";
	
	// provide default behaviour for freeze+thaw functions, which is to create
	// a "coverup" div.
	if(fnFreeze==null)
	{
		fnFreeze = function()
		{
			// coverUp already exists, but is possibly hidden.
			if(document.getElementById('coverUp') && document.getElementById('coverMsg'))
			{
				document.getElementById('coverMsg').innerHTML = '';
				document.getElementById('coverMsg').appendChild(document.createTextNode(strHoldMsg));
				document.getElementById('coverUp').style.display = 'block';
			}
			else
			{
				var coverupdiv = document.createElement("div");
				coverupdiv.id = 'coverUp';
				var strCSS = 'position:absolute; top:0px; left:0px; background-color:black; width:100%; -moz-opacity:0.7;';
				strCSS += 'filter:alpha(opacity=70); vertical-align:middle; text-align:center; font-family:Courier New, Courier, mono;';
				strCSS += 'color:white; font-size:16px; font-weight:bold;';
				coverupdiv.style.cssText = strCSS;
			
				var coverspan = document.createElement("span");
				coverspan.id = 'coverMsg';
				coverspan.appendChild(document.createTextNode(strHoldMsg));
			
				var coverimg = document.createElement("img");
				coverimg.src = this.includePath+'/images/page/hourglass.gif';
				coverimg.align='absmiddle';
			
				coverupdiv.appendChild(coverspan);
				coverupdiv.appendChild(coverimg);
			
				document.body.insertBefore(coverupdiv,document.body.firstChild);
				
				//document.firstChild.appendChild(coverupdiv);
			}
		}

		fnThaw = function()
		{
			_mjDoc.hide('coverUp');
		}
	}
	
	fnFreeze();
	
	// proxy function to be called once asynchronous transaction is finished.
	var fnProxy = function(xml)
	{
		fnThaw();
		fnCallback(xml);
	};
	
	if(strData!=null)
	{
		if(typeof(strData)!="string") throw "fetchXMLWithFreezeAndData(): strData must be a string or null.";
		this.fetchXML(strURL,strData,"POST",true,fnProxy);
	}
	else
	{
		this.fetchXML(strURL,null,"POST",true,fnProxy);
	}
}



MajicDoc.prototype.doFreeze = function(strHoldMsg,posx,posy,width,height,bgcolor,textcolor)
{

			// coverUp already exists, but is possibly hidden.
			if(document.getElementById('coverUp') && document.getElementById('coverMsg'))
			{
				document.getElementById('coverMsg').innerHTML = '';
				document.getElementById('coverMsg').appendChild(document.createTextNode(strHoldMsg));
				
		/*		var coverimg = document.createElement("img");
				coverimg.src = this.includePath+'/images/page/hourglass.gif';
				coverimg.align='absmiddle';
				document.getElementById('coverMsg').appendChild(coverimg); */

				document.getElementById('coverUp').style.display = 'block';
			}
			else
			{
				posy = (typeof(posy)!="undefined")?posy:((this.getWindowHeight()/2)-25);
				posx = (typeof(posx)!="undefined")?posx:((this.getWindowWidth()/2)-200);
				width = (typeof(width)!="undefined")?width:350;
				height = (typeof(height)!="undefined")?height:20;
				
				var coverupdiv = document.createElement("div");
				coverupdiv.id = 'coverUp';
				var strCSS = 'position:absolute; top:'+posy+'px; left:'+posx+'px; background-color:'+(bgcolor?bgcolor:"transparent")+'; width:'+width+'px; height:'+height+'px; padding-top:6px; -moz-opacity:0.45;';
				strCSS += 'filter:alpha(opacity=45); vertical-align:middle; text-align:center; font-family:Courier New, Courier, mono;';
				strCSS += 'color:'+(textcolor?textcolor:"white")+'; font-size:12px; font-weight:bold;';
				coverupdiv.style.cssText = strCSS;
			
				var coverspan = document.createElement("div");
				coverspan.id = 'coverMsg';
				coverspan.appendChild(document.createTextNode(strHoldMsg));

/*
				var coverimg = document.createElement("img");
				coverimg.src = this.includePath+'/images/page/hourglass.gif';
				coverimg.align='absmiddle';
				coverspan.appendChild(coverimg); */

				coverupdiv.appendChild(coverspan);
							
				document.body.insertBefore(coverupdiv,document.body.firstChild);
			}
}


MajicDoc.prototype.doThaw = function()
{
	_mjDoc.hide('coverUp');
}

/* 
---------------------------------------------------------------------------------------------------------
Caret position, input manipulation funcs 
---------------------------------------------------------------------------------------------------------
*/
function CaretPosition()
{
 var start = null;
 var end = null;
}

function getCaretPosition(oField)
{
	var oCaretPos = new CaretPosition();
	if(oField && oField['nodeType'] && (oField.nodeName.toLowerCase()=='input' || oField.nodeName.toLowerCase()=='textarea'))
	{
		// IE
		if(document.selection)
		{
			oField.focus();
			var oSel = document.selection.createRange();
			var selectionLength = oSel.text.length;
			oSel.moveStart ('character', -oField.value.length);
			oCaretPos.start = oSel.text.length - selectionLength;
			oCaretPos.end = oSel.text.length;
		}
		// Firefox
		else if(oField.selectionStart || oField.selectionStart == '0')
		{
			oCaretPos.start = oField.selectionStart;
			oCaretPos.end = oField.selectionEnd;
		}
	}
	return (oCaretPos);
}


function setCaretPosition(oField, iCaretStart, iCaretEnd)
{
	// IE
	if (document.selection)
	{
		oField.focus();
		var oSel = oField.ownerDocument.selection.createRange();
		oSel.moveStart ('character', -oField.value.length);
		oSel.moveEnd ('character', -oField.value.length);
		if(iCaretEnd != null)
		{
			oSel.moveEnd ('character', iCaretEnd);
		}
		else
		{
			oSel.moveEnd ('character', iCaretStart);
		}
		oSel.moveStart ('character', iCaretStart);
		oSel.select();
	}
	// Firefox
	else if(oField.selectionStart || oField.selectionStart == '0')
	{
		oField.selectionStart = iCaretStart;

		if(iCaretEnd != null)
		{
			oField.selectionEnd = iCaretEnd;
		}
		else
		{
			oField.selectionEnd = iCaretStart;
		}
		oField.focus();
	}
}

String.prototype.insertAt = function(at,str)
{
	return this.substring(0,at) + str + this.substring(at);
}

String.prototype.backspaceAt = function(at)
{
	return this.substring(0,at - 1) + this.substring(at); 
}

function backspaceAtCaret(element)
{
	if(element && element.nodeType==1)
	{
		if(element.nodeName.toLowerCase()=="input" || element.nodeName.toLowerCase()=="textarea")
		{
			var beforepos = getCaretPosition(element).start;
			if(beforepos>0)
			{
				element.value = element.value.backspaceAt(beforepos);
				setCaretPosition(element,beforepos-1,beforepos-1);
			}
		}
	}
	
}

function typeAtCaret(element,str)
{
	if(element && element.nodeType==1)
	{
		if(element.nodeName.toLowerCase()=="input" || element.nodeName.toLowerCase()=="textarea")
		{
			var beforepos = getCaretPosition(element).start;
			element.value = element.value.insertAt(beforepos,str);
			setCaretPosition(element,beforepos+str.length,beforepos+str.length);
		}
	}
}
/* 
---------------------------------------------------------------------------------------------------------
*/



/* Static init */
if (!_mjDoc) var _mjDoc = new MajicDoc(document);

function addResizeObj(objName,parentName)
{
	_mjDoc.addResizeObj(objName,parentName);
}

function removeResizeObj(objName,parentName)
{
	_mjDoc.removeResizeObj(objName,parentName);
}

function addResizeHook(func_in)
{
	_mjDoc.addResizeHook(func_in);
}

function addChildResizeCallback(func)
{
	_mjDoc.childResizeCallback = func;
}

function __doLoad()
{
	_mjDoc.doLoad();
}

function __doResize()
{
	_mjDoc.doResize();
}

function debugprint(/* arg,u,ments */)
{
	if(window['_mjIPC'])
		_mjIPC.debugprint(arguments);
//	else
//		window.console.log(arguments);
}
function debugprint_error(/* arg,u,ments */)
{
	if(window['_mjIPC'])
		_mjIPC.debugprint_error(arguments);
//	else
//		window.console.error(arguments);
}
function debugprint_warn(/* arg,u,ments */)
{
	if(window['_mjIPC'])
		_mjIPC.debugprint_warn(arguments);
//	else
//		window.console.warn(arguments);
}
function debugprint_info(/* arg,u,ments */)
{
	if(window['_mjIPC'])
		_mjIPC.debugprint_info(arguments);
//	else
//		window.console.info(arguments);
}

// usage $('bob') to return element with id=bob
function $(id){return document.getElementById(id);};

window.onload = __doLoad;

/**
* Function : dump()
* Arguments: The data - array,hash(associative array),object
*    The level - OPTIONAL
* Returns  : The textual representation of the array.
* This function was inspired by the print_r function of PHP.
* This will accept some data as the argument and return a
* text that will be a more readable version of the
* array/hash/object that is given.
*/
function array_dump(arr,level) {
	var dumped_text = "";
	if(!level) level = 0;
	
	//The padding given at the beginning of the line.
	var level_padding = "";
	for(var j=0;j<level+1;j++) level_padding += "    ";
	
	if(typeof(arr) == 'object') { //Array/Hashes/Objects 
		for(var item in arr) {
			var value = arr[item];
			
			if(typeof(value) == 'object') { //If it is an array,
				dumped_text += level_padding + "'" + item + "' ...\n";
				dumped_text += dump(value,level+1);
			} else {
				dumped_text += level_padding + "'" + item + "' => \"" + value + "\"\n";
			}
		}
	} else { //Stings/Chars/Numbers etc.
		dumped_text = "===>"+arr+"<===("+typeof(arr)+")";
	}
	return dumped_text;
}

