function registerAfterCallBackFunction(treeID, useDetailNavigation) {
    var tree = igtree_getTreeById(treeID);
    tree.useDetailNavigation = useDetailNavigation
    tree.doLoadOnDemand = function(tree, node, currentNodeText) 
    {
	        var index = node.Id.indexOf("_");
	        var nodeId = node.Id.substring(index);
	        // Construct the parent display chain for the treelines
	        var nodeDisplayChain = "";
	        if(tree.ClassicTree){
	            var parent = node;
	            while(parent != null) {
	                var next;
	                next = parent.getNextSibling();
                    nodeDisplayChain += (next != null) ? "1" : "0";
	                parent = parent.getParent();
	            }       
	        }
	        var clientContext = {operation:"LoadOnDemand", clientId:tree.Id, requestType:"html", nodeId:node.Id, currentLoadingNodeText:currentNodeText};
	        var serverContext = {serverId:tree.UniqueId, nodeId:nodeId, dataPath:node.getDataPath(), level:node.getLevel(), displayChain:nodeDisplayChain};
	        var smartCallback2 = new ig_SmartCallback(clientContext, serverContext, hugeHackCallbackFunction, tree.UniqueId, this);
	        smartCallback2._responseComplete = function () 
            {
                
		        var proccessComplete = null;
                for (var i = 0; i < _asyncSmartCallbacks.length; i++) {
                    smartCallback = _asyncSmartCallbacks[i];
                    if (smartCallback && smartCallback._xmlHttpRequest && (smartCallback._xmlHttpRequest.readyState == 4)) 
                    {
				        _asyncSmartCallbacks[i] = null;
                        smartCallback.processSmartCallback();
                        proccessComplete = smartCallback;
                    }
                }
                if(proccessComplete != null)
                {
                    if(proccessComplete.callbackFinished != null)
				        proccessComplete.callbackFinished();
			        proccessComplete._control = null;
			        proccessComplete._registeredControls = null;
			        proccessComplete._progressIndicator = null; 
			        ig_dispose(proccessComplete);
			        proccessComplete = null;
                }
            }
	        smartCallback2.execute();
	}
}
function hugeHackCallbackFunction(payload, context) {
   	    var tree = igtree_getTreeById(context.clientId);
	    var parentNode = igtree_getNodeById(context.nodeId);	    
	    var tmp = payload;
	    var error = false;
	    var response;
        var subnodesId = "M_" + parentNode.Element.id;
        var subnodes = document.getElementById(subnodesId);
	    if(tmp != null && tmp.substring(0, 9) == "Exception")
	    {
	        error = true;
	    }
	    else  
	    { 
            tmp = tmp.replace(/\^\^/g, "\"");
	        response = tmp; //eval(tmp);
        }
		if(response == null || response.length == 0 || response.substring(0,6) == "NoData") 
		{
		    error = true;
		}
		if(error == true) 
		{
		    parentNode._loadingNodes = true;
		    if(tmp.substring(0, 9) == "Exception" && tmp.length > 10) 
		        parentNode.addChild(tmp.substring(10));
		    else
			    parentNode.addChild("No Data Returned from Server");
            if(context.currentLoadingNodeText != null)
                parentNode.setText(context.currentLoadingNodeText);
		    parentNode._loadingNodes = null;
			if(tree.ExpandAnimation == AnimationRateEnum.Static || tree.Element.offsetHeight == 0 || !tree.TreeLoaded) {
				subnodes.style.display = "";
		    }
			else {
   				var animate = new ig_RevealAnimation();
				animate.setElement(subnodes);
				animate.setRate(tree.ExpandAnimation);
				animate.setDirection(AnimationDirectionEnum.Down);
				animate.finishPos = subnodes.scrollHeight;
				animate.startPos = 0;
       			subnodes.style.height = 1;
       			subnodes.style.display = "";
				animate.finishPos = subnodes.scrollHeight;
    			animate.play();
    		}	
	        return;
	    }
	    var html = response; //[0]; 
        html = html.replace(/\^/g, "\"");
	    if(subnodes != null) {
            subnodes.innerHTML = html;
        }
    	if(tree.SingleBranchExpand) 
	        igtree_showSingleBranch(tree, parentNode);
        if(context.currentLoadingNodeText != null)
            parentNode.setText(context.currentLoadingNodeText);
       	parentNode._loadingNodes = null;
		if(tree.ExpandAnimation == AnimationRateEnum.Static || tree.Element.offsetHeight == 0 || !tree.TreeLoaded) {
			subnodes.style.display = "";
		}
		else {
  			var animate = new ig_RevealAnimation();
			animate.setElement(subnodes);
			animate.setRate(tree.ExpandAnimation);
			animate.setDirection(AnimationDirectionEnum.Down);
			animate.finishPos = subnodes.scrollHeight;
			animate.startPos = 0;
       		subnodes.style.height = 1;
       		subnodes.style.display = "";
			animate.finishPos = subnodes.scrollHeight;
    		animate.play();	
    	}
    	callNWAFunctions(context.clientId);
    	return;	
	

}

