/**
 * DOMUtils.js
 * Reinventing the wheel?
 * Perhaps.  Basic extensions to DOM functionality to 
 * make your life easier.
 */


/**
 * removeChildren
 * remove all child nodes of a given node
 *
 * @parameter object node DOM node from which to remove child nodes
 */
function removeChildren(node) {

  var duchild;

  if (node.hasChildNodes) {
    while(node.childNodes.length > 0) {
      duchild = node.removeChild(node.firstChild);
    }
    return true;
  } else {
    return false;
  }

}// end removeChildren()

/**
 * removeChildrenExcept
 * remove all child nodes of a given node
 * except a child with the given id
 *
 * @parameter object node DOM node from which to remove child nodes
 * @parameter string exceptid id of the child that should not be removed
 */
function removeChildrenExcept(node, idexcept) {

  var duchild;
  var exceptfound = false;

  if (node.hasChildNodes && document.getElementById(idexcept)) {

    while(node.childNodes.length > 1) {
      if (!exceptfound && node.firstChild.nodeType == 1 && node.firstChild.getAttribute('id') == idexcept) {
        exceptfound = true;
      } else {
        if (exceptfound) {
          node.removeChild(node.lastChild);
        } else {
          node.removeChild(node.firstChild);
        }
      }
    }

    return true;
  } else {
    return false;
  }

}// end removeChildrenExcept()


/**
 * appendTextNode
 * append a text node to a given node
 *
 * @parameter object node DOM node from which to append the text node
 * @parameter string text the text to insert within the text node
 *
 * @return object input object reference
 */
function appendTextNode(node, text) {

  var dutext;

  if (node.nodeType == 1) {

      dutext = document.createTextNode(text);
      return node.appendChild(dutext);

  } else {
    return false;
  }

}// end appendTextNode()


/**
 * appendBr
 * append a br element to a given node
 *
 * @parameter object node DOM node from which to append the br element
 * @parameter string text the text to insert within the text node
 *
 * @return object input object reference
 */
function appendBr(node) {

  var dubr;

  if (node.nodeType == 1) {

      dubr = document.createElement("br");
      return node.appendChild(dubr);

  } else {
    return false;
  }

}// end appendBr()


/**
 * appendRadio
 * append a radio button to a given node
 *
 * @parameter object node DOM node from which to append the radio button
 * @parameter string name the value of the name attribute of the radio button
 * @parameter string value the value of the value attribute of the radio button
 * @parameter string id the value of the id attribute of the radio button
 * @parameter boolean checked whether or not the radio button is checked by default
 *
 * @return object input object reference
 */
function appendRadio(node, name, value, id, checked) {

  var duradio;
  var iestring;
  
  if (node.nodeType == 1) {

    // Workaround to make dynamically created radio buttons
    // selectable in (drum roll...) IE!
    try {
      iestring = "<input type='radio'";
      if (name) {
        iestring += " name='" + name + "'";
      }
      iestring += "/>";
      duradio= document.createElement(iestring);
      // force Opera to throw an error
      if (duradio.toString() == "[object HTMLElement]") throw("Opera is not IE");
    } catch(err) {
      duradio = document.createElement("input");
      duradio.setAttribute("type", "radio");
      if (name) {
        duradio.setAttribute("name", name);
      }
    }
    if (value) {
      duradio.setAttribute("value", value);
    }
    if (id) {
      duradio.setAttribute("id", id);
    }
    if (checked) {
      duradio.defaultChecked = true;
    }


    return node.appendChild(duradio);

  } else {
    return false;
  }

}// end appendRadio()


/**
 * appendLabel
 * append a label element to a given node
 *
 * @parameter object node DOM node from which to append the label element
 * @parameter string forval the value of the for attribute of the label element
 * @parameter string text the text to insert within the label element
 *
 * @return object input object reference
 */
function appendLabel(node, forval, text) {

  var dulabel;
  var dutext;
  var dulabelapp;

  if (node.nodeType == 1) {

    dulabel= document.createElement("label");

    if (forval) {
      setFor(dulabel, forval);
    }
    if (text) {
      dutext = document.createTextNode(text);
      dulabel.appendChild(dutext);
    }

    return node.appendChild(dulabel);

  } else {
    return false;
  }

}// end appendLabel()


/**
 * replaceSelect
 * replace the options in a select box with the values stored in an array
 *
 * @parameter object node SELECT node for which you want to replace the options
 * @parameter array options an array of options key = option value, value = option text
 *
 * @return object select object reference
 */
function replaceSelect(node, options) {

  var rsoption;

  if (node.nodeType == 1 && node.nodeName == "SELECT") {

    removeChildren(node);

    for (code in options) {
      rsoption = document.createElement('option');
      rsoption.setAttribute('value', code);
      appendTextNode(rsoption, options[code]);
      node.appendChild(rsoption);
    }

    return node;

  } else {

    return false;

  }

}// end replaceSelect()


/**
 * Workaround to allow setting a class in IE and Moz w/o delivering invalid html
 * 
 * @parameter object node DOM node on which you want to set the class
 * @parameter string class the class you want to use
 */
function setClass(node, value) {
  
  if (node.nodeType == 1) {
    if (document.all) {
      node.setAttribute("className", value);
    } else {
      node.setAttribute("class", value);
    }
  }

}// end setClass()


/**
 * Workaround to allow setting for attributes (for labels) in IE and Moz w/o delivering invalid html
 * 
 * @parameter object node DOM node on which you want to set the class
 * @parameter string value the value of the for attribute
 */
function setFor(node, value) {
  
  if (node.nodeType == 1) {
    if (document.all) {
      node.setAttribute("htmlFor", value);
    } else {
      node.setAttribute("for", value);
    }
  }

}// end setFor()