/**************************************************
 ** Global Variables                             **
 **************************************************/

var keyLoaded = false;
var helpLoaded = "";
var requestMap = new Map();			// XML Requests for the whole site.
var viewLog = false;

/**************************************************
 ** XmlRequest Functions                         **
 **************************************************/

function createXMLHttpRequest() { 
  if (navigator.appName == "Microsoft Internet Explorer")
    request = new ActiveXObject("Microsoft.XMLHTTP");
  else
    var request = new XMLHttpRequest();
  
  return request;
}  // createXMLHttpRequest  

/**************************************************
 ** Color Functions                              **
 **************************************************/

/**
 * rgbConvert
 *
 * Convert Color RGB to normal hex.
 *
 */
function rgbConvert(str) {
   str = str.replace(/rgb\(|\)/g, "").split(",");
   str[0] = parseInt(str[0], 10).toString(16).toUpperCase();
   str[1] = parseInt(str[1], 10).toString(16).toUpperCase();
   str[2] = parseInt(str[2], 10).toString(16).toUpperCase();
   str[0] = (str[0].length == 1) ? '0' + str[0] : str[0];
   str[1] = (str[1].length == 1) ? '0' + str[1] : str[1];
   str[2] = (str[2].length == 1) ? '0' + str[2] : str[2];
   return ('#' + str.join(""));  
} // rgbConvert

/**************************************************
 ** Table Functions                              **
 **************************************************/

/**
 * maxScroll
 * 
 * Set scroll bar to lowest position.
 * 
 */
function maxScroll(id) {
  var el = document.getElementById(id);
  
  if (el == null)
    return;
    
  var h = el.scrollHeight; // height of element scroll
  var y = el.scrollTop; // vertical scroll offset from top (of scrollHeight)
  var c = el.clientHeight; // scroll bar height
  
  var scrollBottom = h - (y + c); // offset of scroll from bottom
  el.scrollTop += scrollBottom;
} // maxScroll

/**************************************************
 ** Cookie Functions                             **
 **************************************************/

/**
 *
 * Save a Cookie
 *
 * Save a cookie into the browser based on the
 * id of the field to be saved and the cookie
 * name.
 *  
 */
function setCookie(id, cookieName) { 
  var myField = document.getElementById(id);
      
  if (myField == null)
    return false;
  
  try {
    createCookie(cookieName, escape(myField.value), 365);
    return true;
  } // try
  catch(err) {  
  } // catch
   
  return true;
} // setCookie

/**
 * createCookie
 *
 * Create a cookie in users browser.
 *
 */
function createCookie(name, value, days) {
  if (days) {
    var date = new Date();
    date.setTime(date.getTime()+(days*24*60*60*1000));
    var expires = "; expires="+date.toGMTString();
  } // if
  
  else var expires = "";
  document.cookie = name + "=" + value + expires + "; path=/";
} // createCookie
 
/**   
 * readCookie
 *
 * Read a cookie from users browser.
 * 
 */
function readCookie(name) {
  var ca = document.cookie.split(';');
  var nameEQ = name + "=";
  for(var i=0; i < ca.length; i++) {
    var c = ca[i];
    while (c.charAt(0)==' ') c = c.substring(1, c.length); //delete spaces
    if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length, c.length);
  } // for
    
  return "";
} // readCookie

/**
 * eraseCookie   
 *    
 * Erase a cookie from users browser.
 * 
 */
function eraseCookie(name) {
  createCookie(name, "", -1);
} // eraseCookie

/**************************************************
 ** Form Functions                               **
 **************************************************/

/**
 * isChecked
 *  
 * See if a field is checked.
 *
 */
function isChecked(id) {  
  var myField = document.getElementById(id);
 
  if (myField == null)
    return false;
  
  if (myField.checked == true)
    return true;
  
  return false;
} // function

/**
 * unCheck
 * 
 * Uncheck a field.
 * 
 */
