

//<script>

//=======
// CNode
//=======
function CNode(id, text, value)
{
	this.id = id;
	this.text = text;
	this.value = value;
	this.child = [];
	this.parent = [];
	return this;
}

CNode.prototype.addParent
=//======================
function (node)
{
	this.parent[this.parent.length] = node;
	node.child[node.child.length] = this;
	return node;
}

CNode.prototype.addChild
=//=====================
function (node)
{
	this.child[this.child.length] = node;
	node.parent[node.parent.length] = this;
	return node;
}

CNode.prototype.findChildById
=//==========================
function (id)
{
	for (var i=0; i<this.child.length; i++)
		if ( this.child[i].id == id )
			return this.child[i];
	return null;
}

CNode.prototype.findChildByText
=//============================
function (text)
{
	for (var i=0; i<this.child.length; i++)
		if ( this.child[i].text == text )
			return this.child[i];
	return null;
}


//===========
// CTreeView
//===========
function CTreeView(id)
{
	this.id = id;
	this.cls = "CTreeView";

	this.root = new CNode(0, "root");
	this.all = [this.root];
	this.selected = null;
	this.opened = null;
	
	this.checked = false;
	this.icon = true;
	this.expand = false;
	
	this.onopen = function(node, lastOpen){};
	this.onselect = function(nodeSelected, nodeUnselected){};
	this.ondblclick = function(node){};
	this.oncheck = function(node, checkbox){};

	this.status = new CStatus(id);
	this.beforeSerialize = EmptyFunction;
	this.status.beforeSerialize = function()
	{
		var target = eval(this.owner);
		target.beforeSerialize();
		this.clientStatus.openedId = target.opened.id;
	}
	this.afterDeserialize = function()
	{
		if (this.status.clientStatus.openedId != null)
			this.open(this.status.clientStatus.openedId, true, true);
	}
	this.status.afterDeserialize = function()
	{
		var target = eval(this.owner);
		target.refresh();
		target.afterDeserialize();
	}
}

CTreeView.prototype.clear
=//======================
function CTreeView_clear()
{
	for (i in this.all)
		delete this.all[i];
	this.root = new CNode(0, "root");
	this.all = [this.root];
	this.selected = null;
	this.opened = null;
}

CTreeView.prototype.addNode
=//========================
function (parent, id, text, value, cls, custom, title, checked)
{
	if (IsEmpty(cls)) cls = this.cls;
	if (IsEmpty(custom)) custom = "";
	if (IsEmpty(title)) title = "";
	if (IsEmpty(checked)) checked = false;
	
	var node = new CNode(id, text, value);
	node.index = id; 
	node.cls = cls;
	node.custom = custom;
	node.title = title;
	node.checked = checked;
	this.all[id] = node;
	
	if (parent == null)
		parent = this.root;
	if (!isNaN(parseInt(parent, 10)))
		parent = this.all[parent];
	return parent.addChild(node);
}  

CTreeView.prototype.loadArray
=//==========================
function (nodeArray)
{
	var i, index, node, parent;
	var idParent, idNode, text, value, cls, custom, title;	
	this.clear();
	for (i=0; i<nodeArray.length; i++) 
	{
		idParent = nodeArray[i][0];
		idNode = nodeArray[i][1];
		text = nodeArray[i][2];
		value = nodeArray[i][3] == null ? null : nodeArray[i][3];
		cls = IsEmpty(nodeArray[i][4]) ? this.cls : nodeArray[i][4];
		custom = IsEmpty(nodeArray[i][5]) ? "" : nodeArray[i][5];
		title = IsEmpty(nodeArray[i][6]) ? "" : nodeArray[i][6];
		checked = IsEmpty(nodeArray[i][7]) ? false : nodeArray[i][7];
		
		node = new CNode(idNode, text, value);
		this.all[idNode] = node;
		node.index = idNode;
		node.cls = cls;
		node.custom = custom;
		node.title = title;
		node.checked = checked;
		node.idParent = idParent;
	}
	for (i in this.all)
	{
		parent = this.findNodeById(this.all[i].idParent);
		if ( parent != null )
			parent.addChild(this.all[i]);
	}
}

CTreeView.prototype.findNodeById
=//=============================
function (id)
{
	if (IsEmpty(this.all[id]))
		return null;
	return this.all[id];
}

