// SctBreadcrumb Class
// Main object used for interacting with the master Navlist.
// Parameters:
// publish_type  specifies how the breadcrumb object will get the navigation data (jsp, php, xhtml)
// tagname		 used to style elements. All elements will have at least tagname in their class
// selectedNode	 is the objectId of the currently selected page ( the page being rendered)
// containerNode  is the objectId of the nearest navigation root node. ( If the page isn't in navigation this is used )
//               to generate the selection list.
// begin_id		 The string used for the id parameter in the base UL (*Optional)
// begin_class	 The string used for the class parameter in the base UL (*Optional)
// debug		 Will print out the menu as text instead of html for debug purposes (*Optional)
function SctBreadcrumb ( startAt, stopAt, publish_type, tagname, selectedNodeId, separator, beginId, beginClass )
{
	var DIV_ID_PREFIX = "sct_bc_div_";
	var UL_ID_PREFIX  = "sct_bc_ul_";
	var NAV_SRC_ID    = "cssnavtree";
	var ELEMENT_NODE  = 1;
	
    
	// set the startAt / StopAt
	this.mStopAt = stopAt;
	this.mStartAt = startAt;
    
	// set the local variables to the values from the ones passed in.
    // required parameters
    this.mPublishType = publish_type;
	this.mBCName = tagname;
    
    // ObjectId's of the selected node and it's container.
    this.mSelectedNodeId = selectedNodeId;
       
    // html id and class used for the UL
    this.mBeginId = beginId;
    this.mBeginClass = beginClass;
	
	this.mSeparator = separator;
	// Set a default separator as null. If null no separator will be supplied
	if ( separator == undefined )
	{
		this.mSeparator = null;
	}
    
    

	
	// function dropCrumbs
	// If the publishType is shtml mode it will fetch the masterNavlist and
	// parse it inserting the data into the div for this breadcrumb object.
	// 
	// If we are using jsp/ajax it will do an ajax call then parse the result to 
	// then insert the data into the div for this breadcrumbtag.
	this.dropCrumbs = function()
		{ 
			var navDataUL = null;
			// Get the master navigation data as a dom object
			// if the publish type is not dynamic get the 'cssnavtree' ul dom object
			// otherwise get the dom object from the jsp/asp components.
			if ( publish_type.indexOf("html") >= 0 )
			{
				var navDataUL = document.getElementById( NAV_SRC_ID );
				// find the selectedPath for this navigation. This will be what the breadcrumb
				// is generated from
				this.createBCFromNavFile(navDataUL);
				
			}
			
		};
		
	// Copies a list item and any of it's children EXCEPT UL's
	// returns the new list item.
	this.copyListItem = function ( oldItem )
	{
		// Clone the li and any other children nodes that aren't UL items
		newItem = oldItem.cloneNode(false);
		
		// If a separator has been defined add it, unless the parent is the UL
		// meaning it's the first one.
		if ( this.mSeparator != null && this.mSeparator != "null" && this.mSeparator != "" )
		{
			var textNode = document.createTextNode( this.mSeparator );
			newItem.insertBefore( textNode , newItem.firstChild ) ;
		}
  		for ( j=0; j<oldItem.childNodes.length; j++)
		{
			var child = oldItem.childNodes[j];
			
			// If it's not a ul add it to our newItem
			if ( child.nodeType == ELEMENT_NODE )
			{
				if ( child.nodeName.toLowerCase().indexOf("ul") == -1 )
				{
					newNode = child.cloneNode(true);
					newItem.appendChild( newNode );
				}
			}
		}
		return newItem;
	};
	
	// Creates the breadcrumb when we are rendering in jsp/asp mode.
	// We don't need to worry about start and stop levels because
	// the active component already returned the data we want
	// we just need to reformat it.
	this.createBCFromActiveSource = function ( navDataUL )
	{
		// create a new UL and copy the LI into it.
		var newUL = navDataUL.cloneNode(false);
		
		// Iterate over the old li's and copy them into our new one.
		var listItems=navDataUL.getElementsByTagName("LI");
		for (i=0; i<listItems.length; i++)
		{
			newItem = this.copyListItem(listItems[i]);
			newUL.appendChild( newItem );
		}
		
		var navDiv = document.getElementById( DIV_ID_PREFIX + this.mBCName );

		this.removeFirstSeparator( newUL );
		navDiv.replaceChild( newUL, navDataUL );
	};
	
	// Removes the first separator element from the breadcrumb UL
	this.removeFirstSeparator = function removeFirstSeparator( rootULNode )
	{
		// If we don't even have a firstChild then we don't need to do anything.
		if ( rootULNode.firstChild == null )
		{
			return;
		}
		
		if ( this.mSeparator != null && this.mSeparator != "null" && this.mSeparator != "")
		{
			// If we have a separator defined we want to remove it from the first <LI>
			// so ul.li.textnode->(separator)
			rootULNode.firstChild.removeChild( rootULNode.firstChild.firstChild );
		}
	}

	
	// Creates the breadcrumb when we are rendering in html mode
	this.createBCFromNavFile = function ( navDataUL )
	{
		// find the array of selected id's
		var liNodes = navDataUL.getElementsByTagName( "LI" );
		
		var selectedNode = this.findSelectedNode( liNodes, this.mSelectedNodeId );
	
		if ( selectedNode != null )
		{
			var bcUL = this.buildBreadcrumb( selectedNode );
			var navDiv = document.getElementById(DIV_ID_PREFIX + this.mBCName);
			this.removeFirstSeparator( bcUL );
			navDiv.appendChild( bcUL );
		}

	};
	
	// Finds the selected node in the array of liNodes passed in.
	// Returns the LI that is selected
	this.findSelectedNode = function( liNodes, selectedIds )
	{
		var selectedNode = null;
		// We now have the primary path of ID's stored in our selectedIds
	    // We need to look through all of them.
	    var primaryPathIds = selectedIds.split('.');
	    for ( j = 0; j < primaryPathIds.length; j++ )
	    {
			for ( k = 0; k < liNodes.length; k++ )
			{
			   var title = liNodes[k].getAttribute( "title" );
			   if ( title == primaryPathIds[j] )
			   {
					selectedNode = liNodes[k];
			   		return selectedNode;
			   }
			}
		}
		
		return selectedNode;
	};
	
	// Utility method that returns the correct class string for use on the node passed in.
    this.setClassName = function( liNode, isSelected, hasChildren  )
		{
		    var className = this.mBCName;
		    if ( isSelected )
		    {
		        className += "_selected";
		    }
		
		    if ( hasChildren )
		    {
		    	className += "_submenu";
	    	}
			// Set the class attribute for the li node and it's child <a> node
			liNode.setAttribute("class", className );
			liNode.firstChild.setAttribute("class", className );
			// Now do it for IE<8
			liNode.setAttribute("className", className );
			liNode.firstChild.setAttribute("className", className );
			
		};
	
	// buildBreadcrum creates the breadcrumb from the navigation
	// source already included in the page. This function is only
	// used when we are doing an html rendition.
	// returns a new UL elelment with LIs for each of the breadcrumb
	// items.
	this.buildBreadcrumb = function( selectedNode )
	{
		var breadcrumbUL = document.createElement("ul");
		breadcrumbUL.setAttribute("id", this.mBeginId );
		breadcrumbUL.setAttribute("class", this.mBeginClass );
		breadcrumbUL.setAttribute("className", this.mBeginClass ); // IE<8 requires this.
		
		this.mSelectedNodesList = new Array();
		
		parentSelectedNode = selectedNode;
		var depth = 0; 
		while ( parentSelectedNode != undefined )
		{
			// Remove the title attribute which is set to the objectId of the page or webview
			if ( parentSelectedNode.tagName == "LI" )
			{
				// set the classname before we clone and insert a textnode.
				this.setClassName( parentSelectedNode, true, (depth > 0) );
				
				// Insert them at the begining of the ul.
				var clonedNode = this.copyListItem( parentSelectedNode );
				
				// Clear the title attribute so we don't get popups with the objectId in them.
				clonedNode.removeAttribute( "title" );
				breadcrumbUL.insertBefore( clonedNode, breadcrumbUL.firstChild );
				depth++;
			}
			parentSelectedNode = parentSelectedNode.parentNode;
		}
		
		// Now we have the breadcrumb we want apply the startAt and stopAt constraints.
		if ( this.mStartAt <= 0 )
		{
			// This is a relative breadcrumb so adjust the startAt and stopAt
			this.mStartAt = depth + this.mStartAt;
			this.mStopAt = depth + this.mStopAt;
		}
		else
		{
			this.mStartAt--; // Tag parameters are one based.
			this.mStopAt--;
		}

		for ( i = 0; i < breadcrumbUL.childNodes.length; i++ )
		{
			if ( i < this.mStartAt )
			{
				// Remove one from the list of children. This will change the length
				// of the array so adjust accordingly.
				breadcrumbUL.removeChild( breadcrumbUL.childNodes[i] );
				i--;
				this.mStartAt--;
				this.mStopAt--;
			}
			else if ( i > this.mStopAt )
			{
				// we can remove the rest of the children once we get here.
				while ( i < breadcrumbUL.childNodes.length )
				{
					breadcrumbUL.removeChild( breadcrumbUL.childNodes[i] );
				}
				break;
			}
		}
		
		
		return breadcrumbUL;
	};

}

// Iterates over the array of breadcrumb objects that is passed
// in and process them.
function processBreadcrumbObjects( breadcrumbArray )
{
	// loop over the breadcrumb array and have them do their thing.
	for ( numNavObj = 0; numNavObj < breadcrumbArray.length; numNavObj++ )
    {
    	breadcrumbArray[numNavObj].dropCrumbs();
    }
}

// Iterates over the array of breadcrumb objects that is passed
// in and process them.
function processActiveBcObject( req )
{
	navDiv = document.getElementById( req.bcDivId );
	navDiv.innerHTML = req.responseText;
	req.bcObject.dropCrumbs();
}



