// JScript File

var userAgent = navigator.userAgent.toLowerCase();
var __sBrowserType = "";
var __CanNotDoubleQuot = "The data can not contain 'Double Quotes' except for the node name. You may use 'Single Quotes' instead."


if( eval( userAgent.indexOf('msie') != -1 ) )
{
	__sBrowserType = "IE";
}
else if( eval(navigator.product == 'Gecko') )
{
	__sBrowserType = "FF";
}

/* GLOBAL VARIABLES */
var __searchReachEnd = "Search reached to the end of the tree.";
var __searchReachStart = "Search reached to the beginning of the tree.";
var __blankSearch = "Please specify the seach text.";

function __Message(str)
{
	alert(str);
}

function Init_XmlHttp() 
{
 	var A;
	try 
	{
		A=new ActiveXObject("Msxml2.XMLHTTP");
	}
	catch (e) 
	{
		try 
		{
			A=new ActiveXObject("Microsoft.XMLHTTP");
		}
		catch (oc)
		{
			A=null;
		}
	}
	if(!A && typeof XMLHttpRequest != "undefined")
	{
		A = new XMLHttpRequest();
	}
	if (!A)
	{
		__Message("Could not create connection object.");
	}
	return A;
}

function GetCurrentURL(treeId)
{
	var url = String( Tree_GetValue( treeId, "hidThisURL" ) );
	var queryString = String( Tree_GetValue( treeId, "hidThisQS" ) );
	
	if( queryString == "" )
	{
		url = url + "?Tree_RemoteCall=true";
	}
	else
	{
		url = url + "?" + queryString + "&Tree_RemoteCall=true";
	}
	return url;
}

function SendXHRequest(treeId, queryStr, isForSearch,extaPram)
{
	var xmlhttp;
	var url = String(GetCurrentURL(treeId)) + "&TreeId=" + treeId + "&" + queryStr;
	var xmlDocument;
//	alert(url)
	xmlhttp = Init_XmlHttp()

	if (xmlhttp) 
	{
		xmlhttp.open("GET", url, true); // true --> Asynchronous
		
		xmlhttp.onreadystatechange = function()
		{
		    // only if req shows "loaded"
			if (xmlhttp.readyState == 4) 
			{
				// only if "OK"
				if (xmlhttp.status == 200) 
				{
					// ...processing statements go here...
					var childHtml = String( xmlhttp.responseText );
					PlugInSubTree(treeId, childHtml, isForSearch,extaPram);
				} 
				else 
				{
					__Message("There was a problem retrieving the XML data:\n" + xmlhttp.statusText);
				}
			}
		};		

		xmlhttp.send(null);
		delete xmlhttp;
	} 
}

function _Tree_NodeImgClick( oClickedImage, isCalledForSearch )  
{
	if( String(isCalledForSearch ) == "undefined" )
	{
		isCalledForSearch = false;
	}
	var currentNodeId = 99;
	var currentParentId = 99;
	var nNodeDepth;
	var treeId = String(oClickedImage.getAttribute("TreeId"));	
	var sDummyTDs = ""; // 0 --> PIPE image; 1 --> BLANK image.
	var bIsLastNode = "true";
	var oCurrentTR;
	var oCurrentTable;
	var imageType;
	
//	fnLoadCachedImgs(treeId);	
	
	/* Determine ParentId & ChildId using Image Clicked. */
	/* ChildId --> Current Node */	
	/* ParentId --> Parent Node of Current Node */	
	currentParentId = String(oClickedImage.getAttribute("ParentNodeId"));
	currentNodeId = String(oClickedImage.getAttribute("NodeId"));
	bIsLastNode = String(oClickedImage.getAttribute("IsLastNode"));	
	// Fetch the node depth.
	nNodeDepth = parseInt( String(oClickedImage.getAttribute( "Depth" )), 10 );

        Debug ( " currentParentId : " + currentParentId );
        Debug( " currentNodeId : " + currentNodeId );

	if( isNaN( nNodeDepth ) )
	{
		nNodeDepth = 0;
	}
	nNodeDepth++;
	/* Detemine the Current TR. */		
	oCurrentTR = document.getElementById( treeId + "_Row_" + currentNodeId );
	oCurrentTable = document.getElementById( treeId + "_Table_" + currentNodeId );

	/* PLUS Image Click */
	if( String(oClickedImage.src).indexOf( Tree_GetValue( treeId, "TPlusImg" ) ) >= 0
	    || String(oClickedImage.src).indexOf( Tree_GetValue( treeId, "LPlusImg" ) ) >= 0 )
	{
		var bHasChildFetched = false;
		bHasChildFetched = String( oCurrentTR.getAttribute( "HasChildAtClient" ) ).toLowerCase();
		
		if( isCalledForSearch )
		{
			bHasChildFetched = false;
		}
		
		if( String(bHasChildFetched) == "true" )
		{
			if(String(Tree_GetValue( treeId, "FetchAlways" )).toLowerCase() != "true")
			{
				/* This Node does already have Child, so no need of Server-trip  */
				/* Just show the tree. */
				/* *** To maintain the user's view. *****  */
				fnAutoCollapse(treeId, currentNodeId);
				fnECNode(treeId, currentNodeId, false, false);
				return true;				
			}
		}

		// Fetch child nodes from Server.
		for(var colNo = 0; colNo < oCurrentTable.rows[0].cells.length ; colNo++ )
		{
			imageType = oCurrentTable.rows[0].cells[colNo].getAttribute("ImageType");
			if(imageType != null)
			{
				switch(imageType.toLowerCase())
				{
					case "vertical" :
						sDummyTDs += "0";
						break;
					case "blank" :
						sDummyTDs += "1";
						break;
				}
			}
		}
		if( bIsLastNode.toLowerCase() == "true" )
		{
			sDummyTDs += "1";
		}
		else
		{
			sDummyTDs += "0";
		}
	
		/* Change the TPlus Image to Loading Image. */ 
		oClickedImage.src = String(oClickedImage.src).replace( Tree_GetValue( treeId, "TPlusImg" ), Tree_GetValue( treeId, "LoadingImg" ) );		
		/* OR Change LPlus image to loading image. */
		oClickedImage.src = String(oClickedImage.src).replace( Tree_GetValue( treeId, "LPlusImg" ), Tree_GetValue( treeId, "LoadingImg" ) );		

		oCurrentTR.setAttribute( "HasChildAtClient", "true");
		
		if( ! isCalledForSearch )
		{
			/* Fetch Child nodes using XmlHttp from Server via . */
			if( String( document.getElementById(treeId).getAttribute( "RootNodeId" ) ) == String(currentNodeId) )
			{
				// If root node Id and current node Id are same then 
				sDummyTDs = "1";
			}
			SendXHRequest( treeId, String( "ParentId=" + _Tree_XHEncode(currentNodeId) + "&currentParentId=" + _Tree_XHEncode(currentParentId )+ "&NodeDepth=" + nNodeDepth + "&DummyTDs=" + sDummyTDs  ), false ,'undefined')
		}
	}
	else
	{
		if(String(Tree_GetValue( treeId, "FetchAlways" )).toLowerCase() == "true")
		{
			// Delete Subtree.			
			fnECNode(treeId, currentNodeId, true, true);
		}
		else
		{
			// Hide Subtree.
			fnECNode(treeId, currentNodeId, true, false);
		}
	}
} 