function unCheck(id) {
  var myField = document.getElementById(id);
  
  if (myField == null)
    return false;
    
  try {
    myField.checked = false;
  }
  catch(e) {
    return false;
  } // catch
  
  return true;
} // function 

/**
 * ClearField
 *
 * Select all text on click.
 *
 */
function ClearField(id) {
  clearMe = document.getElementById(id);
 
  if (clearMe == null)
    return;

  clearMe.value = "";
} // ClearField

/**
 * SelectAll
 *
 * Select all text on click.
 *
 */
function SelectAll(id) {
  myElement = document.getElementById(id);
  
  if (myElement == null)
    return;
   
  myElement.focus();
  myElement.select();
} // SelectAll

/**************************************************
 ** Window Functions                             **
 **************************************************/

/**
 * showWindow
 *
 * Select all text on click.
 *
 */
function showWindow(id) {
  pPop = document.getElementById(id);
  
  if (pPop == null)
    return;  
  
  pPop.style.display = "block";
 
} // showWindow

/**
 * isHidden
 * 
 * Returns true if the window is hidden.
 * 
 */
function isHidden(id) {
  var myOverlay = document.getElementById(id);
  
  if (myOverlay == null)
    return false;
    
  if (myOverlay.style.display == "none")
    return true;

  return false;
} // isHidden  

/**
 * togWindow
 * 
 * Toggles a windows display.
 * 
 */
function togWindow(id) {
  var id = document.getElementById(id);
  
  if (id == null)
    return;

  if (isHidden(id))
    showWindow(id);
  else
    hideWindow(id);

  return;
} // togWindow

/**
 * hideWindow
 * 
 * Hide track window.
 * 
 */
function hideWindow(id) {
  pPop = document.getElementById(id);
  
  if (pPop == null)
    return;
    
  pPop.style.display = "none";
  
} // hideWindow

/**************************************************
 ** Time Functions                               **
 **************************************************/

/**
 * getUnixTime
 * 
 * Return the current UNIX timestamp.
 * 
 */
function getUnixTime() {
  var current_time = new Date();
  
  return parseInt(current_time.getTime() / 1000);
} // getUnixTime


/**************************************************
 ** Element Functions                            **
 **************************************************/

/**
 *
 * Change Element By Id
 * 
 * Try and change an element's innerHTML contents
 * safely by id.
 * 
 */
function changeById(id, msg) {
  var el = document.getElementById(id);

  if (el == null)
    return true;
  
  try {
    el.innerHTML = msg;
    return true;
  } // try
  catch(err) {  
  } // catch
  
  return true; 
} // changeById

/**
 *
 * Change Zindex By Id
 * 
 * Try and change an element's Zindex
 * safely by id.
 * 
 */
function changeZindexById(id, zindex) {
  var el = document.getElementById(id);

  if (el == null)
    return true;
  
  try {
    el.style.zIndex = zindex;
    return true;
  } // try
  catch(err) {  
  } // catch
  
  return true; 
} // changeZindexById

/**
 *
 * Change Background Color By Id
 * 
 * Try and change an element's background color
 * safely by id.
 * 
 */
function changeBackgroundColorById(id, color) {
  var el = document.getElementById(id);

  if (el == null)
    return true;
  
  try {
    el.style.backgroundColor = color;
    return true;
  } // try
  catch(err) {  
  } // catch
  
  return true; 
} // changeBackgroundColorById

/**
 *
 * Change Color By Id
 * 
 * Try and change an element's color
 * safely by id.
 * 
 */
function changeColorById(id, color) {
  var el = document.getElementById(id);

  if (el == null)
    return true;
  
  try {
    el.style.color = color;
    return true;
  } // try
  catch(err) {  
  } // catch
  
  return true; 
} // changeColorById

/**
 *
 * Change field By Id
 * 
 * Try and change an element's innerHTML contents
 * safely by id.
 * 
 */
function changeFieldById(id, msg) {
  var el = document.getElementById(id);

  if (el == null)
    return;
  
  try {
    el.value = msg;
    return;
  } // try
  catch(err) {  
  } // catch
  
  return; 
} // changeFieldById