function callNWAFunctions(clientId)
{
    if(typeof reorderImageAndCheckBox == 'function')
    {
        reorderImageAndCheckBox(clientId);
    }
    if(typeof initDeatailedNavigationEventHandlers == 'function')
    {
        var tree = igtree_getTreeById(clientId);
        if(tree.useDetailNavigation)
        {
            initDeatailedNavigationEventHandlers(clientId);
        }
    }
}

// Public - Gets a function reference in case of the passed function-Name.
function adTree_getFunctionByName(adTreeFunction)
{
    var response = null;
    switch (adTreeFunction)
    {
        case ADTreeFunctionEnum.DragStart:
            response = ADTree_DragStart;
            break;
        case ADTreeFunctionEnum.Drop:
            response = ADTree_Drop;
            break;
        case ADTreeFunctionEnum.NodeChecked:
            response = ADTree_NodeChecked;
            break;
        case ADTreeFunctionEnum.NodeCollapse:
            response = ADTree_NodeCollapse;
            break;
        case ADTreeFunctionEnum.HandleCollapseCallback:
            response = ADTree_HandleCollapseCallback;
            break;
    }
    
    return response;
}

// Public - Enumeration of ADTree functions.
var ADTreeFunctionEnum = new function ()
{
    this.DragStart = "ADTree_DragStart";
    this.Drop = "ADTree_Drop";
    this.NodeChecked = "ADTree_NodeChecked";
    this.NodeCollapse = "ADTree_NodeCollapse";
    this.HandleCollapseCallback = "ADTree_HandleCollapseCallback";
}

// Public - Gets the datakey of the passed node.
function adTree_getDataKey(oNode, seperator)
{
    var dataKey = new String();
    var tag = oNode.getTag();
    dataKey = tag.indexOf(seperator) != -1 ?
        tag.substring(0, tag.indexOf(seperator)) :
        tag;
        
    return dataKey;
}

// Public - Gets the source datakey of the passed node, if the node is a "linked-node".
function adTree_getSourceDataKey(oNode, seperator)
{
    var sourceDataKey = new String();
    var tag = oNode.getTag();
    sourceDataKey = tag.indexOf(seperator) != -1 ?
        tag.substring(tag.indexOf(seperator) + 1) :
        tag;
        
    return sourceDataKey;
}

//Public - Gets the last clicked tree node.
function adTree_getLastClickedNode(treeId)
{
    var clickedNodeTextBox = document.getElementById(treeId + "_ClickedNodeIdField");
    var clickedNode = null;
    
	if (clickedNodeTextBox != null)
	{
	    clickedNode = igtree_getNodeById(treeId + clickedNodeTextBox.value);
	}
	
	return clickedNode;
}

//Public - Gets the last clicked tree node id.
function adTree_getLastClickedNodeId(treeId)
{
    var clickedNodeTextBox = document.getElementById(treeId + "_ClickedNodeIdField");
    var clickedNodeId = null;
    
	if (clickedNodeTextBox != null)
	{
	    if (clickedNodeTextBox.value.length > 0)
	    {
	        clickedNodeId = treeId + clickedNodeTextBox.value;
	    }
	}
	
	return clickedNodeId;
}