// Expand/Collapse Single Node.
function fnECNode(treeId, nodeId, bCollapse, bDelete)
{
	var sDisplay = "";
	if(bCollapse)
	{
		sDisplay = "None";
	}

	var oNodeToHide = document.getElementById(treeId + "_Parent_" + nodeId );
	var oImg;

	// This condition is must. Sometimes oNodeToHide may be null.
	if( oNodeToHide != null )
	{
		oNodeToHide = oNodeToHide.parentNode.parentNode;	
		oNodeToHide.style.display = sDisplay;
		fnPlusToMinus(treeId, nodeId, bCollapse );

		if(bDelete)
		{
			fnDeleteSubtree(treeId, nodeId);
		}
	}
}

// Expand/Collapse Nodes from specified node towards root node recursively.
function fnECRecursive( treeId, nodeId, bCollapse )
{
	var sDisp = "";
	var oCurrentRow;

	if( String(bCollapse) == "true")
	{
		sDisp = "None";
	}
	// stop recursion at Root Node(s).

	oCurrentRow = document.getElementById( treeId + "_Row_" + nodeId );
	if( oCurrentRow == null )
	{
		return true;
	}

	if( oCurrentRow.getAttribute( "HasChildren" ) == "true" )
	{
		var oParentRow;
		oParentRow = document.getElementById( treeId + "_SubTreeTR_" + nodeId );
		if( oParentRow != null )
		{
			// Expand/Collapse node.
			fnPlusToMinus(treeId, nodeId, bCollapse);
			oParentRow.style.display = sDisp;
		}
	}

	oCurrentRow = document.getElementById( treeId + "_Row_" + nodeId );
	// Make recursive call.
	fnECRecursive( treeId, String(oCurrentRow.getAttribute( "ParentNodeId" )), bCollapse )
}

function fnPlusToMinus(treeId, nodeId, bReverse)
{
	var oImg = document.getElementById( treeId + "_Img_" + nodeId );

	if( oImg == null )
	{
		return true;
	}
	
	if( String(bReverse) == "true" )
	{
		oImg.src = String(oImg.src).replace( Tree_GetValue( treeId, "TMinusImg" ), Tree_GetValue( treeId, "TPlusImg" ) );
		oImg.src = String(oImg.src).replace( Tree_GetValue( treeId, "LMinusImg" ), Tree_GetValue( treeId, "LPlusImg" ) );
	}
	else
	{
		oImg.src = String(oImg.src).replace( Tree_GetValue( treeId, "TPlusImg" ), Tree_GetValue( treeId, "TMinusImg" ) );	
		oImg.src = String(oImg.src).replace( Tree_GetValue( treeId, "LPlusImg" ), Tree_GetValue( treeId, "LMinusImg" ) );	
	}
}

function fnHighlighElement(oElem)
{
	var border = String(oElem.border);
	var borderStyle = String(oElem.style.border);
	oElem.border = 1;
	oElem.style.border = "red 3px solid";
	__Message("See highlighted Element.");
	oElem.border = border;
	oElem.style.border = borderStyle;
}