/* ----------------------------------------------------------------------------
 * Name: changeFocusById
 * Changes focus to a given element.
 * Parameters:
 *   none
 * Returns: n/a
 */
function changeFocusById(id) {
  var el = document.getElementById(id);

  if (el == null)
    return;
  
  try {
    el.focus();
    return;
  } // try
  catch(err) {  
  } // catch
  
  return; 
} // changeFocusById

function changeStarsById(id, limit, img) {
  for(var i = 1; i <= limit; i++) {
    changeImageById(id + i, img);
  } // for
} // changeStarsById

function clearStarsById(id, limit, on, off) {
  for(var i = 1; i <= 5; i++) {
    if (i <= limit)
      changeImageById(id + i, on);
    else
      changeImageById(id + i, off);
  } // for
} // clearStarsById

/**
 *
 * Change image By Id
 * 
 * Try and change an element's image contents
 * safely by id.
 * 
 */
function changeImageById(id, msg) {
  var el = document.getElementById(id);

  if (el == null)
    return;
  
  try {
    el.src = msg;
    return;
  } // try
  catch(err) {  
  } // catch
  
  return; 
} // changeImageById

/**
 *
 * Change On Click By Id
 * 
 * Try and change an element's innerHTML contents
 * safely by id.
 * 
 */
function changeOnClickById(id, msg) {
  var el = document.getElementById(id);

  if (el == null)
    return;
  
  try {
    el.onclick = new Function(msg);
    return;
  } // try
  catch(err) {  
  } // catch
  
  return; 
} // changeOnClickById

/**
 * 
 * Append Element By Id
 * 
 * Try and change an element's innerHTML contents
 * safely by id.
 * 
 */
function appendById(id, msg) {
  var el = document.getElementById(id);
  
  if (el == null)
    return true; 
    
  try {
    el.innerHTML += msg;
    return true;
  } // try
  catch(err) {
  } // catch  
  
  return true;
} // appendById

/**************************************************
 ** Math Functions                               **
 **************************************************/

/** 
 * roundFloat
 *
 * Rounds a floating point number.
 *
 */
function roundFloat(number, decimal) {
  return Math.round(number * Math.pow(10, decimal)) / Math.pow(10, decimal);
} // roundFloat

/**************************************************
 ** String Functions                             **
 **************************************************/