//Public - Performs a callback for a node collapse
function adTree_performNodeCollapseCallback(treeId, nodeId, handlerFunction)
{
    if (typeof(handlerFunction) == "undefined")
    {
        handlerFunction = ADTree_HandleCollapseCallback;
    }
    
    var oTree = igtree_getTreeById(treeId);
    var oNode = igtree_getNodeById(nodeId);
    var clientContext = {operation:"LoadOnDemand", clientId:oTree.Id, requestType:"html", nodeId:oNode.Id, currentLoadingNodeText:oNode.getText()};
    var serverContext = {serverId:oTree.UniqueId, nodeId:oNode.Id, dataPath:oNode.getDataPath(), level:oNode.getLevel(), displayChain:"", nodeTag:oNode.getTag(), demandMode:"Collapse"};    
    var smartCallback = new ig_SmartCallback(clientContext, serverContext, handlerFunction, oTree.UniqueId, this)
    smartCallback.execute();
    oNode.setPopulated(false);
}

//Public - Selects the next visible parent of the last clicked node.
function adTree_setNextVisibleParentSelected(treeId, nodeId)
{
    var clickedNodeId = adTree_getLastClickedNodeId(treeId);
    if (clickedNodeId == null)
    {
        return;
    }
    
    var clickedNode = igtree_getNodeById(clickedNodeId);
    var callingNode = igtree_getNodeById(nodeId);
    while (clickedNode == null && clickedNodeId.length > 0)
    {
        clickedNodeId = ADTree_GetNextParentId(clickedNodeId);
        clickedNode = igtree_getNodeById(clickedNodeId);
    }
    if (clickedNode != null)
    {
        var parentNode = clickedNode.getParent();
        var selectedNode = clickedNode;
        var isParentNode = false;
        while (parentNode != null)
        {
            if (parentNode.getExpanded() == false)
            {
                selectedNode = parentNode;
            }
            if (parentNode == callingNode)
            {
                isParentNode = true;
            }
            parentNode = parentNode.getParent();
        }
        if (isParentNode)
        {
            selectedNode.setSelected(true);
        }
    }
}

//Private - gets the next parent id of the passed node id.
function ADTree_GetNextParentId(nodeId)
{
    var newNodeId = new String();
    if (nodeId.length > 2)
    {
        newNodeId = nodeId.substring(0, nodeId.lastIndexOf("_"));
    }
    
    return newNodeId;
}

//Private - Handles the response from a collapse callback.
function ADTree_HandleCollapseCallback(payload, context)
{
    var oNode = igtree_getNodeById(context.nodeId);
    if (oNode == null)
    {
        return;
    }
    var subnodesId = "M_" + oNode.getElement().id;
    var subnodes = document.getElementById(subnodesId);
    if (subnodes == null)
    {
        return;
    }
    subnodes.innerHTML = "";
}

// Private - Special DragStart functionality.
function ADTree_DragStart(oTree, oNode, oDataTransfer, oEvent){
	oDataTransfer.dataTransfer.setData("Text", oNode.getText());
	oDataTransfer.dataTransfer.effectAllowed = "move";
}

// Private - Special Drop functionality.
function ADTree_Drop(oTree, oNode, oDataTransfer, oEvent){
	var droppingNode = oDataTransfer.sourceObject;
			
	if(droppingNode == null)
		return;

	if (!oNode.isChildOf(droppingNode))
	{
		ADTree_AddChildNodesRecursive(droppingNode, oNode);
		oNode.setExpanded(true);
	} 
	else 
	{
		alert("You can't add a node to its parent, grandparent, child, grandchild, etc. without creating an infinite loop.");
	}
	return false;
}

