/* (c) 2005 Koen Peters */

// Deze functie retourneert alle elementen binnen de DOMtree waarvan de tagName gelijk is aan de meegegeven tagName. 
// Er wordt alleen gezocht binnen de subDOMtree van element startNode. Eventueel wordt er gezocht naar een maximaal aantal
// elementen. Het zoeken stopt zodra dit aantal is bereikt.
// @param tagName		De tagName waarnaar moet worden gezocht.
// @param startNode		De Node waarbinnen moet worden gezocht.
// @param maxElements	(optioneel) Het aantal elementen dat moet worden gevonden voordat het zoeken wordt gestaakt. Indien niet opgegeven dan worden alle elementen gezocht.
function getElementsByTagNameFromStartNode(tagName, startNode, maxElements) {
	if (startNode && (!maxElements || maxElements > 0)) {		
		var arr = new Array();			
		rec(tagName, startNode, arr, maxElements);
		if (arr.length > 0) return arr
		else return null;
	} 
}

// Recursieve helperfunctie van de getElementsByTagNameFromStartNode functie 
// Niet direct aanroepen.
function rec(tagName, startNode, arr, maxElements) {
	if (startNode.nodeType == 1 || startNode.nodeType == 9) /* ELEMENT_NODE OF DOCUMENT_NODE */ {
		if (startNode.tagName == tagName) 
			arr.push(startNode);
		if (tagName != 'OPTION' && startNode.tagName != 'SELECT') /* Niet zoeken in lange select lijsten. Dit vreet tijd */ {			
			if (!maxElements || maxElements > arr.length) {
			// Het aantal elementen dat moet worden gevonden is nog niet bereikt of er zit geen grens aan dit aantal.
				var children = startNode.childNodes;
				for(var i=0; i < children.length; i++) {				
					rec(tagName, children[i], arr);
				}
			}
		}
	}
}

// Deze functie retourneert het eerste element binnen de DOMtree waarvan de className gelijk is aan de meegegeven className. 
// Er wordt alleen gezocht binnen de subDOMtree van element startNode.
// @param className		De className waarnaar moet worden gezocht.
// @param startNode		De Node waarbinnen moet worden gezocht.
function getFirstElementThatHasClassFromStartNode(className, startNode) {
	var elements = getElementsThatHaveClassFromStartNode(className, startNode, 1);
	if (elements) return elements[0]
	else return null;
}


// Deze functie retourneert alle elementen binnen de DOMtree waarvan de className gelijk is aan de meegegeven className. 
// Er wordt alleen gezocht binnen de subDOMtree van element startNode. Eventueel wordt er gezocht naar een maximaal aantal
// elementen. Het zoeken stopt zodra dit aantal is bereikt.
// @param className		De className waarnaar moet worden gezocht.
// @param startNode		De Node waarbinnen moet worden gezocht.
// @param maxElements	(optioneel) Het aantal elementen dat moet worden gevonden voordat het zoeken wordt gestaakt. Indien niet opgegeven dan worden alle elementen gezocht.
function getElementsThatHaveClassFromStartNode(className, startNode, maxElements) {
	if (startNode && (!maxElements || maxElements > 0)) {
		var arr = new Array();	
		rec3(className, startNode, arr, maxElements);
		if (arr.length > 0) return arr
		else return null;
	} 
}

// Recursieve helperfunctie van de getElementsThatHaveClassFromStartNode functie 
// Niet direct aanroepen.
function rec3(className, startNode, arr, maxElements) {
	if (startNode.nodeType == 1 || startNode.nodeType == 9) /* ELEMENT_NODE OF DOCUMENT_NODE */ {
		if (nodeHasClass(startNode, className)) arr.push(startNode);
		if (startNode.tagName != 'SELECT') /* Niet zoeken in lange select lijsten. Dit vreet tijd */ {
			if (!maxElements || maxElements > arr.length) {
			// Het aantal elementen dat moet worden gevonden is nog niet bereikt of er zit geen grens aan dit aantal.
				var children = startNode.childNodes;
				for(var i=0; i < children.length; i++) {				
					rec3(className, children[i], arr);
				}
			}
		}
	}
}

/* Methode die bepaalt of een van de de classes die zijn gekoppeld aan een node overeenkomt met een meegegeven className */
function nodeHasClass(node, className) {
	var c = node.className;				
	if (c) {
		if (c.indexOf(className + ' ') == 0) return true; 																			// eerste class van een rij van classes 
		if (c.indexOf(className) == 0  && c.length == className.length) return true;												// eerste en enige class 
		if ((c.indexOf(' ' + className) == (c.length - (className.length + 1))) && c.indexOf(' ' + className) > 0) return true; 	// laatste class van een rij van classes 
		if (c.indexOf(' ' + className + ' ') != -1)  return true;																	// een van de middelste classes van een rij van classes 
	}
	return false;
}