function addslashes(str) {
  str=str.replace(/\'/g,'\\\'');
  str=str.replace(/\"/g,'\\"'); 
  str=str.replace(/\\/g,'\\\\');
  str=str.replace(/\0/g,'\\0'); 
  str=str.replace(/\n/g,'\\n'); 
  
  return str;
}
 
function stripslashes(str) {
  str=str.replace(/\\'/g,'\'');
  str=str.replace(/\\"/g,'"'); 
  str=str.replace(/\\\\/g,'\\');
  str=str.replace(/\\0/g,'\0'); 
  
  return str;
}

/**************************************************
 ** Table Functions                              **
 **************************************************/

function cellStruct() {
  this.text = '';
  this.css_class = '';
  this.colspan = 1;
} // cellStruct

function addRow(tableID, cellClass, tableContent) {
  // Get a reference to the table
  var tableRef = document.getElementById(tableID);
  
  // Insert a row in the table at row index 0
  var newRow   = tableRef.insertRow(-1);
  
  // Insert a cell in the row at index 0
  var newCell  = newRow.insertCell(0);  
  
  // Append a text node to the cell
  var newText  = document.createTextNode(tableContent)
  newCell.innerHTML = tableContent;
  newCell.className = cellClass;   
  newCell.colSpan = 2;
  
} // addRow

function addRow2(tableID, tableArray) {
  // Get a reference to the table
  var tableRef = document.getElementById(tableID);
  
  if (tableRef == null)
    return;
    
  // Insert a row in the table at row index 0
  var newRow   = tableRef.insertRow(-1);
  
  for(var i=0; i < tableArray.length; i++) {
  
    // Insert a cell in the row at index 0
    var newCell  = newRow.insertCell(0);  
    
    // Append a text node to the cell
    // var newText  = document.createTextNode(tableContent)
    newCell.innerHTML = tableArray[i].text;
    newCell.className = tableArray[i].css_class;
    newCell.colSpan = tableArray[i].colspan;
    newCell.id = tableArray[i].id;
  } // for
  
  return;
} // addRow

function pushRow(tableID, tableArray) {
  // Get a reference to the table
  var tableRef = document.getElementById(tableID);
  
  if (tableRef == null)
    return false;
    
  // Insert a row in the table at row index 0
  var newRow   = tableRef.insertRow(0);
  
  for(var i=0; i < tableArray.length; i++) {
  
    // Insert a cell in the row at index 0
    var newCell  = newRow.insertCell(0);  
    
    // Append a text node to the cell
    // var newText  = document.createTextNode(tableContent)
    newCell.innerHTML = tableArray[i].text;
    newCell.className = tableArray[i].css_class;
    newCell.colSpan = tableArray[i].colspan;
    newCell.id = tableArray[i].id;
  } // for
  
  return;
} // addRow

function limitRows(tableID, rowLimit) {
  // Get a reference to the table
  var tableRef = document.getElementById(tableID);
  
  var tableRows = tableRef.rows.length - 1;
  if (tableRows > rowLimit)
    while((tableRef.rows.length - 1) > rowLimit)
      tableRef.deleteRow(0);
      
} // limitRows

function limitRowsEnd(tableID, rowLimit) {
  // Get a reference to the table
  var tableRef = document.getElementById(tableID);
  
  if (tableRef == null)
    return false;
    
  var tableRows = tableRef.rows.length - 1;
  if (tableRows > rowLimit)
    while((tableRef.rows.length - 1) > rowLimit)
      tableRef.deleteRow((tableRef.rows.length - 1));
      
} // limitRowsEnd

function clearRows(tableID) {
  // Get a reference to the table
  var tableRef = document.getElementById(tableID);
  
  if (tableRef == null)
    return false;
    
  while(tableRef.rows.length != 0)
    tableRef.deleteRow(0);
    
} // clearRows

/**************************************************
 ** Help Functions                               **
 **************************************************/

/**
 * toggleHELP
 *
 * Toggle tools functionality.
 *
 */
function toggleHELP() {

  if (isHidden('helpOverlay')) {
    showWindow('helpOverlay');
    windowControl('helpverlay');
    showControl('controlHELP', 'on');
    Drag.init(document.getElementById("helpHandle"), document.getElementById("helpOverlay"), null, null, null, null, false);
  } // if
  else {
    showControl('controlHELP', 'off');
    hideWindow('helpOverlay');
  } // else

  return;
} // toggleHELP

/**     
 * loadHelp
 *
 * Load's a help article into the help window.
 *
 */
function loadHelp(q) {
  var request = createXMLHttpRequest();
  var re = new RegExp("^(articles|random)[:]");
  var site;

  if (isHidden('helpOverlay'))
    toggleHELP();

  scroll(0,0);

  //if (q == helpLoaded) {
  // changeById('helpCached', '(cached)');
  // return;
  //} // if

  changeById('helpCached', '(loaded)');
  changeById('helpTitle', 'LOADING...');
  changeById('helpContainer', '<img class="loadingIcon" src="http://www.openaprs.net/images/updating.gif" width="24" height="24" />');

  // Change help topics button if this is an article index
  if (q.match(re)) {
    site = q.split(':');
    if (site[1] != 'tips')
      changeOnClickById('Help:Button:Index', "loadHelp('articles:" + site[1] + "')");
  } // if

  var queryString = "/ajax/help/view.php?q="+q;

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      var retData = new Array();
      xmlArray("/openaprs/help/article", xmlDoc, retData);
      for (i=0; i < retData.length; i++) {

        changeById('helpTitle', retData[i]["title"]);
        changeById('helpContainer', retData[i]["cdata"]);
        if (retData[i]["id"] != "articles") {
          var helpful = retData[i]["helpful"].split(',');

          appendById('helpContainer', '<br /><br /><div><b>Article last updated: </b>'
                     + retData[i]["updated"]
                     + ' ago by '
                     + retData[i]["by"]
                     + '<br /><b>Popularity: </b>'
                     + retData[i]["hits"]
                     + '+'
                     + '<br /><br /><o>So far, '
                     + helpful[0]
                     + ' users have found this helpful and '
                     + helpful[1]
                     + ' have not.</i>'
                     + '</div>');
        } // if

        helpLoaded = retData[i]["id"];
      } // for
    } // if

  } // function()

  request.send(null);
} // loadHelp