// This function will delete sub-tree of "parentNodeId"
function fnDeleteSubtree(treeId, parentNodeId)
{
	var oTrToDelete = document.getElementById(treeId + "_SubTreeTR_" + parentNodeId );
	if( oTrToDelete != null )
	{
		var oParentTable;
		oParentTable = fnGetParentByTagName(oTrToDelete ,"TABLE");
		oParentTable.deleteRow( oTrToDelete.sectionRowIndex );
	}
	else
	{
		return 
	}
	//fnDeleteSubtree(treeId, parentNodeId);
}

function PlugInSubTree(treeId, childHtml, isFromSearch,extraParam)
{

	if( String( isFromSearch ) == "undefined" )
	{
		isFromSearch = false;
	}

	var oTempDiv = document.createElement("DIV");
	oTempDiv.id = treeId + "_TemporaryDiv";
	
	var oMainTable;
	var oCurrentTR;
	var oNewTable;
	var treeId = "";
	var currentParentId;
	var currentNode;
	var oFinalTable = null;
	var oTables;
	var foundNodeId;
	var firstNodeId;
	var finalTableHtml;

	// Set the returned HTML into a DIV to access the nodes via DOM.
    oTempDiv.innerHTML = String(childHtml);
	// oNewTable is the table that will contain all children requested to fetch from Server.
	oTables = oTempDiv.getElementsByTagName("TABLE");
	oNewTable = oTables[0];
	currentParentId = oNewTable.getAttribute("currentParentId");
	currentNode = oNewTable.getAttribute("parentID");
	treeId = oNewTable.getAttribute("TreeId");

//	fnLoadCachedImgs(treeId);
	switch( String(oNewTable.id).toLowerCase() )
	{
		case "__errortable" : 
			__Message( "Error occurred at server while processing XmlHttp request.\n The error was: " + oNewTable.rows[0].cells[0].innerHTML );
			return false;

		case "__searchresult" :
			// As a result of search, Server has sent the NodeId.
			// Send this node is to Server to get it back along with its tree.
			SendXHRequest( treeId, "nodeIdToSearch=" + String(oNewTable.getAttribute( "FoundNodeId" )) + "&DummyTDs=0", true,'undefined');
			return true;

		case "__searchnotfound" :
			fnSearchNotFound(treeId);
			return false;
			
		case "__addnoderesult" :
			RefreshWholeTree(treeId, String(oNewTable.getAttribute( "NewNodeId" )));
			return true;

		case "__editnoderesult" :
			//if( String(oNewTable.getAttribute( "ParentNodeId" )) == "-1" )
			{
				RefreshWholeTree(treeId, String(oNewTable.getAttribute( "EditedNodeId" )));
			}
			//else
			//{
			//	SendXHRequest( treeId, "nodeIdToSearch=" + String(oNewTable.getAttribute( "EditedNodeId" )) + "&DummyTDs=0", true,'undefined');
			//}
			return true;

		case "__deletenoderesult" :
			/// When node is deleted, highlight the upper node.
			RefreshWholeTree(treeId, String(oNewTable.getAttribute( "UpperNodeId" )));
			return true;
		
		case "__editvalues" :
		
			fnSetEditNodeValues( oNewTable, treeId, oNewTable.getAttribute("NodeID"),extraParam);
			return true;
	}
	
	// determine the final table from the tables received from Server-side.
	// the subtree table is the table whose ID is : treeId + "_Parent_" + currentNode
	for(var i = 0 ; i < oTables.length ; i++ )
	{
		if( String( treeId + "_Parent_" + currentNode ) == String( oTables[i].id ) )
		{
			oFinalTable = oTables[i];
			break;
		}
	}
	Debug("String(oFinalTable): " + String(oFinalTable))
	
	if( String(oFinalTable) == "null" )
	{
		oMainTable = document.getElementById(treeId);
		oMainTable.rows[0].cells[0].innerHTML = oNewTable.rows[0].cells[0].innerHTML;
		return true;
	}

	Debug( "Current Row ID: " + String( treeId + "_Row_" + currentNode ) )
	
	finalTableHtml = String(oFinalTable.parentNode.innerHTML);
	//Make the temp division blank.
	oTempDiv.innerHTML = "";			
	
	// The table in which one row needs to be inserted to plug-in the table which contains its child nodes.
	//oMainTable = document.getElementById( String(treeId + "_Parent_" + currentParentId) );
	// The current node row below which the above mentioned row will be inserted.
	oCurrentTR = document.getElementById( String( treeId + "_Row_" + currentNode ) )
	Debug("oCurrentTR: " + String(oCurrentTR) );	
	if( oCurrentTR == null )
	{
		Debug( "Current TR is NULL" );
		/// THIS IS THE CASE WHEN THE ENTIRE TREE WILL BE REFRESHED.
		oCurrentTR = document.getElementById( String( treeId + "_SubTreeTR_" + currentParentId ) )
		if( oCurrentTR == null )
		{
			return;
		}
		oCurrentTR.cells[0].innerHTML = oFinalTable.parentNode.innerHTML;
		return;
	}
		
	oMainTable = fnGetParentByTagName(oCurrentTR, "TABLE" );

	/* Reset the loading image to TMinus or LMinus. */
	var oClickedImage = document.getElementById( treeId + String("_Img_" + currentNode) );
	if( oClickedImage != null )
	{
		if( String(oClickedImage.getAttribute("IsLastNode")) == "true" )
		{
			oClickedImage.src = String(oClickedImage.src).replace( Tree_GetValue( treeId, "LoadingImg" ) , Tree_GetValue( treeId, "LMinusImg" ) );
		}
		else
		{
			oClickedImage.src = String(oClickedImage.src).replace( Tree_GetValue( treeId, "LoadingImg" ) , Tree_GetValue( treeId, "TMinusImg" ) );
		}
	}
	
	Debug( "isFromSearch: " + isFromSearch )
	if( isFromSearch )
	{
		foundNodeId	= oNewTable.getAttribute( "FoundNodeId" );
		firstNodeId	= oNewTable.getAttribute( "ParentId" );
	
		if ( Tree_GetValue( treeId, "IsFindNext" ) == "true" )
		{
			fnAddToList( treeId, foundNodeId );
		}
		var oCImage = document.getElementById( treeId + "_Img_" + String(firstNodeId) );
		if( oCImage != null )
		{
			/* Change the TMinus Image to TPlus Image. */ 
			oCImage.src = String(oCImage.src).replace( Tree_GetValue( treeId, "TPlusImg" ), Tree_GetValue( treeId, "TMinusImg" ) );
			/* OR  Change the LMinus Image to LPlus Image. */ 
			oCImage.src = String(oCImage.src).replace( Tree_GetValue( treeId, "LPlusImg" ), Tree_GetValue( treeId, "LMinusImg" ) );
		}
		// If the received table is the last node among the root nodes then remove the VERTI image from first TD
		// of all the table in it recursively.
		if( String(oCurrentTR.getAttribute("IsLastNode")) == "true" )
		{
			finalTableHtml = RemoveVertiImages(treeId, finalTableHtml)
		}
	}
	else
	{
		foundNodeId = currentNode;
	}
	
	// Now, ADD/EDIT row to plug the Sub-tree into the existing tree.
	if( ( oCurrentTR.sectionRowIndex + 1 ) < oMainTable.rows.length &&  String(oMainTable.rows[oCurrentTR.sectionRowIndex + 1].id) == String( treeId + "_SubTreeTR_" + currentNode ) )
	{
		// TR for Child-Tree already exists.
		Debug("EDIT ROW IN TABLE" + treeId + "_SubTreeTR_" + currentNode);
		oTd = oMainTable.rows[oCurrentTR.sectionRowIndex + 1].cells[0];
	}
	else
	{
		// Insert New TR for Child-Tree.
		Debug("INSERT ROW IN TABLE: " + treeId + "_SubTreeTR_" + currentNode);
		oTr = oMainTable.insertRow(oCurrentTR.sectionRowIndex + 1);
		oTr.id = treeId + "_SubTreeTR_" + currentNode; 
		oTd = oTr.insertCell(0);
	}

	oTd.innerHTML = finalTableHtml;
	
	// Set flag that Child Tree has been loaded at client-side.
	oCurrentTR.setAttribute( "HasChildAtClient", "true");

	Debug("foundNodeId: " + foundNodeId)

	/* *** To maintain the user's view ***  */
	fnAutoCollapse(treeId, foundNodeId);	
	if(isFromSearch)
	{
		fnClearHighlight(treeId);
		if( ! HighLightNode(treeId, foundNodeId) )
		{
			/*
			// RARE CASE.
			if( Tree_GetValue( treeId, "IsFindNext" ) == "true" )
			{
				// Node not found. So again click the find next button.
				btnFind_OnClick( document.getElementById( treeId + "_btnFind" ) , true );
			}
			else
			{
				// Node not found. So again click the find previous button.
				btnFindPrev_OnClick(document.getElementById( treeId + "_btnFindPrev" ));
			}
			*/
		}
	}
	return true;
}

