﻿
window.WebTree = window.WebTree || function(aspTree, tree, settings)
{
	// private fields

	var form = document.forms[0]; // form owns this tree, rewrite if not work!!!
	var lastOnSubmitHandler = form.onsubmit; // current onsubmit handler

	// Events

	form.onsubmit = function()
	{
		settings.eventsData[0].value = Common.toJSON(tree.EventData);

		if (lastOnSubmitHandler != null)
			lastOnSubmitHandler();
	}

	this.OnSubmitForm = function(onSubmit)
	{
	}

	this.OnNodeExpand = function(node)
	{
	}
	
	
	this.OnNodeClick = function(treeId, nodeId)
	{
	}
	
	
	
	this.OnNodeChecked = function(node, isChecked)
	{
		// call a custom user event
		if (settings.onNodeChecked && settings.onNodeChecked(tree, node, isChecked) == false)
			return false;

		if (node.getLevel() == 0) node.setClass(isChecked ? settings.Css.NodeParentCheckedCss : settings.Css.NodeCss);
		if (node.getLevel() == 1) node.setClass(isChecked ? settings.Css.NodeCheckedCss : settings.Css.NodeCss);

		if (tree.DisableEvents) return;

		if (node.getLevel() == 0)	// if node's level is 0, then check/uncheck all its children
		{
			WebTree.EnsureChildNodesLoaded(tree, node, function(node)
			{
				node.setExpanded(true);

				$(node.getChildNodes()).each(function(index, node)
				{
					node.hasCheckbox() && node.setChecked(isChecked);
				});
			});
		}
		else if (node.getLevel() == 1)	// unpdate parent node's state
		{
			var isCheckedChildren = this.GetCheckedChildNodes(node.getParent()).length > 0;

			if (node.getParent().hasCheckbox())
			{
				tree.DisableEvents = true;
				node.getParent().setChecked(isCheckedChildren);
				tree.DisableEvents = false;
			}

			node.getParent().setClass(isCheckedChildren ? settings.Css.NodeParentCheckedCss : settings.Css.NodeCss);
		}
	}

	// Methods

	this.InfragisticTree = function()
	{
		return tree;
	}

	// the dropdownlist owns this tree, if any
	this.DropDownList = function()
	{
		return aspTree[0].DropDownList;
	}

	this.FindNode = function(levelIds, onNodeFound)
	{
		WebTree.FindNode(tree, levelIds, onNodeFound)
	}

	this.GetCheckedChildNodes = function(node)
	{
		node = node || tree;

		var foundNodes = [];
		var nodes = node.getNodes ? node.getNodes() : node.getChildNodes();

		for (var n = 0, length = nodes.length; n < length; n++)
		{
			var childNode = nodes[n];

			try
			{
				if (childNode.hasCheckbox())
				{
					if (childNode.getChecked())
					{
						// if the node's level is 0 and it's checked, test its child node.
						if (childNode.getLevel() == 0)
							foundNodes = foundNodes.concat(this.GetCheckedChildNodes(childNode));
						else
							foundNodes.push(childNode);
					}
				}
				else
					foundNodes = foundNodes.concat(this.GetCheckedChildNodes(childNode));
			} catch (ex) { } // infragistics tree crushes sometimes in getChecked, so don't let it crush the whole script
		}

		return foundNodes;
	}

	this.LoadTreeFromServer = function(onReady)
	{
		WebTree.EnsureChildNodesLoaded(tree, tree, onReady);
	}

	this.ClearAll = function(node)
	{
		var nodes = (node = node || tree).getNodes ? node.getNodes() : node.getChildNodes();

		for (var n = 0, length = nodes.length; n < length; n++)
		{
			var node = nodes[n];

			if (node.hasCheckbox())
			{
				if (node.getChecked())
					node.setChecked(false);
			}
			else
				this.ClearAll(node);
		}
	}
}

WebTree.OnInitializeTree = function(treeId)
{
	var tree = igtree_getTreeById(treeId);
	var aspTree = $(tree.Element.parentNode);

	tree.CancelPostBack = true;
	tree.NeedPostBack = false;
	tree.EventData = null;
	tree.Element.style.outline = "none"; // hide focus rectange for this tree (FF)
	tree.Element.hideFocus = true; // hide focus rectange for this tree (IE)

	tree.WebTree = aspTree[0].WebTree = new WebTree(aspTree, tree,
	{
		url: aspTree.attr("DataSourceUrl"),
		eventsData: $("#" + aspTree.attr("DataId")),
		onNodeChecked: window[aspTree.attr("OnNodeChecked")],
		Css:
		{
			NodeCss: aspTree.attr("CssNode"),
			NodeHoveredCss: aspTree.attr("CssNodeHovered"),
			NodeCheckedCss: aspTree.attr("CssNodeChecked"),
			NodeParentCheckedCss: aspTree.attr("CssNodeParentChecked")
		}
	});
}

WebTree.OnNodeExpand = function(treeId, nodeId)
{
	var tree = igtree_getTreeById(treeId);
	var node = igtree_getNodeById(nodeId);
	var childNodes = node.getChildNodes();

	if (tree.DisableEvents == true) return true;

	if (node.getPopulated() == false || childNodes.length == 0 || childNodes[0].getText() == tree.LoadOnDemandPrompt)
	{
		WebTree.LoadNodeFromServer(tree, node, false, function()
		{
			WebTree.OnEvent("onexpand", tree, node, true, { status: "expanded" });
		});
	}
	else
		WebTree.OnEvent("onexpand", tree, node, true, { status: "expanded" });

	tree.WebTree.OnNodeExpand(node);
}

