function newNode(sType, sContent, sName) {
	
	var oNode = null;
	
	if (sType == "text" && document.createTextNode)
		oNode = document.createTextNode(sContent);
	else if (sType == "attribute" && document.createAttribute)
		oNode = document.createAttribute(sName);
	else if (document.createElement)
		oNode = document.createElement(sType);
	
	return oNode;
}

function getParentNode(el, bTextEdit) {
	if (bTextEdit && el.parentTextEdit) return el.parentTextEdit;
	else if (el.parentNode) return el.parentNode;
	else if (el.parentElement) return el.parentElement;
	else return null;
}

function getChildObjects(oObject, sTag, bText) {
	
	if (oObject.childNodes) {
		if (bText) var aElements = oObject.childNodes;
		else {
			var aElements = new Array();
			for (var i = 0, d = -1; i < oObject.childNodes.length; i++)
				if (oObject.childNodes[i].nodeName != "#text") aElements[++d] = oObject.childNodes[i];
		}
	} else if (oObject.children) var aElements = oObject.children;
	else if (oObject.all) var aElements = oObject.all;
	if (!sTag) return aElements;
	else {
		var aReturn = new Array();
		for (var i = 0, d = -1; i < aElements.length; i++)
			if (aElements[i].nodeName == sTag) aReturn[++d] = aElements[i];
		return aReturn;
	}
}

function getSiblings(el) {
	var oParent = getParentNode(el);
	return getChildObjects(oParent);
}

function getNextSibling(oNode) {
	if (!oNode) return null;
	if (oNode.nextSibling) return oNode.nextSibling;
	var aSiblings = getSiblings(oNode);
	var retNode = null;
	if (aSiblings.length < 2) return retNode;
	for (var i = 0; i < aSiblings.length; i++) {
		if (aSiblings[i] == oNode && i < (aSiblings.length - 1)) return aSiblings[i + 1];
	}
	return retNode;
}

function getPreviousSibling(oNode) {
	if (!oNode) return false;
	if (oNode.previousSibling) return oNode.previousSibling;
	var aSiblings = getSiblings(oNode);
	if (aSiblings.length < 2) return false;
	for (var i = (aSiblings.length - 1); i > 0; i--) {
		if (aSiblings[i] == oNode) return aSiblings[i - 1];
	}
	return false;
}

function lastSibling(oNode) {
	if (!oNode) return null;
	retNode = oNode;
	if (retNode.nextSibling) while (retNode.nextSibling != null) retNode = retNode.nextSibling;
	else {
		var aSiblings = getSiblings(oNode);
		retNode = aSiblings[aSiblings.length - 1];
	}
	return retNode;
}

function firstSibling(oNode) {
	if (!oNode) return null;
	retNode = oNode;
	if (retNode.previousSibling) while (retNode.previousSibling != null) retNode = retNode.previousSibling;
	else {
		var aSiblings = getSiblings(oNode);
		retNode = aSiblings[0];
	}
	return retNode;
}

function nthSibling(n, oFrom) {
	if (!oFrom) return null;
	if (!n) return oFrom;
	retNode = oFrom;
	var aSiblings = getSiblings(oFrom);
	if (aSiblings.length < 2) return retNode;
	if (retNode.previousSibling || retNode.nextSibling) {
		for (var i = 1; i <= Math.abs(n); i++) {
			if (n > 0) retNode = retNode.nextSibling;
			else retNode = retNode.previousSibling;
			if (retNode == null) return retNode;
		}
		return retNode;
	} else {
		for (var i = 0; i < aSiblings.length; i++) {
			if (aSiblings[i] == oFrom) {
				if (aSiblings[i + n]) return aSiblings[i + n];
				else return null;
			}
		}
	}
}

function firstChildOf(oNode) {
	if (!oNode) return null;
	if (oNode.firstChild && oNode.firstChild.nodeName != "#text") return oNode.firstChild;
	else {
		var aKids = getChildObjects(oNode);
		return aKids[0];
	}
}

function lastChildOf(oNode) {
	if (!oNode) return null;
	if (oNode.lastChild && oNode.lastChild.nodeName != "#text") return oNode.lastChild;
	else {
		var aKids = getChildObjects(oNode);
		return aKids[aKids.length - 1];
	}
}

function nthChild(oParent, n, oFrom) {
	if (!oParent) return null;
	if (!n) return firstChildOf(oParent);
	if (!oFrom) oFrom = firstChildOf(oParent);
	retNode = oFrom;
	for (var i = 1; i <= Math.abs(n); i++) {
		if (n > 0) retNode = retNode.nextSibling;
		else retNode = retNode.previousSibling;
		if (retNode == null) return retNode;
	}
	return retNode;
}