// This function removes vertical image from first TD of the table and the child tables within it.
function RemoveVertiImages(treeId, tableHtml)
{
	var oTempDiv = document.createElement("DIV");
	oTempDiv.id = treeId + "_myTempDiv";
	oTempDiv.innerHTML = tableHtml;
	var sTempHtml = "";
	
	var oTableColl = oTempDiv.getElementsByTagName( "TABLE" );
	
	for( var i = 0 ; i < oTableColl.length ; i++)
	{
		if(oTableColl[i].id != "" && String(oTableColl[i].id).indexOf( treeId + "_Table_" ) != -1)
		{
			oTableColl[i].rows[0].cells[0].innerHTML = String(oTableColl[i].rows[0].cells[0].innerHTML).replace( Tree_GetValue( treeId, "VertiImg" ), Tree_GetValue( treeId, "BlankImg" ) );
			oTableColl[i].rows[0].cells[0].setAttribute( "ImageType", "blank")
		}
	}
	
	return oTempDiv.innerHTML;
}

function fnAddToList(treeId, nodeId)
{
	var sTemp = Tree_GetValue(treeId, "foundNodes");
	sTemp += nodeId + ",";
	Tree_SetValue(treeId, "foundNodes", sTemp);
}

function RemoveFromList(nodeId)
{
	var sTemp = Tree_GetValue(treeId, "foundNodes");
	sTemp += sTemp.replace( "," + nodeId + ",", "," );
	Tree_SetValue(treeId, "foundNodes", sTemp);
}

function fnAutoCollapse(treeId, nodeToKeepOpen)
{
	if( String(Tree_GetValue( treeId, "AutoCollapse")).toLowerCase() == "true" )
	{
		// Close all the trees.
		fnCEAll(treeId, false);
		// Now, open the current node.
		fnECRecursive(treeId, nodeToKeepOpen, false);
	}
}

