NETJOHNHENRY = window.NETJOHNHENRY ||
{};

NETJOHNHENRY.dom = {};

NETJOHNHENRY.dom.recurseAllChildNodes = function(node, injected_function, params)
{
	if (node) 
	{
		injected_function(node, params);
		for (var i = 0; i < node.childNodes.length; i++) 
		{
			var childnode = node.childNodes[i];
			if (childnode !== undefined && (childnode.nodeType == childnode.ELEMENT_NODE || childnode.nodeType == 1)) 
			{ // <- IE doesn't support node.ELEMENT_NODE therefore || node.nodeType == 1			
				NETJOHNHENRY.dom.recurseAllChildNodes(childnode, injected_function, params);
			}
		}
	}
};


//The difference between this function and the above is the scope of injected_function
//here the injected function is run within the scope of the object that declares the function
//while the above is run with the scope of the window object.
//The following has also a return of the original node.

NETJOHNHENRY.dom.recurseAllChildNodesWithDelegate = function(node, scope, injected_function, params)
{
	if (node) 
	{
		NETJOHNHENRY.delegate(scope, injected_function, params);
		for (var i = 0; i < node.childNodes.length; i++) 
		{
			var childnode = node.childNodes[i];
			if (childnode !== undefined && (childnode.nodeType == childnode.ELEMENT_NODE || childnode.nodeType == 1)) 
			{ // <- IE doesn't support node.ELEMENT_NODE therefore || node.nodeType == 1	
				try 
				{
					params.currentNode = childnode;
				} 
				catch (e) 
				{
				}
				
				node.replaceChild(NETJOHNHENRY.dom.recurseAllChildNodesWithDelegate(childnode, scope, injected_function, params), node.childNodes[i]);
				//#note: we are using the replace child because IE complains with the following code
				//node.childNodes[i] = NETJOHNHENRY.dom.recurseAllChildNodesWithDelegate(childnode, scope, injected_function, params);
			}
		}
	}
	return node;
};

NETJOHNHENRY.dom.getElementPosition = function(element)
{
	var left = 0, top = 0;
	if (element.offsetParent) 
	{
		do 
		{
			left += element.offsetLeft;
			top += element.offsetTop;
		}
		while (element = element.offsetParent);
	}
	return {
		'left': left,
		'top': top
	};
};


/*
 Class manipulation functions
 */
NETJOHNHENRY.dom.hasClass = function(e, c)
{
	var re = new RegExp('\\b' + c + '\\b');
	if (e.className) 
	{
		return re.test(e.className);
	}
	if (e.getAttribute && e.getAttribute('class'))
	{
		return re.test(e.getAttribute('class'));
	}
	return false;
};
NETJOHNHENRY.dom.addClass = function(e, c)
{
	if (!this.hasClass(e, c)) 
	{
		if (!e.className) 
		{
			e.className = c;
		}
		else 
		{
			var current = e.className;
			e.className = [current, c].join(' ');
		}
	}
};
NETJOHNHENRY.dom.removeClass = function(e, c)
{
	if (this.hasClass(e, c)) 
	{
		var re = new RegExp('\\b' + c + '\\b');
		if (e.className) 
		{
			var current = e.className;
			e.className = NETJOHNHENRY.trimString(current.replace(re, ''));
		}
	}
};
NETJOHNHENRY.dom.replaceClass = function(e, oldClass, newClass)
{
	this.removeClass(e, oldClass);
	this.addClass(e, newClass);
};


NETJOHNHENRY.dom.getElementsByClassName = function(searchClass, node, tag)
{
	// this should probably check for a native implementation and replace itself
	// if one exists
	var classElements = [];
	if (!node) 
	{
		node = document;
	}
	if (!tag) 
	{
		tag = '*';
	}
	var els = node.getElementsByTagName(tag);
	var pattern = new RegExp("(^|\\s)" + searchClass + "(\\s|$)");
	for (i = 0, elsLen = els.length; i < elsLen; i++) 
	{
		if (pattern.test(els[i].className)) 
		{
			classElements.push(els[i]);
		}
	}
	return classElements;
};