/**     
 * wasHelpful
 *
 * Load's a help article into the help window.
 *
 */
function wasHelpful(q, isHelpful) {
  var request = createXMLHttpRequest();

  if (isHelpful == true)
    var h = "yes";
  else
    var h = "no";

  changeById('wasHelpful', "Saving your response...");

  var queryString = "/ajax/help/helpful.php?q="+q+"&h="+h;

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      var retData = new Array();
      xmlArray("/openaprs/reply", xmlDoc, retData);
      for (i=0; i < retData.length; i++) {
        changeById('wasHelpful', retData[i]["response"]);
      } // for
    } // if

  } // function()

  request.send(null);
} // wasHelpful

/**     
 * wasRated
 *
 * Load's a help article into the help window.
 *
 */
function wasRated(q, myRating) {
  var request = createXMLHttpRequest();

  changeById('wasRating', "Saving your response...");

  var queryString = "/ajax/help/rate.php?q="+q+"&r="+myRating;

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      var retData = new Array();
      xmlArray("/openaprs/reply", xmlDoc, retData);
      for (i=0; i < retData.length; i++) {
        changeById('wasRating', retData[i]["response"]);
      } // for
    } // if

  } // function()

  request.send(null);
} // wasRated

/**     
 * whyHelpful
 *
 * Load's a help article into the help window.
 *
 */
function whyHelpful(q) {
  var request = createXMLHttpRequest();
  var why = document.getElementById('oaprs_form_help_why');

  if (why == null || why.value.length < 1) {
    changeById('whyStatus', 'Error, please type in a comment first.');
    return;
  } // if

  changeById('wasHelpful', "Saving your response...");

  var queryString = "/ajax/help/why.php?q="+q+"&y="+escape(why.value);

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      var retData = new Array();
      xmlArray("/openaprs/reply", xmlDoc, retData);
      for (i=0; i < retData.length; i++) {
        changeById('wasHelpful', retData[i]["response"]);
      } // for
    } // if

  } // function()

  request.send(null);
} // whyHelpful

/**     
 * doContact
 *
 * Load's a help article into the help window.
 *
 */