// Collapse/Expand ALL Nodes recursively.
function fnCEAll(treeId, bExpand)
{
	var sDisp = "None";
	var nodeId;
	if(bExpand)
	{
		sDisp = "";
	}
	if( String(Tree_GetValue( treeId, "AutoCollapse")).toLowerCase() == "true" )	
	{
		var oMainTable = document.getElementById( treeId );
		var oTRColl = oMainTable.getElementsByTagName( "TR" );
		
		for( var i = 0 ; i < oTRColl.length; i++ ) 
		{
			if( String(oTRColl[i].id).indexOf( treeId + "_Row_" ) != -1  )
			{
				nodeId = String(oTRColl[i].getAttribute("NodeId"));
				fnECRecursive( treeId, nodeId, ! bExpand );
			}
		}
	}
}

function fnGetParentByTagName( oElement , sTargetTagName )
{
	var oTemp = oElement.parentNode;
	while( String( oTemp ) != "null" &&  String( oTemp.tagName ) != sTargetTagName )
	{
		oTemp = oTemp.parentNode;
	}
	return oTemp;
}

/* FIND NEXT */
function btnFind_OnClick(objBtnFind, isBtnClicked)
{
	var treeId = String(objBtnFind.getAttribute("TreeId"));

//	fnLoadCachedImgs(treeId);
	
	if( isBtnClicked || String( isBtnClicked ) == "undefined" )
	{
		Tree_SetValue( treeId, "IsFindNext", "true" )
		isBtnClicked = true;
	}
	
	var strToSearch	= Tree_Trim( String( document.getElementById( treeId + "_txtSearch" ).value ) );

	if( strToSearch == "" )
	{
		__Message( __blankSearch );
		document.getElementById( treeId + "_txtSearch" ).focus();
		return false;
	}
	
	// objBtnFind.disabled = true;

	if( Tree_Trim( Tree_GetValue(treeId, "prevSearchTxt" ) ) != Tree_Trim(strToSearch) )
	{
		Tree_SetValue( treeId, "IsFirstRequest", "true");
		Tree_SetValue(treeId, "foundNodes", ",");
	}

	// Find at client-side. If not found then Find at Server-Side from database.
	if( ! SearchInTree( treeId, strToSearch ) && isBtnClicked )
	{
		if( Tree_GetValue( treeId, "IsFirstRequest" ) == "true" )
		{
			Tree_SetValue( treeId, "IsFirstRequest", "false");
		}
		SendXHRequest( treeId, "textToSearch=" + _Tree_XHEncode(strToSearch) + "&FoundNodes=" + String(Tree_GetValue(treeId, "foundNodes")) + "&DummyTDs=1", true,'undefined');
	}

	Tree_SetValue(treeId, "prevSearchTxt", strToSearch );
}


/* FIND PREVIOUS */
function btnFindPrev_OnClick(objFindPrev)
{
	var treeId = String(objFindPrev.getAttribute("TreeId"));	
	var strToSearch	= Tree_Trim( String( document.getElementById( treeId + "_txtSearch" ).value ) );
    if( strToSearch == "" )
    {
	    __Message( __blankSearch );
	    document.getElementById( treeId + "_txtSearch" ).focus();
	    return false;
    }
	Tree_SetValue( treeId, "IsFindNext", "false" )
	var oldStr = Tree_GetValue(treeId, "foundNodes");
	var sFoundNodes = oldStr.replace( new RegExp( "\,[^,]+\,$" ), "," );
	Tree_SetValue( treeId, "foundNodes", sFoundNodes);
	
	if( oldStr == sFoundNodes || sFoundNodes == "," )
	{
		fnSearchNotFound(treeId);
		return false;
	}
	else
	{
		fnClearHighlight(treeId);
		var tempArr = sFoundNodes.split(",");
		var prevNode = tempArr[ tempArr.length - 2 ];
		
	 	if( ! HighLightNode( treeId, prevNode) )
	 	{
			SendXHRequest( treeId, "nodeIdToSearch=" + prevNode + "&DummyTDs=0", true,'undefined');	 		
	 	}
	}
}

function RefreshWholeTree(treeId, expandNodeId)
{
	var strTemp = "";
	if( String(expandNodeId) != "undefined" && String(expandNodeId) != "" )
	{
		strTemp = "&SelectedNodes=" + expandNodeId;
	}
	SendXHRequest( treeId, "nodeIdToSearch=" + _Tree_XHEncode(String(document.getElementById(treeId).getAttribute("RootNodeId"))) + "&Tree_Mode=refresh" + strTemp , true,'undefined');
}


function fnLoadCachedImgs(treeId)
{

	/*
	if( String(Tree_GetValue( treeId, "TPlusImg" )) == "undefined" )
	{
		Tree_GetValue( treeId, "TPlusImg" ) = Tree_GetValue( treeId, "TPlusImg" );
		Tree_GetValue( treeId, "TMinusImg" ) = Tree_GetValue( treeId, "TMinusImg" );
		Tree_GetValue( treeId, "LPlusImg" )  = Tree_GetValue( treeId, "LPlusImg" );
		Tree_GetValue( treeId, "LMinusImg" ) = Tree_GetValue( treeId, "LMinusImg" );
	
		Tree_GetValue( treeId, "VertiImg" ) = Tree_GetValue( treeId, "VertiImg" );
		Tree_GetValue( treeId, "SpacerImg" ) = Tree_GetValue( treeId, "SpacerImg" );
		Tree_GetValue( treeId, "BlankImg" ) = Tree_GetValue( treeId, "BlankImg" );

		Tree_GetValue( treeId, "LoadingImg" ) = Tree_GetValue( treeId, "LoadingImg" );
		
		Tree_GetValue( treeId, "ImgPath" ) = Tree_GetValue( treeId, "ImgPath" );
	}
	*/
}

