// ---- NodeUtility V 1.0 ---------------------
// Node Utility
// © 2003-2006 Onidji®. All rights reserved.

function upNode(node)
{
  var nx = node.nextSibling;
  var p = node.parentNode;
  p.insertBefore(nx, node);
}

function downNode(node)
{
  var pv = node.previousSibling;
  var p = node.parentNode;
  p.insertBefore(node,pv);
}

function trim(s) {return s.replace(/(^\s+)|(\s+$)/g,"");}

// Delete all child of node
function deleteAllChild(node)
{
	while(node.hasChildNodes())
  		node.removeChild(node.firstChild);	
}

function deleteNode(node)
{
	node.parentNode.removeChild(node);
}

// Delete all child of node in another node
function copyAllChild(nodeSource,nodeTarget)
{
	var nb = nodeSource.childNodes.length;
	for(var i=0;i<nb;i++)
		nodeTarget.appendChild(nodeSource.childNodes[i].cloneNode(true));
}

// Give the value of the attribute's node
function getNodeAttributeValue(node,name)
{
      var r= '';
      if(node.attributes!=null)
		  for(var i=0;i<node.attributes.length;i++)
		  {
			 if(node.attributes[i].nodeName==name)
			 {
				 r=node.attributes[i].nodeValue;
				 break;
			 }
		  }
      return r;
}

function getElementsByClassName(className, tag, node) 
{
  var arr = new Array();    
  tag = tag || '*';
  node = node || document;    
  var oo = (tag == '*' && document.all) ? document.all : node.getElementsByTagName(tag);                          
  var separator = className.indexOf('|') != -1  ? '|' : ' ';   
  var cc = className.split(separator);    
  for (i = 0, j = oo.length; i < j; i++) {
    if( oo[i].tagName == undefined ) continue;   
    var aa = oo[i].className.split(' ');   
    if (separator == ' ' && cc.length > aa.length) continue;
    var c = 0;
    loop:
    for (k = 0, l = aa.length; k < l; k++) {
      for (m = 0, n = cc.length; m < n; m++) {
        if (cc[m] == aa[k]) c++;
        if (( separator == '|' && c == 1) || (separator == ' ' && c == cc.length)) {
          arr.push(oo[i]); 
          break loop;
        }
      }
    }
  }
  return arr; 
}

function addEvent(target,type,listener,useCapture) 
{
	if(target)
	{
		useCapture = typeof(useCapture)=="boolean"?useCapture:false;
		if (target.addEventListener) {
			target.addEventListener(type, listener, useCapture);
		} else if ((target==window) && document.addEventListener) {
			document.addEventListener(type, listener, useCapture);
		} else if (target.attachEvent) {
			target["e"+type+listener] = listener;
			target[type+listener] = function() {target["e"+type+listener](window.event);}
			target.attachEvent("on"+type, target[type+listener]);
		} else {
			target["on"+type] = listener;
		}
	}
}

function isChildOf(node,other) {
	if (node.compareDocumentPosition) {
		return (node.compareDocumentPosition(other)==10);
	} else if (other.contains) {
		return other.contains(node);
	}
	var isChild = false;
	function _isChildOf(node,other) {
		while (other) {
			if (other==node) {
				isChild = true;
				return;
			} else _isChildOf(node,other.firstChild);
			other = other.nextSibling;
		}
	}
	_isChildOf(node,other.firstChild);
	return isChild;
}

function setNodeAttributeValue(node,name,value)
{
	  node.setAttribute(name, value); 
      return true;
}

function getNumberOfChild(node,name)
{
	var r = 0;
	for(var i=0;i<node.childNodes.length;i++)
		if(node.childNodes[i].nodeName==name)
			r++;
	return r;		
}

function getNumberOfChildWithAttribute(node,name, value)
{
	var r = 0;
	for(var i=0;i<node.childNodes.length;i++)
		if(getNodeAttributeValue(node.childNodes[i],name)==value)
			r++;
	return r;
}

function upNode(item)
{
	var l = item.parentNode;
	var prev = item.previousSibling;
	if(prev!=null)
	{
		l.insertBefore(item,prev);
		return true;
	}
	return false;
}

function downNode(item)
{
	var l = item.parentNode;
	var nex = item.nextSibling;
	if(nex!=null)
	{
		l.insertBefore(nex,item);
		return true;
	}
	return false;
}

// Send the first node  with this tag, class or identifier
function getNode(parent,tag,className,id)
{
	var a = parent.getElementsByTagName(tag);
	for(var i=0;i<a.length;i++)
	{
		var isOk = true;
		if(isOk && className != null)
		{
			if(getNodeAttributeValue(a[i],TAG_CLASS) == className)
				isOk=true;
			else
				isOk=false;
				
		}
		if(isOk && id != null)
		{
			if(getNodeAttributeValue(a[i],TAG_ID) == id)
				isOk=true;
			else
				isOk=false;	
		}
		if(isOk)
			return a[i];
	}
	return null;
}