function doContact() {
  var request = createXMLHttpRequest();
  var n = document.getElementById("openaprs_form_contact_name");
  var e = document.getElementById("openaprs_form_contact_email");
  var s = document.getElementById("openaprs_form_contact_subject");
  var m = document.getElementById("openaprs_form_contact_message");

  if (e == null || n == null || m == null
      || s == null)
    return;

  // reset each fields error message span
  changeById('errName', '');
  changeById('errEmail', '');
  changeById('errSubject', '');
  changeById('errMessage', '');

  if (n.value.length < 1) {
    changeById('errName', '<-- Please give me your name.');
    changeById('statusSignup', "There was an error processing your request, see the fields with red error messages next to them to correct the problem.");
    return;
  } // if

  if (e.value.length < 1) {
    changeById('errEmail', '<-- Please give me an email address so I can respond to you.');
    changeById('statusSignup', "There was an error processing your request, see the fields with red error messages next to them to correct the problem.");
    return;
  } // if

  if (m.value.length < 1) {
    changeById('errMessage', '&nbsp;^-- You have not typed in a message yet.');
    changeById('statusSignup', "There was an error processing your request, see the fields with red error messages next to them to correct the problem.");
    return;
  } // if

  changeById('statusSignup', "Attempting to send your message...");
  disableField('openaprs_form_contact_submit');

  var queryString = "/ajax/contact/do.php?n="
                    + encodeURIComponent(n.value)
                    + "&e="
                    + encodeURIComponent(e.value)
                    + "&s="
                    + encodeURIComponent(s.value)
                    + "&m="
                    + encodeURIComponent(m.value);

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      var retData = new Array();
      xmlArray("/openaprs/signup", xmlDoc, retData);
      for (i=0; i < retData.length; i++) {
        if (retData[i]["done"] == "yes")
          changeById('helpContainer', retData[i]["response"]);
        else {
          changeById('statusSignup', "There was an error processing your request, see the fields with red error messages next to them to correct the problem.");
          changeById(retData[i]["field"], retData[i]["response"]);
        } // else
      } // for

      enableField('openaprs_form_contact_submit');
    } // if

  } // function()

  request.send(null);
} // doContact

/**************************************************
 ** Key Functions                                **
 **************************************************/

/**     
 * loadKey
 *
 * Load's symbol table.
 *
 */
function loadKey() {
  var request = createXMLHttpRequest();

  if (keyLoaded == true)
   return;

  showWindow('keyContainer');
  changeById('keyContainer', '<img src="http://www.openaprs.net/images/updating.gif" width="24" height="24" />');

  keyLoaded = true;

  var queryString = "/ajax/key/view.php";

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      var retData = new Array();
      xmlArray("/openaprs/symbols", xmlDoc, retData);
      for (i=0; i < retData.length; i++) {

        changeById('keyContainer', retData[i]["key"]);
      } // for
    } // if

  } // function()

  request.send(null);
} // loadKey

/**************************************************
 ** Ad Functions                                 **
 **************************************************/

/**     
 * loadAd
 *
 * Load's an ad for display.
 *
 */
function loadAd() {
  var request = createXMLHttpRequest();

  //changeById('adText', '<img src="http://www.openaprs.net/images/updating.gif" width="24" height="24" />');

  var queryString = "/ajax/ad/load.php";

  request.open("GET", queryString, true);
  request.onreadystatechange = function() {

    if (request.readyState == 4) {
      var xmlDoc = request.responseXML;

      var retData = new Array();
      xmlArray("/openaprs/ads", xmlDoc, retData);
      for (i=0; i < retData.length; i++) {

        changeById('adText', retData[i]["ad"]);
        changeById('adBanner', retData[i]["banner"]);
      } // for
    } // if

  } // function()

  request.send(null);
} // loadAd

/**************************************************
 ** XML Functions                                **
 **************************************************/


function xmlArray(path, doc, retData) {
  //var chat_debug = document.getElementById("chat_debug");
  if (doc == null)
    return;

  /**
   * Return an Array of XML elements.
   *
   */
  var i=0;

  // microsoft idiots always have to mess things up
  // by not conforming to standards.
  if (navigator.appName == "Microsoft Internet Explorer") {
    var r = doc.selectNodes(path);

    for(i=0; i < r.length; i++) {
      var n = r[i];
      retData[i] = new Object();

      // chat_debug.innerHTML += "T:"+n.tagName+"<br />";
      for(h=0; h < n.childNodes.length; h++) {
        if (n.childNodes[h].tagName != undefined) {
          // chat_debug.innerHTML += "T:["+n.childNodes[h].tagName+": "+n.childNodes[h].textContent+"]<br />";

          if (n.childNodes[h].text == undefined)
            continue;

          retData[i][n.childNodes[h].tagName] = n.childNodes[h].text;

          //if ((i % 10) == 0)
          //chat_debug.innerHTML += "T:["+n.childNodes[h].tagName+": "+n.childNodes[h].text+"]<br />";
        } // if
      } // for

    } // for
  } // if
  else {
    var xpe = doc.ownerDocument || doc;
    var nsResolver = xpe.createNSResolver(doc.ownerDocument == null ?
                      doc.documentElement : doc.ownerDocument.documentElement);
    var r = xpe.evaluate(path, doc, nsResolver, 0, null);

    for(var n; n = r.iterateNext();) {

      retData[i] = new Object();

      // chat_debug.innerHTML += "T:"+n.tagName+"<br />";
      for(h=0; h < n.childNodes.length; h++) {
        if (n.childNodes[h].tagName != undefined) {
          // chat_debug.innerHTML += "T:["+n.childNodes[h].tagName+": "+n.childNodes[h].textContent+"]<br />";

          retData[i][n.childNodes[h].tagName] = n.childNodes[h].textContent;
          // chat_debug.innerHTML += "T:["+n.childNodes[h].tagName+": "+n.childNodes[h].textContent+"]<br />";
        } // if
      } // for

      i++;
    } // for
  } // else
 

  return retData.length;
} // xmlArray