function fnClearHighlight(treeId)
{
	var oMainTable = document.getElementById(treeId);	
	var oSpanColl = oMainTable.getElementsByTagName( "SPAN" );
	
	for( cntr = 0; cntr < oSpanColl.length; cntr++ )
	{
		if( String(oSpanColl[cntr].getAttribute( "name" )) == "__searchSpan" &&  String(oSpanColl[cntr].className).toLowerCase() == String(Tree_GetValue( treeId, "HighlightNodeCSS" )).toLowerCase() )	
		{		
			oSpanColl[cntr].className = Tree_GetValue( treeId, "NormalCSSClass" );
		}
	}
}

function HighLightNode(treeId, targetNodeId)
{
	var oNodeSpan = document.getElementById( treeId + "_Span_" + targetNodeId );
	if(oNodeSpan != null)
	{
		//if( String( oNodeSpan.getAttribute( "ParentNodeId" ) ) != "-1" )
		{
			fnAutoCollapse(treeId, String( oNodeSpan.getAttribute( "ParentNodeId" ) ))
		}
		fnECRecursive(treeId, String( oNodeSpan.getAttribute( "ParentNodeId" ) ) , false);
		oNodeSpan.className = Tree_GetValue( treeId, "HighlightNodeCSS" );
		return true;
	}
	return false;
}

function fnGetInnerText(oElem)
{
	switch(__sBrowserType.toUpperCase())
	{
		case "IE" :
			return oElem.innerText;
	}
	return oElem.textContent;
}

function SearchInTree( treeId,  txtToSearch )
{
	var foundAtPos = -1;
	var foundNodeId;
	var oSpan;

	var oMainTable = document.getElementById(treeId);	
	var oSpanColl = oMainTable.getElementsByTagName( "SPAN" );
	
	for( cntr = 0; cntr < oSpanColl.length; cntr++ )
	{
		if( String(oSpanColl[cntr].getAttribute( "name" )) == "__searchSpan"  )	
		{		
			oSpan = oSpanColl[cntr];

			foundAtPos = String( fnGetInnerText(oSpan) ).toLowerCase().indexOf( txtToSearch.toLowerCase() )
			if( foundAtPos != -1 )
			{
				foundNodeId = String( oSpan.getAttribute( "NodeId" ) );
				if(  Tree_GetValue( treeId, "foundNodes" ).indexOf( "," + foundNodeId + "," ) == -1  )
				{
					// If result found, then only Clear the Previous Highlight.
					fnClearHighlight(treeId);
				
					if ( Tree_GetValue( treeId, "IsFindNext" ) == "true" )
					{
						fnAddToList( treeId, foundNodeId);
					}
					
					HighLightNode(treeId, foundNodeId );
					
					break;				
				}
				else
				{
					foundAtPos = -1;
				}
			}
			
		}
	}
	
	return foundAtPos != -1;
}


/* General functions. */

function Tree_Trim(strToTrim)
{
	return strToTrim.replace( new RegExp( "^ +| +$", "g" ) , "" )
}

function Tree_GetValue(treeId, paramName )
{
	var oElem = document.getElementById( treeId + paramName );

	if( oElem != null )
	{
		return String(oElem.value)
	}
	else
	{
		__Message( "Problem while fetching value of '" + treeId + paramName + "' from hidClient." );
		return null;
	}
}

function Tree_SetValue(treeId, paramName, paramValue )
{
	var oElem = document.getElementById( treeId + paramName );

	if( oElem != null )
	{
		return oElem.value = paramValue;
	}
	else
	{
		__Message( "Problem while setting value of '" + treeId + paramName + "' to hidClient." );
		return null;
	}
}

function fnGetParentNodeId( treeId, nodeId )
{
	var oNodeRow = document.getElementById( treeId + "_Row_" + nodeId   );
	if( oNodeRow != null )
	{
		return  String( oNodeRow.getAttribute( "ParentNodeId" ) );
	}
	else
	{
		return String(document.getElementById(treeId).getAttribute("RootNodeId"));
	}
}

function fnGetUpperNodeId(treeId, nodeId)
{
	var parentNodeId = fnGetParentNodeId( treeId, nodeId )

	var oNodeSpan = document.getElementById( treeId + "_Span_" + nodeId );
	var rowNo = parseInt( oNodeSpan.getAttribute( "RowIndex" ), 10 );
	var upperNodeId = "";

	if( rowNo >= 1 )
	{
		var oParentTable = document.getElementById( treeId + "_Parent_" + parentNodeId  );
		upperNodeId = String(oParentTable.rows[rowNo-1].getAttribute( "NodeId" ));
		
		Debug("oParentTable: " + oParentTable.id + " upperNodeId: " + upperNodeId )
		
	}
	else
	{
		upperNodeId = parentNodeId
		Debug("RowIndex = 1: upperNodeId: " + upperNodeId )
	}
	if( String(upperNodeId) == "null" )
	{
		upperNodeId = String(document.getElementById(treeId).getAttribute("RootNodeId") );
		Debug("So take root node id: " + upperNodeId )
	}
	

	return upperNodeId;
}

