function Tree(){
	this.ID=null;
	this.VariableName=null;
	this.Width=300;
	this.Height=500;
	this.LeafTextCssClass=null;
	this.LeafTextHoverCssClass=null;
	this.LeafTextSelectedCssClass=null;
	this.LeafTextDisabledCssClass=null;
	this.BranchTextCssClass=null;
	this.BranchTextHoverCssClass=null;
	this.BranchTextSelectedCssClass=null;
	this.SetOnBranchClick=_setBranchClick;
	this.SetOnLeafClick=_setLeafClick;
	this.SetOnLoad=_setOnLoad;
	this.OnClick=_click;//private
	this.OnLoad=_onload;//private
	this.OnHighLight=_onhighlight;//private
	this.CheckChildren=_checkchildren;//private
	this.OnExpandCollapse=_exp;//private
	this.Render=_render;
	this.NodeCollection=null;
	this.ChildOffset=20;
	this.TBranchImage=null;
	this.LBranchImage=null;
	this.SelectionMode=enumSelectionMode.Single;
	this.Resize=_resize;
	this.GetSelectedNode=_getselectednode;
	this.DisableExpandCollapse=false;
	this.SetNodeText=_setnodetext;
	this.SetNodeIcon=_setnodeicon;
	this.DisplayCheckBoxes=true;
	this.SetSelected=_setselectednodes;
	this.IsDownlevelBrowser=false;
	this.ToggleCheckBranchByValue=_toggleBranchCheckByValue;
	this.FindParentNode=_findParentNode;
	this.GetNodeById=_getNodeByID;
	this.ValueNodeDepth = -1;
	var _onbranchclick;
	var _onleafclick;
	var _funcOnLoad;
	var _selectedNodeValues;
	
	var _currentlySelectedLeaf=null;
	
	function _setOnLoad(func){
		_funcOnLoad=func;
	}
	function _setBranchClick(func){
		_onbranchclick=func;
	}
	function _setLeafClick(func){
		_onleafclick=func;
	}
	
	function _toggleBranchCheckByValue(value,checked){
		var node;
		node=_getBranchByValue(value,this.NodeCollection);
		if(node!=null){
			document.getElementById(node.UniqueID+'_cb').checked=checked;
			_checkNodeRecursize(checked,node.NodeCollection,this);
		}
	}
	
	function _getBranchByValue(value,NodeCollection){
		var nodefound=null;
		for(var n=0;n<NodeCollection.Nodes.length;n++){
			if(!NodeCollection.Nodes[n].IsLeaf){
				if(NodeCollection.Nodes[n].Value==value){
					nodefound=NodeCollection.Nodes[n];
					break;
				}else{
					nodefound=_getBranchByValue(value,NodeCollection.Nodes[n].NodeCollection);
				}
			}
		}
		return nodefound;
	}
	
	function _GetNodeByID(nodeid,node){
		var path=nodeid.split('$');
		for(var p=2;p<path.length;p++){
			node=node.NodeCollection.Nodes[path[p]];
		}
		return node;
	}
	
	function _findParentNode(node){
		return _getParentnodeRecursive(this,this.NodeCollection.Nodes[0],node);
	}

	function _getNodeByID(nodeid){
		var node=null;
		var path=nodeid.split('$');
		for(var p=2;p<path.length;p++){			
			node=(node==null) ? this.NodeCollection.Nodes[path[p]] : node.NodeCollection.Nodes[path[p]];
		}
		return node;
	}

	function _inArray(val,array){
		for(var i=0;i<array.length;i++){
			if(array[i]==val){
				return true;
				break;
			}
		}
		return false;
	}
	
	function _setselectednodes(values){
		if(this.NodeCollection==null)
			return;
		_setselectednodesRecursive(this,this.NodeCollection,values, null,1);
		var output='';
		output+=__render(this.NodeCollection.Nodes,0,this);
		
		document.getElementById(this.ID).innerHTML=output;
	}
	function _setselectednodesRecursive(thisObj,NodeCollection,values,parentnode,currNodeLevel){
		for(var x=0;x<NodeCollection.Nodes.length;x++){
			var node=NodeCollection.Nodes[x];
		    node._ParentNode=parentnode;

			//if(node.NodeCollection.Nodes.length>0 && !_inArray(node.Value,values)){ // added "!_inArray(node.Value,values)" to handle drill down charts
			if(node.NodeCollection.Nodes.length>0){
				if(thisObj.SelectionMode==enumSelectionMode.Multiple){				
					node.Selected=false;
				}else{
					node.Expanded=false;
					//be careful, what happens if a branch and a leaf both have the same id?
					if(currNodeLevel >= thisObj.ValueNodeDepth)
					    node.Selected=(_inArray(node.Value,values)) && (node.NodeCollection.Nodes.length == 0 || node.TreatAsLeaf) ;
				}
				_setselectednodesRecursive(thisObj,node.NodeCollection,values,node,currNodeLevel+1);
			}else{
				node.Selected=(currNodeLevel < thisObj.ValueNodeDepth )? false : (_inArray(node.Value,values)) && (node.NodeCollection.Nodes.length == 0 || node.TreatAsLeaf) ;
//				node.Selected=(_inArray(node.Value,values));
				if(thisObj.SelectionMode == enumSelectionMode.Multiple){
					if(node.Selected && node._ParentNode!=null){
						node._ParentNode.Selected=true;
						var xNode=node;
						while(xNode._ParentNode!=null){
							xNode._ParentNode.Selected=xNode.Selected;
							xNode=xNode._ParentNode;
						}
					}
				}else{
					if(node.Selected && node._ParentNode!=null){
						node._ParentNode.Expanded=true;
						var xNode=node;
						while(xNode._ParentNode!=null){
							xNode._ParentNode.Expanded=(xNode.Expanded || xNode.Selected);
							xNode=xNode._ParentNode;
						}
					}
				}
			}
		}
	}
	function _getselectednode(){
		if(this.SelectionMode==enumSelectionMode.Multiple){
			var nodes=new Array();
			_getnodeRecursiveMulti(this,this.NodeCollection,nodes);
			return nodes;
		}else{
			return _getnodeRecursive(this,this.NodeCollection);
		}
	}
	function _getnodeRecursiveMulti(obj,NodeCollection,nodes){
		for(var x=0;x<NodeCollection.Nodes.length;x++){
			var node=NodeCollection.Nodes[x];
			
			if(node.NodeCollection.Nodes.length>0){//branches will not be represented in the selected nodes list
				_getnodeRecursiveMulti(obj,node.NodeCollection,nodes);
			}else{
				if(node.Selected){
					nodes[nodes.length]=node;
				}
			}
		}
	}
	function _getnodeRecursive(obj,NodeCollection){
		var ret=null;
		for(var x=0;x<NodeCollection.Nodes.length;x++){
			var node=NodeCollection.Nodes[x];
			
			/*if(obj.DisableExpandCollapse==false){
				if(node.NodeCollection.Nodes.length==0){
					if(node.Selected){
						ret= node;
						break;
					}
				}else{
					ret=_getnodeRecursive(obj,node.NodeCollection);
					if(ret!=null)
						break;
				}
			}else{*/
				if(node.Selected){
					ret= node;
					break;
				}else{
					ret=_getnodeRecursive(obj,node.NodeCollection);
					if(ret!=null)
						break;
				}
			//}
		}
		return ret;
	}
	
	function _getParentnodeRecursive(obj,parentNode,findnode){
		var ret=null;
		for(var x=0;x<parentNode.NodeCollection.Nodes.length;x++){
			var node=parentNode.NodeCollection.Nodes[x];
			if(node.UniqueID==findnode.UniqueID){
				ret= parentNode;
				break;
			}else{
				ret=_getParentnodeRecursive(obj,node,findnode);
				if(ret!=null)
					break;
			}
		}
		return ret;
	}
	
	function _checkchildren(cb,nodeID,e){
		var srcElement=null;
		if(document.all){
			e=window.event;
			srcElement=e.srcElement;
			tagname=e.srcElement.tagName;
		}else{
			srcElement=e.target;
			tagname=e.target.tagName;
		}
		var cancelclick=false;
		if(srcElement.getAttribute('cancelclick'))
			cancelclick=true;
		if(cancelclick)
			return;
		var node=_GetNodeByID(nodeID,this);
		_checkNodeRecursize(cb.checked,node.NodeCollection,this);
	}
	function _checkNodeRecursize(checked,NodeCollection,thisObj){
		var node;
		var isLeaf=true;
		for(var x=0;x<NodeCollection.Nodes.length;x++){
			node=NodeCollection.Nodes[x];
			
			isLeaf=(node.NodeCollection.Nodes.length==0);
	
			document.getElementById(node.UniqueID+'_cb').checked=checked;
			if(!isLeaf){
				_checkNodeRecursize(checked,node.NodeCollection,thisObj)
			}else{
				var n=document.getElementById(node.UniqueID);
				if(checked){
					if(node.Enabled)
					n.className=thisObj.LeafTextSelectedCssClass;
					else
						n.className=thisObj.LeafTextDisabledCssClass;			
					n.setAttribute('selected','true');
					node.Selected=true;
				}else{
					if(node.Enabled)
					n.className=thisObj.LeafTextCssClass;
					else
						n.className=thisObj.LeafTextDisabledCssClass;					
					n.setAttribute('selected','false');
					node.Selected=false;
				}
			}
		}
	}
	
	
	function _click(nodeid,isLeaf,e,forceGetSelected){
		var tagname='';
		var srcElement=null;
		if(document.all){
			e=window.event;
			srcElement=e.srcElement;
			tagname=e.srcElement.tagName;
		}else{
			srcElement=e.target;
			tagname=e.target.tagName;
		}
		var cancelclick=false;
		if(srcElement.getAttribute('cancelclick'))
			cancelclick=true;
		//if(tagname=='INPUT' || cancelclick)
		if(cancelclick)
			return;
		_click2(nodeid,isLeaf,this,forceGetSelected);
	}
	
	
	function _click2(nodeid,isLeaf,thisObj,forceGetSelected){
		var node;
		node=_GetNodeByID(nodeid,thisObj);
		
		var n=document.getElementById(nodeid);
	
	//	if(isLeaf || this.DisableExpandCollapse){
			if(thisObj.SelectionMode==enumSelectionMode.Single && _currentlySelectedLeaf!=null){
			    if(forceGetSelected)_currentlySelectedLeaf = thisObj.GetSelectedNode();
				if(_currentlySelectedLeaf.UniqueID!=node.UniqueID){
					_currentlySelectedLeaf.Selected=false;
					document.getElementById(_currentlySelectedLeaf.UniqueID).className=thisObj.LeafTextCssClass;
					document.getElementById(_currentlySelectedLeaf.UniqueID).setAttribute('selected','false');
					if(thisObj.DisplayCheckBoxes) document.getElementById(_currentlySelectedLeaf.UniqueID+'_cb').checked=false;

			        
					_currentlySelectedLeaf=null;
				}
			}
			if(n.getAttribute('selected')=='false'){
				n.className=thisObj.LeafTextSelectedCssClass;
				n.setAttribute('selected','true');
				node.Selected=true;
				if(thisObj.SelectionMode==enumSelectionMode.Single){
					_currentlySelectedLeaf=node;
				}
			}else{
				n.className=thisObj.LeafTextCssClass;
				n.setAttribute('selected','false');
				node.Selected=false;
				if(thisObj.SelectionMode==enumSelectionMode.Single){
					_currentlySelectedLeaf=null;
				}
			}
			
			if(thisObj.DisplayCheckBoxes){
				document.getElementById(node.UniqueID+'_cb').checked=node.Selected;
			}
			
			
	//	}else{
		if(isLeaf){
			if(_onleafclick)
				_onleafclick(node);
		}else{
			/*var c=document.getElementById(nodeid+'_children');
			if(c.style.display=='none'){
				//n.className=thisObj.BranchTextSelectedCssClass;
				//n.setAttribute('selected','true');
				c.style.display='block';
				//node.Selected=true;
			}else{
				//n.className=thisObj.BranchTextCssClass;
				//n.setAttribute('selected','false');
				c.style.display='none';			
				//node.Selected=false;
			}*/
			if(_onbranchclick)
				_onbranchclick(node);
		}
	}
	function _exp(img,nodeid){
		var node;
		node=_GetNodeByID(nodeid,this);
		
		
		var c=document.getElementById(nodeid+'_children');
		if(c.style.display=='none'){
			//n.className=thisObj.BranchTextSelectedCssClass;
			//n.setAttribute('selected','true');
			img.src='/images/minus2.gif';
			img.alt='collapse';
			c.style.display='block';
			//node.Selected=true;
		}else{
			//n.className=thisObj.BranchTextCssClass;
			//n.setAttribute('selected','false');
			img.src='/images/plus2.gif';
			img.alt='expand';
			c.style.display='none';			
			//node.Selected=false;
		}
	}
	function _onload(){
       if(_funcOnLoad!=null)
            _funcOnLoad(this);
    }
    function _onhighlight(divobj,isLeaf,on){
		var cls;
		if(isLeaf || this.DisableExpandCollapse){
			if(on)
				cls=this.LeafTextHoverCssClass;
			else{
				if(divobj.getAttribute('selected')=='false')
					cls=this.LeafTextCssClass;
				else
					cls=this.LeafTextSelectedCssClass;
			}
		}else{
			if(on)
				cls=this.BranchTextHoverCssClass;
			else{
				if(divobj.getAttribute('selected')=='false')
					cls=this.BranchTextCssClass;
				else
					cls=this.BranchTextSelectedCssClass;
			}
		}
		
		_mousePass(divobj,cls);
		
    }
    
    function _resize(w,h){
		var d=document.getElementById(this.ID);
		if(w)
			d.style.width=w+'px';
		if(h)
			d.style.height=h+'px';
    }
    
    function _render(){
		
		if(this.NodeCollection==null)
			return;
		var output='';
		output+=__render(this.NodeCollection.Nodes,0,this,null);
		
		document.getElementById(this.ID).innerHTML=output;
    }
    
    function __render(nodelist,parentindx,thisObj,parentnode){
		if(nodelist==null)
			return;
		
		var output='';
		var node;
		for(var n=0;n<nodelist.length;n++){
			var x=parentindx+'$'+n;
			node=nodelist[n];
			node.CancelClick = false;
			node.UniqueID=thisObj.ID+'$'+x;
			/*if(_selectedNodeValues){
				if(_inArray(node.Value,_selectedNodeValues)){
					node.Selected=true;
					if(parentnode){
						var pNode=new TreeNode();
						pNode.UniqueID=parentnode.UniqueID;
						pNode.SetSelected(true);
					}
				/*	parentnode.Selected=true;
					parentnode.Expanded=true;*
				}else{
					node.Selected=false;
				}
			}*/
			var _branchimg='';
			
			output+='<div style="white-space:nowrap;height:28px;"> ';
			if(thisObj.LBranchImage!=null && thisObj.TBranchImage!=null && parentindx!=0 && !thisObj.IsDownlevelBrowser){
				if(n==nodelist.length-1){
					_branchimg=thisObj.LBranchImage;
				}else
					_branchimg=thisObj.TBranchImage;
				output+='<span><img border="0" src="'+_branchimg+'"></span>';
			}

			output+='<span ';
			output+='id="'+node.UniqueID+'"';
			output+=' value="'+node.Value+'"';
			output+=' selected="'+node.Selected+'"';
			if(thisObj.SelectionMode==enumSelectionMode.Single && node.Selected) 
				_currentlySelectedLeaf=node;
			output+=' class="';
			var cssclass;
			var csshover;
			var csssel;
			var cssdis;
			if(node.NodeCollection.Nodes.length>0 && !thisObj.DisableExpandCollapse){
				cssclass=thisObj.BranchTextCssClass;
				csshover=thisObj.BranchTextHoverCssClass;
				csssel=thisObj.BranchTextSelectedCssClass;	
				cssdis=thisObj.BranchTextDisabledCssClass
			}else{
				cssclass=thisObj.LeafTextCssClass;
				csshover=thisObj.LeafHoverTextCssClass;
				csssel=thisObj.LeafTextSelectedCssClass;	
				cssdis=thisObj.LeafTextDisabledCssClass
			}
			if(!node.Enabled){
				output+=cssdis;
			}else if(node.Selected){
				output+=csssel;
			}else{
				output+=cssclass;			
			}
			output+='"';
			if(node.Enabled){
				output+=' onclick="';
				var isLeaf;
				if(node.NodeCollection.Nodes.length>0){
					output+=thisObj.VariableName+'.OnClick(\''+node.UniqueID+'\',false,event)';	
					if(thisObj.DisplayCheckBoxes){
						output+=';'+thisObj.VariableName+'.CheckChildren(document.getElementById(\''+node.UniqueID+'_cb\'),\''+node.UniqueID+'\',event);';	
					}
					isLeaf=false;			
				}else{
					output+=thisObj.VariableName+'.OnClick(\''+node.UniqueID+'\',true,event)';				
					isLeaf=true;
				}
				output+='"';
				output+=' onmouseover="'+thisObj.VariableName+'.OnHighLight(this,'+isLeaf+',true);"'
				output+=' onmouseout="'+thisObj.VariableName+'.OnHighLight(this,'+isLeaf+',false);"'
			}
			output+='>';
			
			var expalt='expand';
			var expimg='/images/plus2.gif';
			if(node.NodeCollection.Nodes.length==0){
				expimg='/images/none.gif';
				expalt='';
			}else if(node.Selected || node.Expanded){
				expimg='/images/minus2.gif';
				expalt='collapse';
			}
			output+='<img cancelclick="true" border="0" src="'+expimg+'" alt="'+expalt+'" onclick="'+thisObj.VariableName+'.OnExpandCollapse(this,\''+node.UniqueID+'\');">';
			
			if(node.IconPath){
				output+='<img id="'+node.UniqueID+'_icon" border="0" src="'+node.IconPath+'" ';
				if(node.IconToolTip)
					output+='alt="'+node.IconToolTip+'"';
				output+='>&nbsp;';
			}
			
			if(thisObj.DisplayCheckBoxes){
				var disabled='';
				if(!node.Enabled)
					disabled='disabled';
				var checked='';
				
				if(!isLeaf){
				//	if(_getnodeRecursive(thisObj,node.NodeCollection)){
				//		checked='checked';
				//	}
					//output+='<input '+checked+' '+disabled+' type=checkbox id="'+node.UniqueID+'_cb" onclick="'+thisObj.VariableName+'.CheckChildren(this,\''+node.UniqueID+'\');">';
					if(node.Selected)
						checked='checked';
					output+='<input '+checked+' '+disabled+' type=checkbox id="'+node.UniqueID+'_cb" >';
				}else{
					if(node.Selected)
						checked='checked';
					output+='<input '+checked+' '+disabled+' type=checkbox id="'+node.UniqueID+'_cb" >';
				}
			}
			
			output+='<span id="'+node.UniqueID+'_text" style="line-height:28px;">'
			output+=node.Text;
			output+='</span>';
			
		
			
			output+='</span>';
			output+='</div>';
			if(node.NodeCollection.Nodes.length>0){	
				var display='none';
				if(node.Selected || thisObj.DisableExpandCollapse || node.Expanded)
					display='block';
				output+='<span id="'+node.UniqueID+'_children"';
				output+=' style="'
				if(!thisObj.IsDownlevelBrowser){
					output+='border-right:dashed 1px #a9a9a9;'
				}
				output+='width:10px;position:relative;top:0px;left:'+(thisObj.ChildOffset)+'px;display:'+display+';"';
				output+='>';
				if(n==(nodelist.length-1)){
					output+='<div style="border-left:solid 1px white;white-space:nowrap;height:'+(28*node.NodeCollection.Nodes.length)+'px;position:absolute;left:-10px;top:0px;"></div> ';
				}
				output+=__render(node.NodeCollection.Nodes,x,thisObj,node);
				output+='</span>';
			}
		}
		return output;
    }
    function _setnodetext(node,text){
		node.Text=text;
		document.getElementById(node.UniqueID+'_text').innerHTML=text;
    }
    function _setnodeicon(node,iconpath){
		node.IconPath=iconpath;
		document.getElementById(node.UniqueID+'_icon').src=iconpath;
    }
}

function TreeNodeCollection(){
	this.Nodes=new Array();
}

function TreeNode(){
	this.Text='';
	this.IconPath;
	this.Value=null;
	this.Selected=false;
	this.ChildNodes;
	this.SetText=_setText;
	this.SetValue=_setVal;
	this.UniqueID=null;
	this.CommandArgument=null;
	this.Enabled=true;
	this.IconToolTip='';
	this.NodeCollection=null;
	this.Expanded=false;
	this.TreatAsLeaf=false;
	
	function _setText(value){
		this.Text=value;
		document.getElementById(this.UniqueID).innerHTML=value;
	}
	function _setVal(value){
		this.Value=value;
		document.getElementById(this.UniqueID).setAttribute("value",value);
	}
}