CTreeView.prototype.findNodeByText
=//===============================
function (text)
{
	for (i in this.all)
		if (this.all[i].text == text)
			return this.all[i];
	return null;
}

CTreeView.prototype.nodeHTML
=//=========================
function (node)
{
	var i;
	var HTML = "";
	var baseId = this.id + "_" + node.index;
	var checked = (node.checked) ? "CHECKED" : "";
	var expand = this.expand ? this.cls +"-sign-clsTD-minus" : this.cls +"-sign-clsTD-plus";
	var hidden = node.hidden == true ? ' style="display: none;" ' : ' style="display: block;" ';
	if (node.child.length > 0)
	{
		HTML += '\n<DD CLASS="'+ this.cls + '-clsDD" ID="'+ baseId +'"'+ hidden +'>';
		HTML += '<TABLE CLASS="'+ node.cls + '-clsTABLE" CELLSPACING=0 CELLPADDING=0>';
		HTML += '<TR TITLE="'+ node.title +'">';
		HTML += '<TD CLASS="'+ this.cls +'-clsFont '+ expand +'" NOWRAP ID="'+ baseId +'_sign" NAME="+" onmousedown="'+ this.id +'.evexpand(\''+ node.index +'\', event);">&nbsp;</TD>';
		if (this.checked)
			HTML += '<TD CLASS="'+ this.cls +'-clsTD-check" NOWRAP ID="'+ baseId +'_check"><INPUT TYPE="checkbox" CLASS="'+ this.cls +'-clsCHECKBOX" ID="'+ this.id +'_idCHECK_'+ node.index +'" '+ checked +' onclick="'+ this.id +'.check('+ this.id +'.all['+ node.index +'], this);"></TD>';
		if (this.icon)
			HTML += '<TD CLASS="'+ this.cls +'-clsFont '+ node.cls +'-icon-clsTD-close" NOWRAP ID="'+ baseId +'_icon" onmousedown="'+ this.id +'.select(\''+ node.index +'\', event);" onclick="'+ this.id +'.open(\''+ node.index +'\', event);" ondblclick="'+ this.id +'.evexpand(\''+ node.index +'\', event);">&nbsp;</TD>';
		HTML += '<TD CLASS="'+ this.cls +'-clsFont '+ this.cls +'-text-clsTD-normal" NOWRAP ID="'+ baseId +'_text" onmousedown="'+ this.id +'.select(\''+ node.index +'\', event);" onclick="'+ this.id +'.open(\''+ node.index +'\', event);" ondblclick="'+ this.id +'.evexpand(\''+ node.index +'\', event);">'+ node.text +'</TD>';
		HTML += '<TD CLASS="'+ this.cls +'-clsFont '+ this.cls +'-custom-clsTD-normal" ID="'+ baseId +'_custom" NOWRAP>'+ node.custom +'</TD>';
		HTML += '</TR></TABLE></DD>';
		// sub folder
		HTML += '\n<DL ID="'+ baseId +'_sub" CLASS="'+ this.cls +'-clsDL" STYLE="display: '+ (this.expand ? "block" : "none") +';">';
		for (i=0; i<node.child.length; i++)
			HTML += this.nodeHTML(node.child[i]);
		HTML += '</DL>';
	}
	else
	{
		HTML += '\n<DD CLASS="'+ this.cls +'-clsDD" ID="' + baseId + '"'+ hidden +'>';
		HTML += '<TABLE CLASS="'+ node.cls +'-clsTABLE" CELLSPACING=0 CELLPADDING=0>';
		HTML += '<TR TITLE="'+ node.title +'">';
		HTML += '<TD CLASS="'+ this.cls +'-clsFont '+ this.cls +'-sign-clsTD-none" NOWRAP STYLE="text-align: center;">&nbsp;</TD>';
		if (this.checked)
			HTML += '<TD CLASS="'+ this.cls +'-clsTD-check" NOWRAP ID="'+ baseId +'_check"><INPUT TYPE="checkbox" CLASS="'+ this.cls +'-clsCHECKBOX" ID="'+ this.id +'_idCHECK_'+ node.index +'" '+ checked +' onclick="'+ this.id +'.check('+ this.id +'.all['+ node.index +'], this);"></TD>';
		if (this.icon)
			HTML += '<TD CLASS="'+ this.cls +'-clsFont '+ node.cls +'-icon-clsTD-close" ID="' + baseId + '_icon" NOWRAP onmousedown="'+ this.id +'.select(\''+ node.index +'\', event);" onclick="'+ this.id +'.open(\''+ node.index +'\', event);">&nbsp;</TD>';
		HTML += '<TD CLASS="'+ this.cls +'-clsFont '+ node.cls +'-text-clsTD-normal" ID="'+ baseId +'_text" NOWRAP onmousedown="'+ this.id +'.select(\'' + node.index + '\', event);" onclick="'+ this.id +'.open(\''+ node.index +'\', event);" ondblclick="'+ this.id +'.ondblclick(\''+ this.id +'.all['+ node.index +']\');">'+ node.text +'</TD>';
		HTML += '<TD CLASS="'+ this.cls +'-clsFont '+ node.cls +'-custom-clsTD-normal" ID="'+ baseId +'_custom" NOWRAP>'+ node.custom +'</TD>';
		HTML += '</TR></TABLE></DD>';
	}
	return HTML;
}

