/*
 * Copyright 2003-2004, Peter Rowntree. All Rights Reserved.
 * http://www.hdyn.com/wr/common/contact.php?addr=pr
 * no longer needs /wr/common/common.js
 */
 
var g_msHTTPStr=null;
var g_msDOMStr=null;
var g_requestArray=new Array();
var g_XMLRequestTimer=null;
var g_timeout_ms=0;
var g_XMLErrorReporter=null;

//must be called at least once to start timer
function setXMLTimeout(ms)
{
   g_timeout_ms=ms;
   doXMLRequestTimerTask();
}

function setXMLErrorReporter(errProc)
{
   g_XMLErrorReporter=errProc;
}

function reportXMLError(err)
{
   if(g_XMLErrorReporter == null)
      alert(err);
   else
      g_XMLErrorReporter(err);
}

//PR~ 041125 broke out reqDone
function doRequestTimeouts()
{
   var now=new Date().getTime();
   for(var i=0; i < g_requestArray.length; ++i)
   {
      if(reqDone(g_requestArray[i]))
         g_requestArray.splice(i,1);
      --i;
   }
}

function reqDone(req)
{
   if(req.timeoutMS == 'undefined' || req.timeoutMS > now)
      return false;
   if(req.timeoutMS != 0)   //0 => done
      req.doTimeout();
   return true;
}

function doXMLRequestTimerTask()
{
   if(g_XMLRequestTimer != null)
   {
      clearTimeout(g_XMLRequestTimer);
      g_XMLRequestTimer=null;
   }
   doRequestTimeouts();
   if(g_timeout_ms > 0)
      g_XMLRequestTimer=setTimeout("doXMLRequestTimerTask()",g_timeout_ms);
}


//IE doesn't (as of 6) correctly set srcElement (it's own bullshit property!),
//so here's a solution. doneProc may also be an object with a 'done' method.
function XMLRequest(req,doneProc,timeoutProc)
{
   if(timeoutProc != null && g_timeout_ms > 0)
   {
      this.timeoutMS=new Date().getTime()+g_timeout_ms;
      if(g_XMLRequestTimer != null)
         g_requestArray.push(this);
   }
   this.doTimeout=function()
   {
      if(timeoutProc != null)
         timeoutProc(req);
   }
   this.stateChange=function()
   {
      switch(req.readyState)
      {
         case 4:
            if(doneProc == null)
		      	return;
		      if(typeof doneProc == 'function')
		         doneProc(req);
		      else
		      	doneProc.done(req);
            break;
      }
   }
}

//endProc only applies to IE, since mozilla uses DOMParser, not XMLDoc.
//load from file can be done async in mozilla
function loadXML(xmlStr,endProc)
{
   var xmlDoc=null;
   var err=null;
   if(typeof document.implementation.createDocument != "undefined")  //mozilla
   {
      if(typeof DOMParser == "undefined")
         return safariSucks(xmlStr);
      var parser=new DOMParser();
      try
      {
         xmlDoc=parser.parseFromString(xmlStr,"text/xml"); //str,contentType
         err=getError(xmlDoc,"parsererror");
         if(err != null)
         {
            reportXMLError("XML parse error: " + err +"\nXML: "+ xmlStr);
            return null;
         }
      }
      catch(e)
      {
         reportXMLError("XML parse error: " + e +"\nXML: "+ xmlStr);
         return null;
      }
   }
   else //IE
   {
      xmlDoc=createXMLDoc(endProc);
      xmlDoc.loadXML(xmlStr);
      if(xmlDoc.parseError.errorCode != 0)
      {
         err = xmlDoc.parseError;
         reportXMLError("XML parse error: " + err.reason +"\nXML: "+ xmlStr);
         return null;
      }
   }
   return xmlDoc;
}

function safariSucks(xmlStr)
{
   var doc=document.createElement('html');
   doc.innerHTML=xmlStr;
   return doc;
}

function getError(xmlDoc,errNodeName)
{
   var err=xmlDoc.getElementsByTagName(errNodeName);
   if(err == null || err[0] == null || err[0].firstChild == null)
      return null;
   return err[0].firstChild.nodeValue;
}

function detectMSObjects(arr,errStr)
{ 
   var ob;
   for(var i=0; i < arr.length; i++)
   {
      try
      {
         ob=new ActiveXObject(arr[i]);
         return arr[i];
      }
      catch(e)
      { }
   }
   if(errStr != null)
      reportXMLError(errStr);
   return null;
}

function buildMSHTTPStr()
{
   if(g_msHTTPStr != null)
      return true;
   var arr=new Array("Msxml2.XMLHTTP","Microsoft.XMLHTTP");
   g_msHTTPStr=detectMSObjects(arr,"Unable to create an XMLHTTP request object");
   return g_msHTTPStr != null;
}

function buildMSDOMStr()
{
   if(g_msDOMStr != null)
      return true;
   var arr=new Array("MSXML4.DOMDocument", 
      "MSXML3.DOMDocument","MSXML2.DOMDocument", 
      "MSXML.DOMDocument","Microsoft.XMLDOM");
   g_msDOMStr=detectMSObjects(arr,"Unable to create an XMLDOM object");
   return g_msDOMStr != null;
}

