/**
 * Functions and classes for e-Grip CMS front end
 * @version $Id: dom_common.js,v 1.2 2006/11/03 14:01:10 kruithof Exp $
 */

/**
 * Gets the nodeValue for a child node with a given name
 * @access public
 * @param Node node the parent node
 * @param string subNodeName the child node's name
 * @return string the subnode's value if existing, otherwise false
 */
function getSubNodeValue(node, subNodeName)
{
    var value = false;
    if ((node.nodeType == 1) && (node.hasChildNodes())) {
        for (var i = 0; i < node.childNodes.length; i++) {
            childNode = node.childNodes.item(i);
            if ((childNode.nodeType == 1) && (childNode.tagName == subNodeName)) {
                value = getNodeValue(childNode);
            }
        }
    }
    return value;
}

/**
 * Gets node value, searches in child nodes if node is not textnode.
 */
function getNodeValue(node)
{
    var content = '';

    if (node.hasChildNodes()) { // node contains CDATA
        for (var i = 0; i < node.childNodes.length; i++) {
            content = getNodeValue(node.childNodes[i]);
        }
    } else {
        content = node.nodeValue;
    }
    return content;
}

/**
 * Sets node value, searches in first childnode if node is not textnode.
 */
function setNodeValue(node, value)
{
    if (node.hasChildNodes() && (node.childNodes.length == 1) && (node.firstChild.nodeType == 3)) { // node has one subnode, which is a textnode
        setNodeValue(node.firstChild, value);
    } else if (node.nodeType == 3) {
        node.nodeValue = value;
    }
}

/**
 * Sets class attribute, makes sure IE's proprietary 'className' is supported
 */
function setClassName(node, classname)
{
    if (node.setAttribute('class', classname)) {
        return true;
    } else if (node.setAttribute('className', classname)) {
        return true;
    }
    return false;
}

/**
 * Sets for attribute, makes sure IE's proprietary 'htmlFor' is supported
 */
function setForAttribute(node, value)
{
    if (node.setAttribute('for', value)) {
        return true;
    } else if (node.setAttribute('htmlFor', value)) {
        return true;
    }
    return false;
}

/**
 * Adds text node to node
 */
function addTextNode(node, text)
{
    var txt = document.createTextNode(text);
    node.appendChild(txt);
    return txt;
}

/**
 * Removed all children from node
 */
function removeChildren(node)
{
    while (node.firstChild) node.removeChild(node.firstChild);
}

/**
 * Removed node from its parent
 */
function removeNode(node)
{
    node.parentNode.removeChild(node);
}

/**
 * See if node matches given nodename
 */
function nodeHasName(node, nodeName)
{
    return (node.nodeName.toLowerCase() == nodeName);
}

/**
 * Clones a node to given document
 * @param Document doc Document to clone the node to
 * @param Node node The node to clone
 * @param Node dupNode The duplicate node
 * @param Boolean deep Boolean to indicate deep recursion
 */
function cloneNode(doc, node, dupNode, deep)
{
    // create new element
    if (!dupNode) dupNode = doc.createElement(node.nodeName);
    if (!deep) deep = true;

    // clone attributes
    cloneNodeAttributes(dupNode, node.attributes);

    // clone children
    if (node.hasChildNodes()) {

        var tmp_node;

        for (var i = 0; i < node.childNodes.length; i++) {
            if (node.childNodes[i].nodeType == 1) {

                tmp_node = doc.createElement(node.childNodes[i].nodeName);
                cloneNodeAttributes(tmp_node, node.childNodes[i].attributes);

                if (node.childNodes[i].hasChildNodes() && (deep == true)) {
                    tmp_node = cloneNode(doc, node.childNodes[i], tmp_node, deep);
                }

            } else if (in_array(node.childNodes[i].nodeType, [3,4,8])) {
                tmp_node = doc.createTextNode(node.childNodes[i].nodeValue);
            }
            dupNode.appendChild(tmp_node);
        }
    } else {
        dupNode.nodeValue = node.nodeValue;
    }

    return dupNode;
}

/**
 * Clones attributes to given node
 */
function cloneNodeAttributes(node, attributes)
{
    for (var i = 0; i < attributes.length; i++) {
        if (attributes[i].name == 'class') {
            setClassName(node, attributes[i].value);
        } else if (attributes[i].name == 'for') {
            setForAttribute(node, attributes[i].value);
        } else {
            node.setAttribute(attributes[i].name, attributes[i].value);
        }
    }
}

/**
 * This is what insertAfter would do, if there was a specification for it (similar to insertBefore, which does exist)
 * @param Node node The new node to insert
 * @param Node referenceNode The node to insert it after
 * @return Node insertedNode The inserted node
 */
function insertAfter(node, referenceNode)
{
    var insertedNode;
    var parentNode = referenceNode.parentNode;

    if (referenceNode == parentNode.lastSibling) {
        insertedNode = parentNode.appendChild(node);
    } else {
        var sibling = referenceNode.nextSibling;
        insertedNode = parentNode.insertBefore(node, sibling);
    }
    return insertedNode;
}