CTreeView.prototype.HTML
=//=====================
function ()
{
	var HTML = '<DIV onselectstart="return false;" onmousedown="return false;" ID="' + this.id + '_idDIV" CLASS="' + this.cls + '-clsDIV"><DL CLASS="' + this.cls + '-clsDL-root" ID="' + this.id + '">';
	for (var i=0; i<this.root.child.length; i++)
		HTML += this.nodeHTML(this.root.child[i]);
	HTML += '\n</DL></DIV>';
	return HTML;
}  

CTreeView.prototype.writeHTML
=//==========================
function () { document.write(this.HTML()) }  

CTreeView.prototype.refresh = function ()
{ 
	var target= document.getElementById(this.id);
	var HTML = "";
	for (var i=0; i<this.root.child.length; i++)
		HTML += this.nodeHTML(this.root.child[i]);
	HTML += '\n</DL>';
	target.innerHTML = HTML;
}  


CTreeView.prototype.evexpand
=//=========================
function (index, e)
{
	if (IE) e = window.event;	
	if (e.altKey || e.ctrlKey || e.shiftKey)
		this.expandAll(index);
	else	
		this.expandNode(this.all[index]);
}

CTreeView.prototype.expandNode
=//===========================
function (node)
{
	var prefix = this.id +"_"+ node.index;
	var sign = document.getElementById(prefix +"_sign");
	if (sign == null)
		return;
	var sub = document.getElementById(prefix +"_sub");
	if (sign.className.search(/-clsTD-plus/) > 0)
	{
		sub.style.display = "block";
		sign.className = sign.className.replace(/-sign-clsTD-plus/, "-sign-clsTD-minus"); 
	}
	else
	{
		sub.style.display = "none";
		sign.className = sign.className.replace(/-sign-clsTD-minus/, "-sign-clsTD-plus"); 
	}
}

CTreeView.prototype.expandAll
=//==========================
function (index, bExpand)
{
	if (bExpand == null)
	{
		var sign = document.getElementById(this.id +"_"+ index +"_sign");
		if (sign == null)
			return;
		bExpand = (sign.className.search(/-clsTD-plus/) > 0) ? true : false;
	}
	this.expandAllChild(index, bExpand);
}

CTreeView.prototype.expandAllChild
=//===============================
function (index, bExpand)
{
	var node = this.all[index];
	if (IsEmpty(node))
		return;
	for (var i=0; i<node.child.length; i++)
		if ( node.child[i].child.length )
			this.expandAllChild(node.child[i].index, bExpand);	
	var prefix = this.id + "_" + index;
	var sign = document.getElementById(prefix +"_sign");
	if (sign == null)
		return;
	var sub = document.getElementById(prefix +"_sub");
	if (bExpand)
	{
		sub.style.display = "block";
		sign.className = sign.className.replace(/-sign-clsTD-plus/, "-sign-clsTD-minus"); 
	}
	else
	{
		sub.style.display = "none";
		sign.className = sign.className.replace(/-sign-clsTD-minus/, "-sign-clsTD-plus"); 
	}
}

