﻿/// protected:
//	Interfesz specifikacio a fa megjelenito egy elemehez
//	Főleg funkcionális elemeket tartalmaz
function CTreeItem(strID, strName, iLevel, bChecked, bOpened, bShowInTree)
{
	this.strID = (strID != undefined && strID != null ? strID : "");
	this.strName = (strName != undefined && strName != null ? strName : "");
	this.iLevel = (iLevel != undefined && iLevel != null ? iLevel : 0);
	this.bChecked = (bChecked ? true : false);
	this.bOpened = (bOpened ? true : false);
	this.bShowInTree = (bShowInTree != undefined ? bShowInTree : true);
	

	this.pParent = null;  // szülő
	this.pBrother = null; // a szülő következő gyereke
	this.pChild = null;   // első gyerek

	this.tr = null; // A megjelenitett TR
	this.checkbox = null; // A megjelenitett input check box

	// Events
	this.OnOpen =  null; //function(pItem) {}
	this.OnClose = null; //function(pItem) {}
	this.OnCheckChanged = null; //function(pItem) {} // Minden egyes checkbox érték változáskor meghívódik (rekurzív változásokkor is)
	this.OnCheckChangeEnded = null; // function() {}; // Egy SetCheckBox hívás által generált állapotváltozás végén hívódik csak meg.
	
	var me = this;

	
	//protected:
	// Beallitja a fa kapcsolatokat, pParent: szülö, pStepBrother: testvér, ha pStepBrother = null
	this.SetRelations = function(pParent, pStepBrother)
	{
		me.pParent = pParent;
		if(pParent && (pParent.pChild == null)) // Ő az elso gyerek
		{
			pParent.pChild = me;
		}
		else
		{
			var pBrother = null;
			if(pParent)
			{
				pBrother = pParent.pChild; 
				while(pBrother.pBrother != null)
					pBrother = pBrother.pBrother;
			}
			else
				pBrother = pStepBrother;  //előző gyökérelem tesója lesz
			if(pBrother)
					pBrother.pBrother = me; // utso gyerek tesója lesz
		}
	}
	
	// protected:
	// Vissza adja az elem azonosítóját
	this.GetID = function()
	{
		return me.strID;
	}

	// protected:
	// Megjelenítendő név a fán
	this.GetName = function()
	{
		return me.strName;
	}
	
	// protected:
	// Ez az elem hanyadik szinten van a fan
	this.GetLevel = function()
	{
		return me.iLevel;
	}
	
	// protected:
	// Az elemhez tartozo checkbox be van-e pipalva
	this.IsChecked = function()
	{
		return me.bChecked;
	}
	
	// protected:
	// Checkbox érték változtatása
	this.SetChecked = function(bChecked)
	{
		me.bChecked = bChecked;
		// Összes gyerekére is beállitjuk, kivéve a rejtett elemekre
		var arrChildren = me.GetAllChildren();
		for(var i=0; i<arrChildren.length; i++)
		{
			if(!arrChildren[i].bShowInTree)
				continue;
			if(arrChildren[i].bChecked != bChecked)
			{
				arrChildren[i].bChecked = bChecked;
				if(arrChildren[i].OnCheckChanged)
					arrChildren[i].OnCheckChanged(arrChildren[i]);
			}
		}
		
		// A szülők között be kell kapcsolni azokat, amelyeknek összes gyerek be van, a többit pedig ki.
		for(var pParent = me.pParent; pParent; pParent = pParent.pParent)
		{
			var bParentCheck = false;
			for(var pBrother = pParent.pChild; pBrother; pBrother = pBrother.pBrother)
			{
				if(pBrother.bChecked)
					bParentCheck = true;
				else
				{
					bParentCheck = false;
					break;
				}
			}
			if(pParent.bChecked != bParentCheck)
			{
				pParent.bChecked = bParentCheck;
				if(pParent.OnCheckChanged)
					pParent.OnCheckChanged(pParent);
			}
		}
		if(me.OnCheckChanged)
			me.OnCheckChanged(me);
		if(me.OnCheckChangeEnded)
			me.OnCheckChangeEnded();
	}
	
	// protected:
	// Átállítja a checkbox értéket az ellenkezőjére
	this.ChangeCheck = function()
	{
		me.SetChecked(!me.bChecked)
	}
	
	// protected:
	// Nyitva van ez az elem (gyerekei latszanak-e ha o is latszik)
	this.IsOpened = function()
	{
		return me.bOpened;
	}
	
	// protected:
	// Kinyitja az alfat
	this.Open = function()
	{
		me.bOpened = true;
		if(me.OnOpen)
			me.OnOpen(me);
	}
	
	// protected:
	// becsukja az alfat
	this.Close = function()
	{
		me.bOpened = false;
		
		var arrChildren = me.GetAllChildren();
		for(var i=0; i<arrChildren.length; i++)
		{
			arrChildren[i].m_bOpened = false;
		}
		
		if(me.OnClose)
			me.OnClose(me);
	}
	
	// private:
	this.Switch = function()
	{
		if(me.bOpened)
			me.Close();
		else
			me.Open();
	}
	
	// proteced:
	this.GetTR = function()
	{
		return me.tr;
	}
	// protected
	this.SetTR = function(tr)
	{
		me.tr = tr;
		me.checkbox = null;
	}
	
	// private:
	// Visszadja a checkbox input elemet
	this.GetCheckBox = function()
	{
		return me.checkbox;
	}
	// private:
	this.SetCheckBox = function(checkbox)
	{
		me.checkbox = checkbox;
	}

	// private:
	// Egy adott szintű szülőt ad vissza
	this.GetParent = function(iLevel)
	{
		var pParent = null;
		if(iLevel < me.GetLevel())
		{
			pParent = me.pParent;
			while(pParent && pParent.GetLevel() != iLevel)
				pParent = pParent.pParent;
		}
		return pParent;
	}
	// private:
	// A tényleges, látványban is szereplő tesója
	this.GetRealBrother = function()
	{
		if(me.pBrother)
		{
			if(me.pBrother.bShowInTree)
				return me.pBrother;
			else
				return me.pBrother.GetRealBrother();
		}
		return null;
	}

	// protected:
	// Visszaadja egy elem összes gyerekét, unokáját, stb..
	this.GetAllChildren = function()
	{
		var arrChildren = new Array();
		var pChild = me.pChild;
		while(pChild)
		{
			arrChildren[arrChildren.length] = pChild;
			if(pChild.pChild)
				pChild = pChild.pChild;
			else if(pChild.pBrother)
				pChild = pChild.pBrother;
			else {
				var pParent = pChild.pParent;
				while(pParent && !pParent.pBrother && (pParent != me))
				{
					pParent = pParent.pParent;
				}
				if(pParent)
					pChild = pParent.pBrother;
				else
					pChild = null;

				if(pParent == me)
					break;
			}
		}
		return arrChildren;
	}

	// Fa mátrix képek
	TREE_NULL = 0; // üres
	TREE_T = 1;    // kiágazás
	TREE_L = 2;    // utolsó kiágázás 
	TREE_I = 3;    //

	//private:
	// Adott szinten milyen fa alakzat tartozik
	this.GetTreeType = function(iLevel)
	{
		if(iLevel == me.GetLevel())
		{
			if(me.GetRealBrother())
				return TREE_T; // van meg tesója tehát leágazás van itt
			else
				return TREE_L; // utolsó gyerek : kanyar
		}
		else if(iLevel < me.GetLevel())
		{
			if(me.GetParent(iLevel).GetRealBrother())
				return TREE_I;
		}
		return TREE_NULL;
	}
	
	//private:
	this.GetTreeClass = function(iLevel)
	{
		var strClass = "";
		switch(me.GetTreeType(iLevel))
		{
			case TREE_L: strClass = "treeL"; break;
			case TREE_T: strClass = "treeT"; break;
			case TREE_I: strClass = "treeI"; break;
			case TREE_NULL: strClass = "tree0"; break;
		}
		return strClass;
	}

	this.GetTreeIcon = function(iLevel)
	{
		var strUrl = "transparent.gif";
		if(!me.pChild)
			strUrl = "line";
		else if(me.IsOpened())
			strUrl = "minus";
		else
			strUrl = "plus";
			
		switch(me.GetTreeType(iLevel))
		{
			case TREE_L:
				strUrl += "_l.gif";
				break;
			case TREE_T:
				strUrl += "_t.gif";
				break;
			case TREE_I:
				strUrl = "line_i.gif";
				break;
			case TREE_NULL:
				strUrl = "transparent.gif";
				break;
		}
		return strUrl;
	}

}