// Private - Special NodeCollapse functionality.
function ADTree_NodeCollapse(treeId, nodeId)
{    
	var node = igtree_getNodeById(nodeId);
	var clickedNodeTextBox = document.getElementById(treeId + "_ClickedNodeIdField");
	
	if (clickedNodeTextBox != null)
	{
	    var clickedNode = igtree_getNodeById(treeId + clickedNodeTextBox.value);
	    if (clickedNode == null)
	    {
	        node.setSelected(false);
	    }
	    else
	    {
	        var parentNode = clickedNode.getParent();
	        while(parentNode != null)
	        {
	            if (parentNode == node)
	            {
	                node.setSelected(true);
	                break;
	            }
	            parentNode = parentNode.getParent();
	        }
	        parentNode = null;
	        node = null;
	    }
	}
}

// Private - Adds child nodes to a parent node recursively.
function ADTree_AddChildNodesRecursive(childNode, parentNode)
{
	var newChildNode = null;
	if (parentNode == null)
	{
		var tree = igtree_getTreeById(childNode.getTreeId());
		newChildNode = tree.addRoot(childNode.getText());
	}
	else
	{
		newChildNode = parentNode.addChild(childNode.getText());
    }
	if (childNode.hasChildren()) 
	{
		var children = childNode.getChildNodes();
		for (c in children) 
		{
			var childSubNode = children[c];
			ADTree_AddChildNodesRecursive(childSubNode, newChildNode);
		}
	}
	childNode.remove();
}

var ADTree_useIndeterminationProperty = false;
// Private - Special NodeChecked functionality of the tree (myTree client behavior).
function ADTree_NodeChecked(treeId, nodeId, bChecked)
{
	var node = igtree_getNodeById(nodeId);
	
	// Initially remove the eventually set indetermination box of the clicked node.
	RemoveIndeterminationBox(node);
	
	// Handle checked and unchecked fields
	ADTree_FillCheckedUncheckedFields(node, bChecked);
	
	// In dependance on the "checked" state of the clicked node, all child nodes will be checked or unchecked.
	if (bChecked)
	    ADTree_CheckAllChildsRecursiv(node);
	else
	    ADTree_UnCheckAllChildsRecursiv(node);
	
	// The parent nodes will be set to state "indeterminate", "unchecked" or "checked".
	ADTree_CheckNodesRecursiv(node, treeId);
}

// Private - Checks all child nodes of a leaf recursively.
function ADTree_CheckAllChildsRecursiv(node)
{
    if (node.hasChildren)
    {
        var childs = node.getChildNodes();
        for (child in childs)
        {
            // Get all "input" elements from the actual child-node.
            var inputElements = childs[child].getElement().getElementsByTagName("input");
            var el;
            for (inputElement in inputElements)
            {
                el = inputElements[inputElement];
                if (el.type == "checkbox")
                {
                    el.checked = true;
                    RemoveIndeterminationBox(childs[child]);
                }
            }
            // Handle checked and unchecked fields
	        ADTree_FillCheckedUncheckedFields(childs[child], true);
            
            ADTree_CheckAllChildsRecursiv(childs[child])
        }
    }
}

// Private - Unchecks all child nodes of a leaf recursively.
function ADTree_UnCheckAllChildsRecursiv(node)
{
    if (node.hasChildren)
    {
        var childs = node.getChildNodes();
        for (child in childs)
        {
            // Get all "input" elements from the actual child-node.
            var inputElements = childs[child].getElement().getElementsByTagName("input");
            var el;
            for (inputElement in inputElements)
            {
                el = inputElements[inputElement];
                if (el.type == "checkbox")
                {
                    el.checked = false;
                    RemoveIndeterminationBox(childs[child]);
                }
            }
            // Handle checked and unchecked fields
	        ADTree_FillCheckedUncheckedFields(childs[child], false);
            
            ADTree_UnCheckAllChildsRecursiv(childs[child])
        }
    }
}