function fnSearchNotFound(treeId)
{
	// lastNodeId --> It is a node id that was last found just before reaching to Begining or End of Tree.
	if( Tree_GetValue( treeId, "IsFindNext" ) == "true" )
	{
		__Message( __searchReachEnd );
	}
	else
	{
		__Message( __searchReachStart );
	}
}
function Tree_Trim(tstrInput)
{
	return (tstrInput.replace(/^ *| *$/g,""));
}

/* FUNCTIONS FOR ADD/EDIT/DELETE NODE. */
function _Tree_AddEdit( treeId,nodeId,parentNodeId,mode)
{		
      	if(mode == "edit")
		{			
		var oImage = document.getElementById(treeId +"edit" + nodeId) ;
		var imagename = String(oImage.src).substring(String(oImage.src).lastIndexOf('/')+1)
		oImage.src = String(oImage.src).replace(imagename,"waiting.gif" );	
		fnCreateAddEditDiv("edit",treeId,nodeId,parentNodeId ,imagename);									
							
		}
		else if(mode == 'add' )
		{		
	       	fnCreateAddEditDiv("add",treeId,nodeId,parentNodeId,'undefined');			
		}
		else if(mode == 'delete')
		{
		    if ((nodeId ==  document.getElementById(treeId).getAttribute("RootNodeId")) ||( parentNodeId == -1))
			{
			  __Message("Root node cannot be deleted,contact your administrator");
			}			
			else
			{
			    if( confirm( "Are you sure you want to delete the node ?" ) )
			    {
			    
				    var upperNodeId = fnGetUpperNodeId(treeId, nodeId);
					parentOfUpper = fnGetParentNodeId(treeId, upperNodeId);
				SendXHRequest(treeId, "Tree_Mode=delete&nodeid=" + _Tree_XHEncode(nodeId) + "&UpperNodeId=" + _Tree_XHEncode(upperNodeId) + "&ParentNodeId=" + _Tree_XHEncode(parentOfUpper) , false,'undefined');	
				}
			}
		}
	return false;
}

function fnSetEditNodeValues( oTempTable ,nTreeId, nNodeId ,extraParam )
{
	var sFieldsList = document.getElementById(nTreeId + "FieldsList").value
	var arrFieldsList = sFieldsList.split(",");	
	var oFieldElement 
	for (i=0;i< arrFieldsList.length  ;i++)
	{
        oFieldElement = document.getElementById( nTreeId + arrFieldsList[i].substring(1));
	    if (arrFieldsList[i].substring(0,1) == "t")
	    {
	        if(oTempTable.getAttribute(nTreeId + arrFieldsList[i]) != null )
	            oFieldElement.value = oTempTable.getAttribute(nTreeId + arrFieldsList[i])
	        else
	            oFieldElement.value = '';
	    }
	    else
	    {    
	        if (String(oTempTable.getAttribute(nTreeId + arrFieldsList[i])).toLowerCase() == "true")
	             oFieldElement.checked = true ;	             
	        else
	             oFieldElement.checked = false ;
	    }	
	}
	_Tree_ShowHideDiv(nTreeId + "AddEditDiv","block");
	var oImage = document.getElementById(nTreeId +"edit" + nNodeId) ;
	oImage.src = String(oImage.src).replace("waiting.gif",extraParam);
	var sFieldsList = document.getElementById(nTreeId + "FieldsList").value
    var arrFieldsList = sFieldsList.split(",");   
    document.getElementById(nTreeId + arrFieldsList[0].substring(1)).focus();		  
}

function fnCreateAddEditDiv (sMode , treeId , nodeId,parentNodeId ,imagename) 
{ 
   document.getElementById(treeId + "NodeId").value = nodeId
   document.getElementById(treeId + "ParentId").value = parentNodeId
   document.getElementById(treeId + "AddEditMode").value = sMode
   if( sMode == "add" ) // Reset Form
   {
        
         var sFieldsList = document.getElementById(treeId + "FieldsList").value
         var arrFieldsList = sFieldsList.split(",");   
         var oFieldElement ;
           _Tree_ShowHideDiv(treeId + "AddEditDiv","block");   
            for (i=0;i< arrFieldsList.length ;i++)
            {
                oFieldElement = document.getElementById( treeId + arrFieldsList[i].substring(1))
                if (arrFieldsList[i].substring(0,1) == "t") // if form item is type = textbox
                    oFieldElement.value = '';
	            else
	                oFieldElement.checked = false ;	             
	        }
        document.getElementById(treeId + arrFieldsList[0].substring(1)).focus();		  
	}else
	{
	    var queryString = "Tree_Mode=editvalues&ParentNodeId=" +_Tree_XHEncode(parentNodeId) + "&nodeid=" + _Tree_XHEncode(nodeId) ;
		SendXHRequest( treeId , queryString, false,imagename);
	}
    //document.getElementById(treeId +"_EditNodeImg" + nodeId).disabled = false;			
}

