/**function SAXlike
 * durchläuft die gesamte DOM-Struktur unterhalb eines Startknoten
 * und ruft zu Beginn und zum Ende jedes Knoten bestimmte
 * callback-Funktionen auf. 
 * Die callback-Funktionen müssen auf window-Ebene bereitgestellt werden
 * und bestimmten Namenskonventionen bedingen. Die node-start-Funktionen
 * heißen SAXlike_start_<tagName> (z. B. SAXlike_start_div für alle div-container).
 * Analog SAXlike_end_<tagName> für die node-end-Funktionen
 * Den callback-Funktionen werden zwei Parameter übergeben:
 * 1. Das node object, das gerade startet resp. endet
 * 2. Die Hierarchietiefe bezüglich des Startknotens als Ganzzahl
 *
 * @param startNode Entweder der Startknotenselber (node object) 
 *              oder ein String, der die id des Startknotens bestimmt
 * @return void
 * @author Guido Jansen <guido_jansen@gmx.de>
 */
// bug: d counts in steps of 2 not 1
function SAXlike(startNode) {
	// the starting node 
	// either node id or node object is allowed
	// default value = document.body
	var breakOuter
	
	var startNode,
	startNode = startNode == undefined
				? document.getElementsByTagName('BODY').item(0)
				: startNode;
	startNode = typeof startNode == "string"
					? document.getElementById(startNode)
					: ( typeof startNode == "object" && startNode.nodeType && startNode.nodeType == 1
						? startNode
						: false
					  );
	if (!startNode) return;
	// remembers the start node or chooses the body node if no adequate node was given
	var root = startNode ? startNode : document.getElementsByTagName('BODY').item(0);
	// temporary
	var $;
	// counts the hierarchical depths of the node regarding to the starting node
	var d = 0;
	// parent: the current node, through which one traverses
	var $_ = root;
	// pointer stack, current pointer is always the first element
	// pointing to the childNodes of parent
	var p = [0];
	if ($_.nodeType == 1 && typeof window['SAXlike_begin_' + $_.tagName] == "function" ) {
		window['SAXlike_begin_' + $_.tagName]($_, d)
	} else if ($_.nodeType == 3 && typeof window.SAXlike_begin_textnode == "function" ) {
			window.SAXlike_begin_textnode($_, d)
	}
	
	SHOWDOMOUTER: while (true) { // break conition inside this loop // if last childnode of starting node has been accessed
		// temporary 
		$ = $_.childNodes[p[0]];
		//if (!$ || $ == NaN) break SHOWDOMOUTER;
		// so p[0] will show to the next sibling node
		p[0]++;
		try {
			if ($.nodeType != null
					&& $.nodeType == 1 
					&& typeof window['SAXlike_begin_' + $.tagName] == "function" ) {
				window['SAXlike_begin_' + $.tagName]($, d);
			} else if ($.nodeType == 3 && typeof window.SAXlike_begin_textnode == "function" ) {
					window.SAXlike_begin_textnode($, d);
			}
		} catch(e) {
			
			break
		}
		
		// node has childnodes, dive into them
		if ($.nodeType == 1
			&& $.childNodes.length > 0) {
			// current $ will be the new $_ (old parent can be accessed through the parentNode-object)
			$_ = $;
			// pointer starts with firstElement -> 0
			p.unshift(0);
			d++;
		}
		
		// end of this node, go back to parent node
		while (p[0] >= $_.childNodes.length) {
			if($_.nodeType == 1 && typeof window['SAXlike_end_' + $_.tagName] == "function" ) {
				window['SAXlike_end_' + $_.tagName]($_, d);
			}
		
			if ($_ == root) { // break condition // end of starting node
				breakOuter = true
				break
			} else {
				breakOuter = false
			}
			// step up one level
			$_ = $_.parentNode;
			//parent.pointer++
			p.shift();
				d--;
		}
			
		if (breakOuter) {
			break
		}
	}
}
