var toc_bRendered = false;
var toc_iTocID = 0;
var toc_iAnchorID = 0;


var toc_cTocs = [];

function writeToc(cClasses, vContainerLocator, iMinItems, vTargetLocator, sTocClass, sHeaderHTML)
{
	if( typeof(cClasses) == "string" ) cClasses = [[cClasses]];
	else if( typeof(cClasses[0]) == "string" ) cClasses = [cClasses];
	
	var oToc = { id: "__toc_" + ++toc_iTocID, classes: cClasses, itemContainerLocator: vContainerLocator, minItems: iMinItems, targetLocator: vTargetLocator };
	toc_cTocs.push(oToc);
	
	document.write("<div style=\"display: none\" class=\"" + (sTocClass || "toc") + "\" id=\"" + oToc.id + "\">" + (sHeaderHTML ? sHeaderHTML : "") + "</div>");	
}


function renderTocs()
{
	if( toc_bRendered ) return;

	toc_bRendered = true;	
	for( var i = 0; i < toc_cTocs.length; i++ ) {
		var oToc = toc_cTocs[i];
		
		var oTocContainer = document.getElementById(oToc.id);
				
		var oItemContainer = locateTarget(oToc.itemContainerLocator).element || document.body;
		
		var cRegEx = [];
		for( var j = 0, n_j = oToc.classes.length; j < n_j; j++ )
		{			
			var s = "";						
			for( var k = 0, n_k = oToc.classes[j].length; k < n_k; k++ ) {
				s += (k == 0 ? "" : "|") + oToc.classes[j][k].replace(/\-/g, "\\-");
			}	
			cRegEx.push(new RegExp("(^|\\s)(" + s + ")(\\s|$)", "i"));
		}
		
		var oTocRoot = { element: oItemContainer, children: [] };
		var cStack = [oTocRoot];
		
		var c = oItemContainer.all ? oItemContainer.all : oItemContainer.getElementsByTagName("*");
		var iItems = 0;
		for( var j = 0, n = c.length; j < n; j++ )
		{
			for( var k = 0; k < cRegEx.length; k++ ) {
				if( cRegEx[k].test(c[j].className) ) {					
					while( cStack.length - 1 > k ) cStack.pop();					
					var oTocEntry = { element: c[j], children: [], level: (k + 1) };
					cStack[cStack.length - 1].children.push(oTocEntry);
					cStack.push(oTocEntry);
					++iItems;
				}
			}
		}
		
		if( !oToc.minItems || iItems >= oToc.minItems ) {			
			createTocItems(oTocRoot, oTocContainer);
			if( oToc.targetLocator ) {								
				var oTargetInfo = locateTarget(oToc.targetLocator);				
				if( oTargetInfo.element ) {					
					if( oTargetInfo.append )
						oTargetInfo.element.insertBefore(oTocContainer, oTargetInfo.element.firstChild);
					else
						oTargetInfo.element.parentNode.insertBefore(oTocContainer, oTargetInfo.element);
				}
				else
					return;
			}
			oTocContainer.style.display = "";			
		}
	}
	
		function locateTarget(vLocator)
		{
			var oTarget = null;
			if( typeof(vLocator) == "string" ) {
				if( vLocator == "nextSibling" ) {
					oTarget = toc_getNextSibling(oTocContainer);
				} else
					oTarget = document.getElementById(vLocator);
			}
			else if( vLocator ) {			
				oTarget = vLocator(oTocContainer);				
				if( oTarget && oTarget.element ) return oTarget;				
			}					
			return { element: oTarget, append: true };
		}
	
		function createTocItems(oTocRoot, oParent)
		{
			for( var i = 0; i < oTocRoot.children.length; i++ )
			{
				var oTocEntry = oTocRoot.children[i];
				
				var oAnchor = document.createElement("A");
				oAnchor.id = oAnchor.name = "__toc_anchor" + ++toc_iAnchorID;				 				
				oTocEntry.element.parentNode.insertBefore(oAnchor, oTocEntry.element);
				if( location.hash.substr(1).toLowerCase() == oAnchor.id.toLowerCase() )
					oAnchor.scrollIntoView();
				
				
				
				var oTocItem = document.createElement("DIV");
				oTocItem.className = "tocItem tocLevel" + oTocEntry.level;
				var oTocLink = document.createElement("A");
				oTocLink.className = "tocItem tocLevel" + oTocEntry.level;
				oTocLink.href = "#" + oAnchor.id;				
				
				if( document.all ) {
					// Dynamically generated anchors does not work in IE
					oTocLink.anchorID = oAnchor.id;
					oTocLink.attachEvent('onclick', 
					function() {
						document.getElementById(event.srcElement.anchorID).scrollIntoView(true);
					});	
				}

								
				oTocLink.innerHTML = getAnchorText(oTocEntry.element.innerHTML);				
				if( oTocLink.innerHTML.replace(/( |(&nbsp;)|(&#x60))/gi, "") != "" ) {
					oTocItem.appendChild(oTocLink);			
					oParent.appendChild(oTocItem);
					
					createTocItems(oTocEntry, oTocItem);
				} else {
					createTocItems(oTocEntry, oParent);
				}
			}
		}
		
		function getAnchorText(sHtml)
		{
			var sText = sHtml.replace(/<[^>]*?>/gi, "");
			if( sText.length > 40 ) sText = sText.substr(0, 37) + "...";
			
			return sText;
		}
}

function toc_findHeaderInNextSibling(oToc, sHeaderClass, bInsertTopIfNone)
{
	var oNextSibling = toc_getNextSibling(oToc)
		
	if( oNextSibling ) {	
		var c = oNextSibling.all ? oNextSibling.all : oNextSibling.getElementsByTagName("*");
		for( var i = 0, n = c.length; i < n; i++ ) {			
			if( c[i].className.indexOf(sHeaderClass) != -1 ) {	
				var _oNextSibling = toc_getNextSibling(c[i]);
				if( _oNextSibling )
					return { element: _oNextSibling, append: false };
			}
		}
		if( bInsertTopIfNone )
			return { element: oNextSibling, append: true };
	}
	return null;
}


function toc_getNextSibling(oElement)
{
	var oNextSibling = oElement.nextSibling;
	while( oNextSibling && oNextSibling.nodeType != 1 ) { 
		oNextSibling = oNextSibling.nextSibling;						
	}	
	return oNextSibling;
}


if( window.addEventListener ) {
	window.addEventListener('load', renderTocs, false);	
} else {
	window.attachEvent('onload', renderTocs);	
}