function _Tree_Save(treeId)
{	

    sMode = document.getElementById(treeId + 'AddEditMode').value
    nodeId = document.getElementById(treeId + 'NodeId').value
    parentNodeId = document.getElementById(treeId + 'ParentId').value
    if (document.getElementById(treeId + 'AddEditDiv') != "undefined") 
    {      
        var sFieldsList = document.getElementById(treeId + "FieldsList").value
	    var arrFieldsList = sFieldsList.split(",");	
	    var oFieldElement = document.getElementById( treeId + arrFieldsList[0].substring(1))
	    var DoubleQuoteTBs =  CheckFormFields(treeId);
		if( Tree_Trim( String(oFieldElement.value) ) == "" ) // if node name is blanks
	    {
	        __Message("Node Name(First TextBox) cannot be blank.");
	    }
	    else if(DoubleQuoteTBs != 0 ) // if Double Quote is in any TextBox other then Node Name
	    {
	        __Message(__CanNotDoubleQuot)
        }
	    else // send request for Add/Update Node 
	    {	 
	         var Querystr =	"Tree_Mode=" + sMode + 
			        	    "&ParentNodeId=" + _Tree_XHEncode(parentNodeId) +
			        	    "&nodeid=" + _Tree_XHEncode(nodeId)
	        for (i=0;i< arrFieldsList.length  ;i++)
	        {
	            oFieldElement = document.getElementById( treeId + arrFieldsList[i].substring(1));
	            if (arrFieldsList[i].substring(0,1) == "t") // if form item is type = textbox
	            {
	               Querystr +=  "&" + arrFieldsList[i] + "="  + _Tree_XHEncode(oFieldElement.value)
	            }
	            else // if form item is type = Checkbox
	            {
	                if (oFieldElement.checked)
	                {
                        Querystr +=  "&" + arrFieldsList[i] + "=1" 
	                }
	                else
	                {
	                    Querystr +=  "&" + arrFieldsList[i] + "=0" 
	                }	                
        	    }        	  
	      	} 
	      	 
	      	var ParentField = String(document.getElementById(treeId +  "ParentField").value)
            var ChildField  = String(document.getElementById( treeId + "ChildField").value)
	    _Tree_ShowHideDiv(treeId + "AddEditDiv" , "none" );
	    // Order of Fields(parameters) in Querystr is important, server added params to stored procedure accordingly
	     
		SendXHRequest(treeId, "ParentField=" + _Tree_XHEncode(ParentField) + "&ChildField=" + _Tree_XHEncode(ChildField) + "&" + Querystr,'undefined');
	  }
   }
	return false;
}
function _Tree_ShowHideDiv(divId,action)
{
   document.getElementById(divId).style.display = action;	
}

/* ************************************** */
function Debug( str, append )
{
	if( document.getElementById( "txaDebug" ) != null )
	{
		if( String( append ) == "false" )
		{
			document.getElementById( "txaDebug" ).value = String(str);
		}
		else
		{
			document.getElementById( "txaDebug" ).value += String(str) + "\n" ;		
		}
	}
}
// Click Event borwser compitiblity with FF and IE (not used)
function OnClickOn(objId , fnclick)
{
 var obj = document.getElementById(objId)
    if (__sBrowserType = "IE")
    {
       obj.onclick =  fnclick ;//fnclick; // IE
    }
    else if (__sBrowserType = "FF")
    {
       obj.addEventListener( "onclick", fnclick ); // Fire fox
    }
    else 
    {
      __Message('Browser Does not Supported - use IE or FF ')       
    }
}
function fnOnFormEleKeyPress(event)
{
    var oKey ; 
    if( __sBrowserType == "IE" )
	{ 
			oKey = event.keyCode;
	}
	else if( __sBrowserType == "FF" )
	{
			oKey = event.which;
	}	
	if ( oKey == 34)
	{
	    if( __sBrowserType == "FF" )
		{
				event.returnValue = false ;
		}
		__Message(__CanNotDoubleQuot)
		return false;		
	}else
	return true;
}
function  CheckFormFields(treeId)
{
    var quotFound = 0
    if (document.getElementById(treeId + 'AddEditDiv') != "undefined") 
    {   
        var sFieldsList = document.getElementById(treeId + "FieldsList").value
	    var arrFieldsList = sFieldsList.split(",");	
	    var oFieldElement 
	    
	    for (i=1;i< arrFieldsList.length  ;i++)
	    {
	      oFieldElement = document.getElementById( treeId + arrFieldsList[i].substring(1));
	      if (arrFieldsList[i].substring(0,1) == "t")
	      {
	       if (oFieldElement.value.indexOf('"') != -1)
	        {
	           quotFound = quotFound + 1 ;
	        }
	      }	    
	    }
    }
    return quotFound;
}
// following function will encode the values to avoid crash when xmlhttp request is sent with data.
function _Tree_XHEncode(strInput)
{
//    return String(strInput).replace( new RegExp( "&", "g" ), "%26" )
    return escape( String(strInput) )
}

// Following function can be called on NodeClick event to simulate the functionality Node-Expand-Collapse image on node click.
function __Tree_Node_Click(objThis)
{
	var sTreeId = String(objThis.getAttribute( "Id" )).split( "_" )[0];
	var objClickedImg = document.getElementById( sTreeId + "_Img_" + String(objThis.getAttribute( "NodeId" ) ) );

	// if null --> means no child node.
	if( objClickedImg != null )
	{
		_Tree_NodeImgClick( objClickedImg , false );
	}
}