WebTree.OnNodeClick = function(treeId, nodeId)
{
    var tree = igtree_getTreeById(treeId);
	var node = igtree_getNodeById(nodeId);

    if(node.hasChildren())
    {
        if (node.getExpanded() == false)
	    {
		    node.setExpanded(true);
		    WebTree._WaitForAfterDemandLoad(node.Id, WebTree.OnAfterDemandLoad_ForNodeClick);
		    return;
	    }
	    else
	    {
	        node.setExpanded(false);
	    }

    }
}

WebTree._WaitForAfterDemandLoad = function (nodeId, func)
{
	var node = igtree_getNodeById(nodeId);
	
	if (node.getChildNodes().length > 0)
	{
		// let to the node finish its binding
		window.setTimeout(function() { func(nodeId); }, 100);
	}
	else
	{
		window.setTimeout(function() { WebTree._WaitForAfterDemandLoad(nodeId, func); }, 250);
	}
}
        
WebTree.OnAfterDemandLoad_ForNodeClick = function (nodeId)
{
//	var node = igtree_getNodeById(nodeId);
//	if (node == null)
//		return;
//	node.Element.scrollIntoView();
}

WebTree.OnNodeChecked = function(treeId, nodeId, isChecked)
{
	var tree = igtree_getTreeById(treeId);
	var node = igtree_getNodeById(nodeId);

	if (tree.DisableEvents) return;

	if (tree.WebTree.OnNodeChecked(node, isChecked) == false)
	{
		tree.DisableEvents = true;
		node.setChecked(!isChecked);
		tree.DisableEvents = false;
		return false;
	}

	WebTree.OnEvent("onchecked", tree, node, true, { status: isChecked ? "checked" : "unchecked" });
}

WebTree.LoadNodeFromServer = function(tree, node, isRoot, onNodeLoaded)
{
	$.getJSON(WebTree.GetDataSourceUrl(tree, !isRoot && node), function(data, textStatus)
	{
		WebTree.PopulateNode(tree, node, data, isRoot);

		onNodeLoaded(node);
	});
}

WebTree.GetDataSourceUrl = function(tree, node)
{
	var url = tree.Element.parentNode.getAttribute("DataSourceUrl");

	return url + (url.indexOf("?") == -1 ? "?" : "&") + "NodeId=" + (node ? node.getTag() : -1) + "&NodeLevel=" + (node ? node.getLevel() : 0);
}

WebTree.PopulateNode = function(tree, parentNode, data, isRoot)
{
	// There is infragistics bug, which make the parent node of just added nodes to be expanded.
	// So after this method the parentNode will be expanded, if there are tricks to prevent this.

	var disableCheckboxesForRootNodes = tree.Element.parentNode.getAttribute("DisableCheckboxesForRootNodes") == "true";

	parentNode.removeChild && parentNode.removeChild(0);

	if (isRoot == true)
	{
		for (var key in data)
		{
			tree.CheckBoxes = !disableCheckboxesForRootNodes;

			var node = parentNode.addRoot(data[key].text);
			node.setTag(data[key].id.toString());
			tree.CheckBoxes = false;
			node.addChild(tree.LoadOnDemandPrompt);
			node.setPopulated(false);
			node.setExpanded(false);
			node.CustomData = data[key];
			tree.CheckBoxes = true;
		}
	}
	else
	{
		for (var key in data)
		{
			var node = parentNode.addChild(data[key].text);
			node.setTag(data[key].id.toString());
			node.CustomData = data[key];
		}
	}
}

WebTree.FindNode = function(tree, levelIds, onNodeFound)
{
	function FindNodeInLevel(id, nodes)
	{
		var foundNode = null;

		$(nodes).each(function(index, node)
		{
			if (+node.getTag() == id) { foundNode = node; return false; }
		});

		return foundNode;
	}

	WebTree.EnsureChildNodesLoaded(tree, tree, function()
	{
		var node = FindNodeInLevel(levelIds[0], tree.getNodes());

		WebTree.EnsureChildNodesLoaded(tree, node, function(node)
		{
			onNodeFound(FindNodeInLevel(levelIds[1], node.getChildNodes()));
		});
	});
}

WebTree.EnsureChildNodesLoaded = function(tree, node, onReady)
{
	var isRoot = node.getNodes != null;
	var childNodes = node.getNodes ? node.getNodes : node.getChildNodes();

	if (!isRoot && (!node.getPopulated() || childNodes.length == 0 || childNodes[0].getText() == tree.LoadOnDemandPrompt) || isRoot && node.getNodes() == 0)
		WebTree.LoadNodeFromServer(tree, node, isRoot, function(node) { onReady && onReady(node); });
	else
		onReady && onReady(node);
}

WebTree.OnEvent = function(eventType, tree, node, isInverse, customData)
{
	var treeEventData = tree.EventData = tree.EventData || {};
	var nodeEventData = treeEventData[node.Id] = treeEventData[node.Id] || {};

	if (isInverse == true)
	{
		nodeEventData[eventType] ? delete nodeEventData[eventType] : nodeEventData[eventType] = { id: +node.getTag(), text: node.getText(), level: node.getLevel() };
	}
	else
	{
		// not implemented
	}

	// adding custom data to the default event infromation
	if (nodeEventData[eventType] != null)
	{
		for (var key in customData)
		{
			nodeEventData[eventType][key] = customData[key];
		}
	}
}

if(typeof(Sys)!=='undefined')Sys.Application.notifyScriptLoaded();