if (!window['Node']){
  window.Node = new Object(); 
  Node.ELEMENT_NODE = 1;
  Node.ATTRIBUTE_NODE = 2;
  Node.TEXT_NODE = 3;
  Node.CDATA_SECTION_NODE = 4;
  Node.ENTITYE_REFERENCE_NODE = 5;
  Node.ENTITY_NODE = 6;
  Node.PROCESSING_INSTRUCTION_NODE = 7;
  Node.COMMENT_NODE = 8;
  Node.DOCUMENT_NODE = 9;
  Node.DOCUMENT_TYPE_NODE = 10;
  Node.DOCUMENT_FRAGMENT_NODE = 11;
  Node.NOTATION_NODE = 12;
}

function innerText(node){
  // is this a text or CDATA node?
  if (node.nodeType == 3 || node.nodeType == 4){ 
      return node.data;
  }
  var i;
  var returnValue = [];
  for (i = 0; i < node.childNodes.length; i++){
      returnValue.push(innerText(node.childNodes[i]));
  }
  return returnValue.join('');
}

function elem(name, attrs, style, text){
  var e = document.createElement(name);
  if (attrs){
      for (key in attrs){
          if (key == 'class'){
              e.className = attrs[key];
          }else if(key == 'id'){
              e.id = attrs[key];
          }else{
              e.setAttribute(key, attrs[key]);
          }
      }
  }
  if (style){
      for (key in style){
          e.style[key] = style[key];
      }
  }
  if (text){
      e.appendChild(document.createTextNode(text));
  }
  return e;
}

function handle_button(){
  var parent = document.getElementById('myContainer');
  parent.appendChild(elem('div',
    {'class': 'myDivCSSClass', 'id': 'myDivId'},
    {'position': 'absolute', 'left': '300px', 'top': '200px'},
    'This is the first text of the rest of this code'));
}


function nextNode(node){
  if (!node) return null;
  if (node.firstChild){
      return node.firstChild;
  }else{
      return nextWide(node);
  }
}

function nextWide(node){
  if (!node) return null;
  if (node.nextSibling){
      return node.nextSibling;
  }else{
      return nextWide(node.parentNode);
  }
}

function prevNode(node){
  if (!node) return null;
  if (node.previousSibling){
    return previousDeep(node.previousSibling);
  }
  return node.parentNode;
}

function previousDeep(node){
    if (!node) return null;
    while (node.childNodes.length){
        node = node.lastChild;
    }
    return node;
}

function map(list, func){
  // apply func to each node in nodeList return a new list of the results
  var result_list = new Array();
  for (var i = 0; i < list.length; i++){
      result_list.push(func(list[i]));
  }
  return result_list;
}

function filter(list, test){
    // apply test to each node, return a new list of nodes for which
    // test(node) returns true
    var result_list = new Array();
    for (var i = 0; i < list.length; i++){
        if (test(list[i])) result_list.push(list[i]);
    }
    return result_list;
}

function listInnerNodes(startNode){
    var list = new Array();
    var node = startNode;
    while(node){
        list.push(node);
        node = nextNode(node);
			if(node == startNode.nextSibling) {
			node = false;	
			}
    }
    return list;
}

function listNodes(startNode){
    var list = new Array();
    var node = startNode;
    while(node){
        list.push(node);
        node = nextNode(node);
    }
    return list;
}

function listNodesReversed(startNode){
    var list = new Array();
    var node = startNode;
    while(node){
        list.push(node);
        node = prevNode(node);
    }
    return list;
}

function nodeListToString(list){
    var strList = new Array();
    for (var i = 0; i < list.length; i++){
        strList.push(list[i].nodeName);
    }
    return strList.join(', ');
}

function docOrderIndex(node){
    // This doesn't seem to work
    var count = 0; 
    var curr = document;
    while(curr && (curr != node)){
        count++;
        curr = nextNode(node);
    }
    return count;
}


function insertAt(parent, node, index){
    if (index >= parent.childNodes.length){
        parent.appendChild(node);
    }else{
        var refNode = parent.childNodes[index];
        parent.insertBefore(node, refNode);
    }
}

var isChild = false;
function containsChild(parent_node,child_node) {      

	if(parent_node == child_node) {
	isChild = true;
	}								
							                           
    var children = parent_node.childNodes;              
    for(var i=0; i < children.length; i++) {    
        containsChild(children[i],child_node);      // Recurse on each one
    }
                             
	return isChild;						   
							   
}

function findNewParent(startNode){
    var node = startNode;
    while(node){
        if (/new/.test(node.id)) {
		return node;
		}
        node = prevNode(node);
    }
}

function findParent(startNode,parentnodeName) {
	
	var node = startNode;
    while(node){
		//debug('node '+node+'<br>'); 
		regEx = new RegExp("" + parentnodeName + "","i")
        if (regEx.test(node.nodeName) || regEx.test(node.className) || regEx.test(node.id)) {
		return node;
		}
        node = prevNode(node);
    }
		
}

function findChild(parent_node,childnodeName) {
	
	var node = nextNode(parent_node);
    while(node){
		regEx = new RegExp("" + childnodeName + "","i")
        if (regEx.test(node.nodeName) || regEx.test(node.className) || regEx.test(node.id)) {
		return node;
		}
        node = nextNode(node);
    }
		
}

var childFound;
function isAChild(parent_node,child_node) {      

	regEx = new RegExp("" + child_node + "","i")
	if (regEx.test(parent_node.nodeName) || regEx.test(parent_node.className) || regEx.test(parent_node.id)) {
	childFound = true;
	} else {
	childFound = false;	
	}
							                           
    var children = parent_node.childNodes;              
		
    for(var i=0; i < children.length; i++) {    
		if(childFound == false) {
        isAChild(children[i],child_node);      // Recurse on each one
		}
    }
	
	return childFound;
                             
							   
}