// protected:
// fa megjelenito
// div: A div amiben felrajzolja a fat
// arrItems: CTreeItem fuggvenyeivel biro elemek tombje,
// meghozzá a fa melysegi bejárás sorrendjében

// Főleg a megjelenítésre a koncentrál, az ész inkább a CTreeItem-ben van
function CTree(div, arrItems)
{
	this.div = div;  // teljes div
	this.table = null;   // Dinamikusan létrejövő táblázat
	this.arrItems = arrItems;
	
	this.iMaxLevel = 0;  // Maximum szintek szama
	this.iColCount = 0;  // A táblázat oszlopainak száma		
	this.OnCheckChecked = null; // function(pItem){} // Akkor hívódik meg, ha változás áll be a checkboxok állapotában
	this.bEnabled = true;
	var me = this;
	
	
	
	//private:
	this.Init = function()
	{
		me.SetItems(arrItems);
		me.bEnabled = true;
	}
	
	this.Reset = function ()
	{	
	    me.UncheckAll ();    	    
	    me.arrItems[0].Close ();			
	    
	    var i = 0;
	    for (i = 0; i < me.arrItems.length; i++)
	    {
			try
			{
				me.arrItems[i].checkbox.checked = false;
				me.arrItems[i].Close ();
				//me.arrItems[i].checkbox.value = "off";
			}
			catch (x)
			{
			}		
		}
	    me.Enable ();
	}
	
	//protected:
	// visszaadja a fa elemeit
	this.GetItems = function()
	{
		return me.arrItems;
	}
	
	//protected:
	//beállitja a fa elemeit
	this.SetItems = function(arrItems)
	{
		me.arrItems = arrItems
		me.iMaxLevel = 0;
		var pLastOrphan = null; // Az utso olyan item, akinek nincs szuloje.
		if(arrItems)
		{
			var pParent = null;
			var iLevel = 0;
			var pPrevItem = null;
			for(var i=0; i<arrItems.length; i++)
			{
				var pItem = arrItems[i];
				if(pPrevItem != null)
				{
					if(pPrevItem.GetLevel() < pItem.GetLevel())
						pParent = pPrevItem;
					else if(pPrevItem.GetLevel() > pItem.GetLevel())
					{
						pParent = pPrevItem.GetParent(pItem.GetLevel()-1);
					}
				}
				pItem.SetRelations(pParent, pLastOrphan);
				if(pParent == null)
					pLastOrphan = pItem;
				pItem.OnOpen = me.OnOpenNode;
				pItem.OnClose = me.OnCloseNode;
				pItem.OnCheckChanged = me.OnCheckNodeChangedInternal;
				pItem.OnCheckChangeEnded = me.OnCheckChangedInternal;

				if(me.iMaxLevel < pItem.GetLevel())
					me.iMaxLevel = pItem.GetLevel();

				pPrevItem = pItem;
			}
		}
		me.iColCount = me.iMaxLevel + 3;
	}
	
	//protected:
	// Megjeleniti a fat
	this.Show = function()
	{
		if(me.div)
		{
			while(me.div.firstChild)
				me.div.removeChild(me.div.firstChild);
			
			var table = NewTag("table");
			table.cellPadding = 0;
			table.cellSpacing = 0;
			table.setAttribute("border", "0");
			me.table = NewTag("tbody", table);
			AddTag(table, me.div);
			
			var bRowVisible = true;
			var iSkipLevel = 0;
			for(var i=0; i<me.arrItems.length; i++)
			{
				if(!me.arrItems[i].bShowInTree)
					continue;
				if(!bRowVisible)
				{
					if(me.arrItems[i].GetLevel() > iSkipLevel)
						continue;
					bRowVisible = true;
				}
				if(bRowVisible)
				{
					me.ShowNode(me.arrItems[i], null);
					if(me.arrItems[i].pChild && !me.arrItems[i].IsOpened())
					{
						iSkipLevel = me.arrItems[i].GetLevel();
						bRowVisible = false;
					}
				}
			}
		}
	}
	// protected:
	// Egy adott fa elemhez tartozó sort jelenít meg
	this.ShowNode = function(pItem, trBefore)
	{
		var tr = NewTag('tr', me.table, trBefore);
		
		pItem.SetTR(tr);

				// Fa ikonok
		for(var iTreeLevel = 0; iTreeLevel <= pItem.GetLevel(); iTreeLevel++)
		{
			td = NewTag('td', tr);
			td.className = pItem.GetTreeClass(iTreeLevel);
			img = NewTag('img');
			SetImage(img, 'images/tree/' + pItem.GetTreeIcon(iTreeLevel), 19, 16);
			
			if(pItem.pChild && (iTreeLevel == pItem.GetLevel()) )
			{
				a = NewTag('a', td);
				a.setAttribute('href','javascript:void(0)');
				a.onclick = pItem.Switch;
				AddTag(img, a);
			}
			else
				AddTag(img, td);
		}

		// Checkbox
		td = NewTag('td', tr);
		td.setAttribute('width', 16);
		td.className = "treeCheckbox";
		var input = NewTag('input');
		input.className = "treeCheckbox";
		input.setAttribute('type', 'checkbox');
		AddTag(input, td);
		input.checked = pItem.IsChecked();
		input.onclick = pItem.ChangeCheck;
		pItem.SetCheckBox(input);

		//Szöveg
		var iColSpan  = me.iColCount - (pItem.GetLevel()+2) ; // Szöveg hány oszlopot foglaljon el
		td  = NewTag('td', tr);
		td.className = 'treeText';
		//td.setAttribute('colSpan', iColSpan);
		td.colSpan = iColSpan;
		td.width = '99%';
		a = NewTag('a', td);
		a.className = 'treeText';
		NewTextTag(pItem.GetName(), a);
		a.onclick = pItem.ChangeCheck;

		if(pItem.pChild)
			a.ondblclick = pItem.Switch;
	}

	//protected:
	// Egy részfa logikai kinyitása után felrajzolja a részfát
	this.OnOpenNode = function(pItem)
	{
		// A következő elem elé kell illeszteni (testvér vagy szülő testvére)
		var pSister = pItem;
		while(pSister && !pSister.GetRealBrother())
			pSister = pSister.pParent;

		var trBefore = (pSister ? pSister.GetRealBrother().GetTR() : null);
		
		for(var pChild = pItem.pChild; pChild != null; pChild = pChild.pBrother)
		{
			if(pChild.bShowInTree)
			me.ShowNode(pChild, trBefore);
		}
		
	}

	//protected:
	//Letörli a becsukott részfát
	this.OnCloseNode = function(pItem)
	{
		var arrChildren = pItem.GetAllChildren();
		for(var i=0; i<arrChildren.length; i++)
		{
			var tr = arrChildren[i].GetTR();
			if(tr && tr.parentNode)
				tr.parentNode.removeChild(tr);
			arrChildren[i].SetTR(null);
		}
	}
	//private:
	// Minden CTreeItem változásra meghívódik
	this.OnCheckNodeChangedInternal = function(pItem)
	{
		var input = pItem.GetCheckBox();
		if(input)
			input.checked = pItem.IsChecked();
	}
	
	//private:
	// Meghívódik, ha lefutott egy teljes rekurzív checkbox állapotváltás
	this.OnCheckChangedInternal = function(pItem)
	{
		if(me.OnCheckChanged)
			me.OnCheckChanged()
	}
	
	// protected:
	// Visszaadja a /legtömörebb formában kéne/ sztringben, hogy mely elemek vannak bekapcsolva
	// (Ha a szulo be van kapcsolva, akkor a gyerekei nem szerepelnek a listában)
	this.GetCheckedIDsInStr = function()
	{
		return me.GetCheckedIDsInStrINNER(me.arrItems[0]);
	}	
	
	this.GetCheckedIDsInStrINNER = function(item)
	{
	    var retval = ""; // 5|7|12|19	    
	    
	    while (item != null)
	    {
           if (item.IsChecked())
           {
                retval = retval + "|" + item.GetID ();
                item = item.pBrother;
           }
           else
           {
				var temp = me.GetCheckedIDsInStrINNER(item.pChild);
				if (temp != "")
					retval = retval + "|" + temp;
				
				item = item.pBrother;
           }	    
	    }
	    	    
        retval = retval.substring (1);                	    	    
	    return retval;
	}
	
	this.UncheckAll = function ()
	{
		var i;	    
		for (i = 0; i < me.arrItems.length; i++)
		{
			var item = me.arrItems[i];
			if (item != null && item.bShowInTree)
			{
					item.bChecked = false;
			}
		}
	}

	this.CheckAll = function ()
	{
		var i;
		for (i = 0; i < me.arrItems.length; i++)
		{
			var item = me.arrItems[i];
			if (item != null && item.bShowInTree)
			{
				item.bChecked = true;
			}
		}
	}

	this.Disable = function ()
	{	    
	    var i;	    
	    for (i = 0; i < me.arrItems.length; i++)
	    {
            var item = me.arrItems[i];
            if (item != null)
            {
                if (item.checkbox != null)
                    item.checkbox.disabled = "true";
            }	       
	    }
	    me.bEnabled = false;
	}

	this.Enable = function ()
	{
	    var i;	    
	    for (i = 0; i < me.arrItems.length; i++)
	    {
            var item = me.arrItems[i];
            if (item != null)
            {
                if (item.checkbox != null)
                    item.checkbox.disabled = "";
            }	       
	    }
	    me.bEnabled = true;
	}

	// Visszaadja a legtömörebb formában, hogy mely elemek vannak nyitva
	// (Ha a szulo be van kapcsolva, akkor a gyerekei nem szerepelnek a listában)
	this.GetOpenedIDs = function()
	{
	}

	this.Init();
}
