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 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);
    }
}