CTreeView.prototype.expandAllParent
=//================================
function (index, bExpand)
{
	var node = this.all[index];
	if (IsEmpty(node))
		return;
	if (node.parent.length > 0)
		this.expandAllParent(node.parent[0].index, bExpand);
	var prefix = this.id + "_" + index;
	var sign = document.getElementById(prefix +"_sign");
	if (sign == null)
		return;
	var sub = document.getElementById(prefix +"_sub");
	if (bExpand)
	{
		sub.style.display = "block";
		sign.className = sign.className.replace(/-sign-clsTD-plus/, "-sign-clsTD-minus"); 
	}
	else
	{
		sub.style.display = "none";
		sign.className = sign.className.replace(/-sign-clsTD-minus/, "-sign-clsTD-plus"); 
	}
}

CTreeView.prototype.check
=//======================
function(node, checkbox)
{
	node.checked = checkbox.checked;	
	this.oncheck(node, checkbox);
};

CTreeView.prototype.checkAll
=//=========================
function (index, bCheck, bUncheckParent)
{
	if (bCheck == null) bCheck = this.all[index].checked;
	if (bUncheckParent == null) bUncheckParent = true;
	this.checkAllChild(index, bCheck);
	if (bUncheckParent)
		this.checkAllParent(index, false);
}

CTreeView.prototype.checkAllChild
=//==============================
function CTreeView_checkAllChild(index, bCheck)
{
	var node = this.all[index];
	if (IsEmpty(node))
		return;
	for (var i=0; i<node.child.length; i++)
		this.checkAllChild(node.child[i].index, bCheck);	
	node.checked = bCheck;
	document.getElementById(this.id +'_idCHECK_'+ index).checked = node.checked;
}

CTreeView.prototype.checkAllParent
=//===============================
function CTreeView_checkAllParent(index, bCheck)
{
	var parent;
	var node = this.all[index];
	if (IsEmpty(node))
		return;
	for (var i=0; i<node.parent.length; i++)
	{
		parent = node.parent[i];
		if (parent.id==0)
			break;
		parent.checked = bCheck;
		document.getElementById(this.id +'_idCHECK_'+ parent.index).checked = parent.checked;
		this.checkAllParent(parent.index, bCheck);
	}
}

CTreeView.prototype.open
=//=====================
function (index, bNotify, bParent)
{
	if (IsEmpty(bNotify)) bNotify = true;
	if (IsEmpty(bParent)) bParent = false;
	
	var target; 
	var lastOpened = this.opened;	
	if (lastOpened != null)
	{
		target = document.getElementById(this.id +"_"+ this.opened.index +"_icon");
		if (target != null)
			target.className = target.className.replace(/-open/g, "-close");
	}
	
	if (bParent)
		this.expandAllParent(index, true);

	this.opened = this.all[index];
	target = document.getElementById(this.id +"_"+ index +"_icon")
	if (target != null)
		target.className = target.className.replace(/-close/g, "-open");
	this.select(index);
	
	if (bNotify)
		this.onopen(this.opened, lastOpened);
}

CTreeView.prototype.select
=//=======================
function (index, bAction)
{
	if(bAction==null) bAction = true;
	var target;
	var prefix;
	var lastSelected = this.selected;
	if (lastSelected != null)
	{
		prefix = this.id +"_"+ lastSelected.index;
		target = document.getElementById(prefix +"_text")
		if (target != null)
			target.className = target.className.replace(/-selected/g, "-normal");
		target = document.getElementById(prefix +"_custom")
		if (target != null)
			target.className = target.className.replace(/-selected/g, "-normal");
	}
	if (index==null)
	{
		this.selected = null;
		return;
	}
	prefix = this.id +"_"+ index;
	this.selected = this.all[index];
	target = document.getElementById(prefix +"_text")
	if (target != null)
		target.className = target.className.replace(/-normal/g, "-selected");
	target = document.getElementById(prefix +"_custom")
	if (target != null)
		target.className = target.className.replace(/-normal/g, "-selected");
	if (bAction)
		this.onselect(this.selected, lastSelected);
}

CTreeView.prototype.showNode = function (index, bShow, bChild)
{
	bChild = bChild == null ? true : false;
	var node = this.all[index];
	node.hidden = !bShow;
	if (bChild)
		for (var i=0; i<node.child.length; i++)
			this.showNode(node.child[i].index, bShow, true);
}

//</script>