/**************************************************
 ** Field Functions                              **
 **************************************************/

/**
 * enableField
 *
 * Enable username and password fields.
 *
 */
function enableField(id) {
  var enableMe = document.getElementById(id);

  if (enableMe == null)
    return false;
  
  enableMe.disabled=null;

  return true;
} // enableField

/**
 * disableField
 *
 * Disable a field.
 *
 */
function disableField(id) {
  var disableMe = document.getElementById(id);

  if (disableMe == null)
    return false;
      
  disableMe.disabled='disabled';
      
  return true;
} // disableField

function isDisabled(id) {
  var disableMe = document.getElementById(id);

  if (disableMe == null)
    return false;

  if (disableMe.disabled == true)
    return true;

  return false;
} // isDisabled


/**************************************************
 ** Tips Functions                               **
 **************************************************/

function showBalloon(title, text) {
  Tip('<div class="tooltip"><b>'
      + title
      + '</b><br /><br />'
      + text
      + '</div>'
      , BALLOON, true, ABOVE, true, OFFSETX, 0
     );

  return;
}

/**************************************************
 ** XML Request Object                           **
 **************************************************/

function requestObject(r) {
  this.request = r;
  this.time = getUnixTime();
} // requestObject

/**************************************************
 ** Log Window                                   **
 **************************************************/

function toggleLOG() {
  if (!viewLog) {
    showWindow('logOverlay');
    changeById('OpenAPRS:Href:Log', '+ Hide Log');
    windowControl('logOverlay');
    Drag.init(document.getElementById("logHandle"), document.getElementById("logOverlay"), null, null, null, null, true);
    viewLog = true;
  } // if
  else {
    hideWindow('logOverlay');
    changeById('OpenAPRS:Href:Log', 'View Log');
    viewLog = false;
  } // else
} // toggleLOG

/**************************************************
 ** Extend Date Object                           **
 **************************************************/

Date.prototype.toFormattedUTCString = function() {
  var hours = this.getUTCHours().toString();

  if (hours.length != 2)
    hours = "0" + hours;

  var mins = this.getUTCMinutes().toString();
  if (mins.length != 2)
    mins = "0" + mins;

  var secs = this.getUTCSeconds().toString();
  if (secs.length != 2)
    secs = "0" + secs;

  var out = hours + ":" + mins + ":" + secs + " UTC";  

  return out;
} // Date::toFormattedUTCString

String.prototype.trim = function() {
  return this.replace(/^\s+|\s+$/g,"");
} // String::trim

String.prototype.ltrim = function() {
  return this.replace(/^\s+/,"");
} // String::ltrim

String.prototype.rtrim = function() {
  return this.replace(/\s+$/,"");
} // String::rtrim

function goWithHash(url, vars) {
  if (vars != undefined)
    window.open(url+'?hash='+seed+vars, '_new');
  else
    window.open(url+'?hash='+seed, '_new');
} // goWithHash