// Send the first node in parent tree with this tag, class or identifier
function getParentNode(parent,tag,className,id)
{
  
	var r = null;
	var node = parent;
	for(var r=null;r==null && node!=null;)
	{
		r = getNode(node,tag,className,id);
		if(r==null)
			node = node.parentNode;
	}
	return r;
}

// Send a node array with this tag, class or identifier
function getNodes(parent,tag,className,id)
{
	var r = new Array();
	var a = parent.getElementsByTagName(tag);
	for(var i=0;i<a.length;i++)
	{
		var isOk = true;
		if(className != null)
		{
			if(hasClassName(a[i],className))
				isOk=true;
			else
				isOk=false;
				
		}
		if(isOk && id != null)
		{
			if(getNodeAttributeValue(a[i],TAG_ID) == id)
				isOk=true;
			else
				isOk=false;	
		}
		if(isOk)
			r[r.length]= a[i];
	}
	return r;
}

function addClassName(node,className) {
	if ((node.nodeType==1) && !hasClassName(node,className))
		node.className = trim(node.className+" "+className);
}

function hasClassName(node,className) {
	return (node.nodeType==1)?((" "+node.className+" ").indexOf(" "+className+" ")!=-1):false;
}

function deleteClassName(node,className) {
	if (node.nodeType==1)
    node.className = trim((' '+node.className+' ').replace(' '+className+' ',' '));
}

function nodeToString(node)
{
	var r = '';
	var hasTag = (node.nodeName!=null && node.nodeName.length>0 && node.nodeName.indexOf('#')!=0);
	var hasChild = node.childNodes.length>0;
	if(hasTag)
	{
		r+= '<'+node.nodeName;
		if(node.attributes!=null && node.attributes.length>0)
		{
			for(var i=0;i<node.attributes.length;i++)
				r+= ' '+node.attributes[i].nodeName+'="'+node.attributes[i].nodeValue+'"';
			
		}
		if(hasChild)
			r+='>';	
		else
			r+='/>';
	}
	if(hasChild)
		for(var i=0;i<node.childNodes.length;i++)
			r+= nodeToString(node.childNodes[i]);
	if(node.nodeValue!=null)		
		r+=node.nodeValue;
	if(hasTag && hasChild)	
		r+='</'+node.nodeName+'>';
	return r;
}

function toXMLFormat(text)
{
	var re=/[(<>"'&]/g
	return text.replace(re, function(m){return replacecharEntities(m)})
}

function replacecharEntities(match)
{
	if (match=='<')
		return '&lt;'
	else if (match=='>')
		return "&gt;"
	else if (match=='\"')
		return '&quot;'
	else if (match=="'")
		return '&#039;'
	else if (match=='&')
		return '&amp;'
}

function toXMLEscape(text)
{
	var re=/[(<>"'&]/g
	return text.replace(re, function(m){return replacecharEscape(m)})
}

function replacecharEscape(match)
{
	if (match=='<')
		return escape('<')
	else if (match=='>')
		return escape('>')
	else if (match=='\"')
		return escape('\"')
	else if (match=="'")
		return escape("'")
	else if (match=='&')
		return escape('&')
}

function insertNodeAtSelection(selection,insertNode)
{

      // get the first range of the selection
      // (there's almost always only one range)
      var range = selection.getRangeAt(0);

      // deselect everything
      selection.removeAllRanges();

      // remove content of current selection from document
      range.deleteContents();

      // get location of current selection
      var container = range.startContainer;
      var pos = range.startOffset;

      // make a new range for the new selection
      range=document.createRange();

      if (container.nodeType==3 && insertNode.nodeType==3) {

        // if we insert text in a textnode, do optimized insertion
        container.insertData(pos, insertNode.nodeValue);

        // put cursor after inserted text
        range.setEnd(container, pos+insertNode.length);
        range.setStart(container, pos+insertNode.length);

      } else {


        var afterNode;
        if (container.nodeType==3) {

          // when inserting into a textnode
          // we create 2 new textnodes
          // and put the insertNode in between

          var textNode = container;
          container = textNode.parentNode;
          var text = textNode.nodeValue;

          // text before the split
          var textBefore = text.substr(0,pos);
          // text after the split
          var textAfter = text.substr(pos);

          var beforeNode = document.createTextNode(textBefore);
          afterNode = document.createTextNode(textAfter);

          // insert the 3 new nodes before the old one
          container.insertBefore(afterNode, textNode);
          container.insertBefore(insertNode, afterNode);
          container.insertBefore(beforeNode, insertNode);

          // remove the old node
          container.removeChild(textNode);

        } else {

          // else simply insert the node
          afterNode = container.childNodes[pos];
          container.insertBefore(insertNode, afterNode);
        }

        range.setEnd(afterNode, 0);
        range.setStart(afterNode, 0);
      }

      selection.addRange(range);
}