// Private - Checks tree nodes recursively.
function ADTree_CheckNodesRecursiv(node, treeId)
{   
    var imgElements;
    var inputElements;
    var el;
    // Handling for all none root nodes.
    if (node.getParent() != null)
	{
	    // Get all "input" and "img" elements from the parent of the actual node.
	    inputElements = node.getParent().getElement().getElementsByTagName("input");
	    imgElements = node.getParent().getElement().getElementsByTagName("img");
	    
	    // Get the count of all checked nodes in the same level as the actual node.
        var nodeCount = ADTree_GetParentSelectedNodesCount(node.getParent());
        var indeterminatedNodesCount = ADTree_GetParentIndeterminatedNodesCount(node.getParent());
        
        // Get image url from tree
        var indeterminateImageUrl = new String();
        indeterminateImageUrl = ADTree_GetIndeterminateImageUrl(treeId);
        
        // Remove the eventually set indetermination box from the parent of the actual node.
        RemoveIndeterminationBox(node.getParent());
        
        var elCounter = 0;
        var inputElement = null;
        for (inp in inputElements)
        {
            inputElement = inputElements[inp];
            if (inputElement.type == "checkbox")
            {
                // Checkbox handling if no node is checked.
                if (nodeCount + indeterminatedNodesCount == 0)
                {
                    inputElement.checked = false;
                    
                    // Handle checked and unchecked fields
	                ADTree_FillCheckedUncheckedFields(node.getParent(), false);
	                
                    if (ADTree_useIndeterminationProperty)
                    {
                        inputElement.indeterminate = false;
                        inputElement.style.backgroundColor = "";
                    }
                    else
                        inputElement.value = "";
                }
                // Checkbox handling if less nodes then the max. possible nodes are checked.
                else if (nodeCount != node.getParent().getChildNodes().length)
                {
                    inputElement.checked = true;
                    
                    // Handle checked and unchecked fields
	                ADTree_FillCheckedUncheckedFields(node.getParent(), true);
                    
                    if (ADTree_useIndeterminationProperty)
                    {
                        inputElement.indeterminate = true;
                        inputElement.style.backgroundColor = "transparent";
                    }
                    else
                        inputElement.value = "indeterminated";
                    
                    // Show an image for checkbox state "indeterminate".
                    for (imgElement in imgElements)
                    {
                        el = imgElements[imgElement];
                        if (el.name == "indeterminationBox")
                        {
                            el.style.display = "inline";
                            elCounter++;
                        }
                    }
                    // If no image created, create one. In the other case, make the image visible.
                    if (elCounter == 0 && indeterminateImageUrl.length > 0)
                    {
                        var newBox = document.createElement("img");
                        newBox.src = indeterminateImageUrl;
                        newBox.style.position = "absolute";
                        newBox.width = "9";
                        newBox.height = "9";
                        newBox.name = "indeterminationBox";
                        node.getParent().getElement().insertBefore(newBox, inputElement);
                    }
                }
                // Checkbox handling, if all nodes are checked.
                else
                {
                    inputElement.checked = true;
                    
                    // Handle checked and unchecked fields
	                ADTree_FillCheckedUncheckedFields(node.getParent(), true);
                    
                    if (ADTree_useIndeterminationProperty)
                    {
                        inputElement.indeterminate = false;
                        inputElement.style.backgroundColor = "";
                    }
                    else
                        inputElement.value = "on";
                    
                }
            }
        }
        // Go up to the root.
        ADTree_CheckNodesRecursiv(node.getParent(), treeId);
    }
    // Handling for all root nodes.
    else
    {
        inputElements = node.getElement().getElementsByTagName("input");
        for (inputElement in inputElements)
        {
            el = inputElements[inputElement];
            if (el.type == "checkbox" && !el.indeterminate && el.value != "indeterminated")
            {
                RemoveIndeterminationBox(node);
            }
        }
    }
}

// Private - Removes the indetermination element of a node.
function RemoveIndeterminationBox(node)
{
    var inputElements = node.getElement().getElementsByTagName("input");
    var imgElements = node.getElement().getElementsByTagName("img");
    var el;
    
    for (inp in inputElements)
    {
        el = inputElements[inp];
        if (el.type == "checkbox")
        {
            if (ADTree_useIndeterminationProperty)
            {
                el.indeterminate = false;
                el.style.backgroundColor = "";
            }
            else
                el.value = "";
        }
    }
    for (img in imgElements)
    {
        el = imgElements[img];
        if (el.name == "indeterminationBox")
        {
            el.style.display = "none";
        }
    }
}