function createRequest(endProc,timeoutProc)
{
   var async=endProc != null;
   var req=null;
   var ro=null;
   if(typeof XMLHttpRequest != "undefined")
   {
      req=new XMLHttpRequest();
      if(async)
      {
         ro=new XMLRequest(req,endProc,timeoutProc);
      	req.onreadystatechange=ro.stateChange;
      }
      return req;
   }
   if(typeof window.ActiveXObject == 'undefined')
      return null;
   if(g_msHTTPStr == null && !buildMSHTTPStr())
      return null;
   req=new ActiveXObject(g_msHTTPStr);
   if(async)
   {
      ro = new XMLRequest(req,endProc,timeoutProc);
      req.onreadystatechange=ro.stateChange;
   }
   return req;
}

function createXMLDoc(endProc)
{
   var async=endProc != null;
   var xmlDoc;
   if(typeof document.implementation.createDocument != "undefined")
   {
      xmlDoc=document.implementation.createDocument("", "", null);
      if(async)
      {
         ro=new XMLRequest(xmlDoc,endProc,null);
      	xmlDoc.onreadystatechange=ro.stateChange;
      }
      return xmlDoc;
   }
   if(typeof window.ActiveXObject == "undefined")
      return null;
   if(g_msDOMStr == null && !buildMSDOMStr())
      return null;
   xmlDoc=new ActiveXObject(g_msDOMStr);
   if(async)
   {
      xmlDoc.async=async;
      ro = new XMLRequest(xmlDoc,endProc,null);
      xmlDoc.onreadystatechange=ro.stateChange;
   }
   return xmlDoc;
}

function sendXML(xml,uri,endProc,timeoutProc)
{
   var method=(arguments.length < 5 ? "POST" : arguments[4]);
   var user=(arguments.length < 6 ? null : arguments[5]);
   var pass=(arguments.length < 7 ? null : arguments[6]);
   var req=null;
   try
   {
      req=createRequest(endProc,timeoutProc);
      if(req == null)
         return null;
      var async=endProc != null;
      req.open(method,uri,async,user,pass);  // method,url,async,user,password 
      req.setRequestHeader("Content-Type", "text/xml; charset=utf-8");
      //req.setRequestHeader("Connection", "Keep-Alive");
      //req.setRequestHeader("Connection", "close");  //causes TIME_WAIT
      //req.setRequestHeader("Content-Length", xml.length); //--old mozilla makes this incorrectly; gets 'Bad Request'
      req.send(xml);
   }
   catch(e)
   {
      reportXMLError("sendXML ("+method+") error: " + e +"\nXML: "+ xml);
      return null;
   }
   return req; //usually only useful if !async
}

function entitySubstitute(s)
{
   s=s.replace(/&/g,"&amp;");
   s=s.replace(/</g,"&lt;");
   s=s.replace(/>/g,"&gt;");
   s=s.replace(/"/g,"&quot;");
   s=s.replace(/(\r\n?|\n\r?)/g,"<br/>");
   return s.replace(/  /g,"&#160;&#160;");
}

//doesn't return subnodes, only 1st child value!
function iElement(tagName,i,nodeList,err)
{
   if(typeof err == "undefined")
      err=null;
   return iNodeFirstChildValue(nodeList.getElementsByTagName(tagName),i,err);
}

//n is a NodeList
function iNodeFirstChildValue(n,i,err)
{
   if(n == null)
      return err;
   if(n.length <= i)
      return err;
   n=n.item(i);
   if(n == null)
      return err;
   n=n.firstChild;
   if(n == null)
      return err;
   return n.nodeValue;
}

function getBodyAsStr(xmlDoc)
{  
   if(xmlDoc == null)
      return null;
   var body=iElement("body",0,xmlDoc);
   if(body == null)
      return null;
   return body;
}

//returns 1st
function getChildElementByAttr(xmlDoc,tagName,attr,attrVal)
{  
   var nds=xmlDoc.getElementsByTagName(tagName);
   if(nds == null)
      return null;
   var len=nds.length;
   for(var i=0; i<len; ++i)
   {
      if(typeof nds.item(i).getAttribute != "undefined" 
      	&& nds.item(i).getAttribute(attr) == attrVal)
         return nds.item(i);
   }
   return null;
}

function ithNode(node,i,tagName)
{  
   var nds=node.getElementsByTagName(tagName);
   if(nds == null || nds.length <= i)
      return null;
   return nds.item(i);
}

function getIndChildByClassName(node,tagName,className,idx)
{  
   var nds=node.getElementsByTagName(tagName);
   if(nds == null)
      return null;
   var len=nds.length;
   for(var i=0; i<len; ++i)
   {
      if(nds.item(i).className == className && idx-- == 0)
         return nds.item(i);
   }
   return null;
}
   
function buildElement(tag,attrs,contents)
{
   return elementOpen(tag,attrs)+contents+elementClose(tag);
}

function elementOpen(tag,attrs)
{
   var s="<"+tag;
   if(attrs != null)
      s+=" "+attrs;
   return s+">";
} 

function elementClose(tag)
{
   return "</"+tag+">";
} 

   