include.js

//Gets the appropriate XMLHttpRequest object, depending on the browser.
//If bXml is set and we're using the Firefox type of object, 
//we'll set it to expect XML.
function getHttpObject(bXML)
{
       var httpobject;

       if (window.XMLHttpRequest) 
        { 
         //Firefox   
         httpobject = new XMLHttpRequest();

         if (bXML && httpobject.overrideMimeType) 
         {
            httpobject.overrideMimeType('text/xml');
         }
      } 
      else if (window.ActiveXObject) 
      {
         //Internet Explorer
         try {
            httpobject = new ActiveXObject("Msxml2.XMLHTTP");
         } catch (e) {
            try {
               httpobject = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {}
         }
      }
      
      return httpobject;
}

//Three HTTP request objects

//This is generally used for fetching XML documents at timed intervals
var httpXMLTimer = getHttpObject(true);

//This one is used to respond to user commands
var httpXMLUser = getHttpObject(true);

//And this is used, rarely, when we need HTML, not XML
var httpHTML = getHttpObject(false);

//Adds a parameter to a url and returns the result
function addURLParameter(url, paramName, paramValue)
{
    //Find the question mark in the URL, which
    //signifies the start of the parameters. 
    var iQuestionMarkIndex = url.indexOf('?');

    //Let's also find the Hash symbol. If it's there
    //(unlikely) it will signify the start of the fragment
    var iHashIndex = url.indexOf('#');

    var strInsert = paramName + "=" + paramValue;
      
    //If there was a question mark
    if (iQuestionMarkIndex >= 0)
    {
        //Is there a fragment?
        if (iHashIndex >= 0)
        {
            //Yes. Add the parameters before the hash symbol.
            url =  url.replace("#", "&" + strInsert + "#");
        }
        else
        {
            //No. Just add the parameters on the end.
            url += "&" + strInsert;
        }
    }
    else
    {
        //There are presently no parameters. Let's insert some.
        //Is there a fragment?
        if (iHashIndex >= 0)
        {
            //Yes. Add the parameters before the hash symbol.
            url =  url.replace("#", "?" + strInsert + "#");
        }
        else
        {
            //No. Just add the parameters on the end.
            url += "?" + strInsert;
        }
    }

    return url;
}

//Two strings which, if we find them
//in the output from a PHP file, mean
//that an error is enclosed
var strErrorStart = "<gwerror>";
var strErrorEnd = "</gwerror>";

//A generic method to do an Http request. As parameters, it takes
//an Http object (created with getHttpObject); a callback function;
//the url to which the request should be sent (usually a PHP file);
//and the method, which should either be "GET" or "POST"
   function doHttpRequest(http, callback, urlTarget, method)
   {
        if (method == "GET")
        {
            //Internet Explorer has a habit of caching Get requests.
            //This is one of the workarounds: you add a "hash" parameter
            //that changes every time
            urlTarget = addURLParameter(urlTarget, "btihash", Math.random());
        }

        //Our callback function will need to check the readystate and the status
        //of the http request object. For convenience, we wrap the "callback"
        //function in if statements which do this check.
        var callbackEnclosed = function ()
                   {
                       if (http.readyState == 4) 
                       {
                           if(http.status==200) 
                           {
                              //TODO: What if it's responseXML?
                              var strResponse = http.responseText;

                              var iIndexError = strResponse.indexOf(strErrorStart);
                              var iIndexEndError = strResponse.indexOf(strErrorEnd);

                              if (iIndexError > -1 && iIndexEndError > -1)
                              {
                                  alert (strResponse.substring(iIndexError + strErrorStart.length, iIndexEndError));
                              }
                              else
                              {
                                  callback();
                              }
                           }
                       }
                   };

        //And do the Http request
        http.open(method, urlTarget, true);
        http.onreadystatechange = callbackEnclosed;
        http.send(null);
   }

//Some edit fields want to handle the "return" key being pressed.
//They will call this function and provide a callback
//function which handles the "return" key however they want.
function handleKeyPress(e, callback)
{
        var keycode;
        if (window.event)
        {
            keycode = window.event.keyCode;
        }
        else if (e)
        {
            keycode = e.which;
        }
        else return true;

        if (keycode == 13)
        {
           callback();
        }
}

//And this does the same thing but
//passes two parameters. Since the code
//is so short, I won't combine this with the
//function above.
function handleKeyPressWithParams(e, callback, param1, param2)
{
        var keycode;
        if (window.event)
        {
            keycode = window.event.keyCode;
        }
        else if (e)
        {
            keycode = e.which;
        }
        else return true;

        if (keycode == 13)
        {
           callback(param1, param2);
        }
}

//TODO: Are these used?
var strOtherUserName;

function getOtherUserName()
{
    return strOtherUserName;
}

function setOtherUserName(strSet)
{
    strOtherUserName = strSet;
}

//This function fetches the text contained in an XML node
   function getTextFromNode(node)
   {
       if (node)
       {
           if (node.firstChild)
           {
               return node.firstChild.data;
           }
      }

      return "";
   }

   //This function finds a named child of an XML node and returns the text therein.
   function getTextFromChildNode(node, childname)
   {
     if (node)
     {
         var collChildren = node.getElementsByTagName(childname);

         if (collChildren.length > 0)
         {
            var nodeChild = collChildren.item(0);

            return getTextFromNode(nodeChild);
         }
     }

     //TODO: Is this return value checked?
     return -1;
   }

//An empty function, used as a callback
function emptyFunction()
{
}

   //If the current node is not an element node,
   //this function moves on to the next sibling
   //which is an element. If there's no such sibling,
   //the function will fail.
   function getNextElementNode(node)
   {
       while (node.nodeType != 1)
       {
           node = node.nextSibling;
       }
 
       return node;
   }

//This function parses a XML file, calling a callback
//function in the particular file to deal with the individual nodes.
//TODO: Get rid of the individual parseXML functions
   function parseXMLWithCallback(xml, callback) 
   {
            //Get the root node (skipping past whitespace until we get to it, if necessary)

            var nodeRoot = xml.firstChild;

            nodeRoot = getNextElementNode(nodeRoot);

            if (nodeRoot != undefined)
            {
                  var nodeCurrent = nodeRoot.firstChild;
           
                  nodeCurrent = getNextElementNode(nodeCurrent);

                  while (nodeCurrent)
                  {
                      callback(nodeCurrent);
                      nodeCurrent = nodeCurrent.nextSibling;
                  }
            }
   }

   function emptyTable(tablename) 
   {
       var tbl = document.getElementById(tablename);

       var lastRow = tbl.rows.length - 1;

       while (lastRow > -1)
       {
           tbl.deleteRow(lastRow);
           lastRow --;
       }
   }