/* This function will allow one js file to include others
 *   inc("moreFunctionality.js");
 */
function inc(filename)
{
  var body = document.getElementsByTagName('head').item(0);
  script = document.createElement('script');
  script.src = filename;
  script.type = 'text/javascript';
  body.appendChild(script)
}

function replaceText(el, text) {
  if (el != null) {
    clearText(el);
    var newNode = document.createTextNode(text);
    el.appendChild(newNode);
  }
}

function clearText(el) {
  if (el != null) {
    if (el.childNodes) {
      for (var i = 0; i < el.childNodes.length; i++) {
        var childNode = el.childNodes[i];
        el.removeChild(childNode);
      }
    }
  }
}

function getText(el) {
  var text = "";
  if (el != null) {
    if (el.childNodes) {
      for (var i = 0; i < el.childNodes.length; i++) {
        var childNode = el.childNodes[i];
        if (childNode.nodeValue != null) {
          text = text + childNode.nodeValue;
        }
      }
    }
  }
  return text;
}

function getElementsByAttribute(element, attribute, attributeValue)
{
  /*
  Will need to change this (or create separate function) as we need to be able
  to control whether we search every node to maximum depth or just until an AE
  is found. It is only valid for an AE to be declared underneath the body element,
  not underneath another declared AE.
  */
  
  D.debugStartFunction("getElementsByAttribute", arguments);

  var elementArray = new Array();
  var matchedArray = new Array();
  
  elementArray = getAllChildren(element);
  
  debug("No. child elements is " + elementArray.length);

  for (var i = 0; i < elementArray.length; i++)
  {
    // debug("Element[" + i + "] = " + elementArray[i].nodeName);
    if (attribute == "class")
    {
      var pattern = new RegExp("(^| )" + attributeValue + "( |$)");

      if (pattern.test(elementArray[i].className))
      {
        matchedArray[matchedArray.length] = elementArray[i];
      }
    }
    else if (attribute == "for")
    {
      if (elementArray[i].getAttribute("htmlFor") || elementArray[i].getAttribute("for"))
      {
        if (elementArray[i].htmlFor == attributeValue)
        {
          matchedArray[matchedArray.length] = elementArray[i];
        }
      }
    }
    else
    {
      // debug("Searching for " + attributeValue + ", value of " + attribute + " = " + elementArray[i].getAttribute(attribute));
      if (elementArray[i].getAttribute(attribute) == attributeValue)
      {
        debug("match found");
        matchedArray[matchedArray.length] = elementArray[i];
        debug("Number of matched elements is " + matchedArray.length);
        debug("Last added = " + matchedArray[matchedArray.length-1]);
      }
      else
      {
        // debug("no match found");
      }
    }
  }
  D.debugEndFunction();
  return matchedArray;
}

function getAllChildren(element)
{
  // (Recursive). Returns an array of all (element) nodes underneath the supplied one

  D.debugStartFunction("getAllChildren", arguments);
  // D.debug("Type of input node is " + element.nodeType);
  // D.debug("Name of input node is " + element.nodeName);
  
  var returnArray = new Array();
  var currentArray = element.childNodes;
  
  D.debug("Number of children of current node is " + currentArray.length);
  
  for (var i=0; i<currentArray.length; i++)
  {
    D.debug("Type of node " + i + " is " + currentArray[i].nodeType);
    D.debug("Name of node " + i + " is " + currentArray[i].nodeName);
    
    if (currentArray[i].id) D.debug("id of node " + i + " is " + currentArray[i].id);
    
    if (currentArray[i].nodeType == 1) // Only interested in element nodes
    {
      returnArray[returnArray.length] = currentArray[i];
      returnArray = returnArray.concat(getAllChildren(currentArray[i]));
    }
  }
  D.debugEndFunction();
  return returnArray;
}

function getAttributeSafe(element, attribute)
{
  // This function overcomes the problem that different browsers behave differently
  // when an element does not contain an attribute.  Some return an empty string and others
  // return null.  This function checks the success of getAttribute and returns an empty string
  // if it fails.  An empty string will also be returned if that is the value of the attribute
  
  if (element.getAttribute(attribute))
  {
    var ret = element.getAttribute(attribute);
  }
  else
  {
    var ret = "";
  }
  return ret;
}


function dump(arr,pLevel)
{
  // This very handy function is from the OpenJS website. Very neat!!
  
  var dumped_text = "";
  var level;
  var level_padding = "";
  var value;
  var j;
  var item;
  
  if(!pLevel) { level = 0; } else { level = pLevel; }
  
  if (true) // Used to have test here to stop going too deep
  {
    //The padding given at the beginning of the line.

    for(j=0;j<level+1;j++) level_padding += "  ";
    
    if(typeof(arr) == 'object')
    { //Array/Hashes/Objects 
      for(item in arr)
      {
        // alert("item = " + item);
        // alert("arr[item] = " + arr[item]);
        
        value = arr[item];
                    
        if(typeof(value) == 'object') //If it is an array,
        {      
          dumped_text += level_padding + "'" + item + "', ";
          dumped_text += dump(value,level+1);
        }
        else
        {
          dumped_text += level_padding + "'" + item + "' => \"" + value + "\"";
          D.debug(dumped_text);
          dumped_text = "";
        }
      }
    }
    else
    { //Stings/Chars/Numbers etc.
      D.debug("type: " + typeof(arr) + ", value: " + arr);
    }
  }
  return true;
}

function FormatCDATA(pData)
{
  return "<![CDATA[" + pData + "]]>";
}

function formatTag(pTag, pData)
{
  return "<" + pTag + ">" + pData + "</" + pTag + ">";
}

function inArray(pValue, pArray)
{
  var i;
  var ret = false;
  
  for (i=0; i<pArray.length && !ret; i++)
  {
    if (pArray[i] == pValue)
    {
      ret = true;
    }
  }
  return ret;
}

function isArray(obj)
{
  return(typeof(obj.length)=="undefined") ? false : true;
}