// Private - Gets the node count of a parent node.
function ADTree_GetParentSelectedNodesCount(parentNode)
{
    var count = 0;
    if (parentNode.hasChildren)
    {
        var childNodes = parentNode.getChildNodes();
        for (child in childNodes)
        {
            if (ADTree_GetCheckedState(childNodes[child], "fullChecked"))
                count++;
        }
    }
    return count;
}

// Private - Gets the indeterminated nodes count of a parent node.
function ADTree_GetParentIndeterminatedNodesCount(parentNode)
{
    var count = 0;
    if (parentNode.hasChildren)
    {
        var childNodes = parentNode.getChildNodes();
        for (child in childNodes)
        {
            if (ADTree_GetCheckedState(childNodes[child], "indeterminate"))
                count++;
        }
    }
    return count;
}

// Private - Gets the state (bool) if a node is checked, indeterminate or checked and not indeterminated.
function ADTree_GetCheckedState(node, checkedState)
{
    var state = false;
    var inputElements = node.getElement().getElementsByTagName("input");
    var el = null;
    for (index in inputElements)
    {
        el = inputElements[index];
        if (el.type == "checkbox")
        {
            switch (checkedState)
            {
                case "fullChecked":
                    if (ADTree_useIndeterminationProperty)
                        state = (!el.indeterminate && el.checked);
                    else
                        state = (el.value != "indeterminated" && el.checked) ? true : false;
                    break;
                case "indeterminate":
                    if (ADTree_useIndeterminationProperty)
                        state = el.indeterminate;
                    else
                        state = el.value == "indeterminated" ? true : false;
                    break;
                case "checked":
                    state = el.checked;
                    break;
            }
        }
    }
    return state;
}

// Private - Gets the image url to the indeterminate image.
function ADTree_GetIndeterminateImageUrl(treeId)
{
    var url = new String();
    if (treeId != null)
    {
        var inputElement = document.getElementById(treeId + "_IndeterminateImageUrl");
        if (inputElement != null)
            url = inputElement.value;
    }
    
    return url;
}

// Private - Initialization for the display of views (myTree).
function ADTree_InitViewDisplay(treeId)
{
    var nodeId = treeId + "_1";
    var node = igtree_getNodeById(nodeId);
    if (node != null)
    {
        ADTree_ChangeNodeAppearance(node, treeId);
        while (node.getNextSibling() != null)
        {
            ADTree_ChangeNodeAppearance(node.getNextSibling(), treeId);
            node = node.getNextSibling();
        }
    }
}

// Private - Changes the checked-state of a leaf.
function ADTree_ChangeNodeAppearance(leaf, treeId)
{
    if (leaf.hasChildren() && leaf.getFirstChild() != null)
    {
        var child;
        var childs = leaf.getChildNodes();
        for (childIndex in childs)
        {
            child = childs[childIndex];
            ADTree_ChangeNodeAppearance(child, treeId);
        }
    }
    else
    {
        if (leaf.getNextSibling() == null)
        {
            ADTree_CheckNodesRecursiv(leaf, treeId);
        }
    }
    return true;
}

// Private - Fills hidden input fields (in case of the passed checked value) with the nodes datakey.
function ADTree_FillCheckedUncheckedFields(node, bChecked)
{
    var checkedInputBox = document.getElementById(node.getTreeId() + "_CheckedNodesField");
	var uncheckedInputBox = document.getElementById(node.getTreeId() + "_UncheckedNodesField");
	
	if (bChecked)
	{
	    if (checkedInputBox != null && uncheckedInputBox != null)
	    {
	        checkedInputBox.value += node.getTag() + ";";
            uncheckedInputBox.value = uncheckedInputBox.value.replace(node.getTag(), "");
        }
	}
	else
	{
	    if (checkedInputBox != null && uncheckedInputBox != null)
	    {
	        uncheckedInputBox.value += node.getTag() + ";";
            checkedInputBox.value = checkedInputBox.value.replace(node.getTag(), "");
        }
	}
}