/* ===========================================================*/
/* Copyright (c) 2007 by SDN AG, CH-8912 Obfelden Switzerland */
/* -----------------------------------------------------------*/
/* Project : easyLEARN skills4u                               */
/* -----------------------------------------------------------*/
/* $Id: dynamictree.js,v 1.10 2009/02/23 07:47:33 MWE Exp $  */
/* ============================================================*/
/*
History
=======
$Log: dynamictree.js,v $
Revision 1.10  2009/02/23 07:47:33  MWE
savetrackdata/allCompleted: Wenn alle Schritte bis auf den letzten Punkt "Abschliessen" erledigt sind, dann den letzten Schritt automatisch als erledigt markieren

Revision 1.9  2008/06/06 10:45:00  MWE
Neue Funktion Modified() / Eigenschaft bStatModified

Revision 1.8  2008/01/18 10:01:59  MWE
Titel als Hint anzeigen auch bei Ordnern

Revision 1.7  2007/11/14 15:28:39  MWE
Zusätzlicher Debug bei restoretrackid

Revision 1.6  2007/04/13 09:59:31  MWE
Release 4.4

Revision 1.5  2007/01/25 13:16:13  MWE
Neue Funktion restoretrackdata()

Revision 1.4  2006/11/07 09:49:00  MWE
Wenn der Node-Eintrag keinen Titel enthält dann den Namen als Titel verwenden damit dieser als Hint angezeigt wird

Revision 1.3  2006/11/03 08:58:41  MWE
Hinweis skipped nur noch anzeigen, wenn der neu angewählte Lernschritt ein Schritt vor dem aktuellen Lernschritt ist

Revision 1.2  2006/11/01 09:31:46  MWE
Neue Optionen InOrderCheck/CheckSkipped

Revision 1.1  2006/09/15 12:35:46  MWE
Release 4.3



*/
/*--------------------------------------------------|

| DynamicTree 2.05 | www.destroydrop.com/javascript/tree/ |

|---------------------------------------------------|

| Copyright (c) 2002-2003 Geir Landrö               |

|                                                   |

| This script can be used freely as long as all     |

| copyright messages are intact.                    |

|                                                   |

| Updated: 17.04.2003                               |

|--------------------------------------------------*/



// Node object

function Node(id, pid, aname, url, atitle, atarget, sstate, trackid,defstate)
{
	this.id = id;
	this.pid = pid;
	this.name = aname;
	this.url = url;
        if (atitle == null || atitle == 'undefined' || atitle == '')
  	  this.title = aname;
        else
  	  this.title = atitle;
	this.target = atarget;
	this.icon = null;
	this.iconOpen = null;
	this._io = false;      /* isOpen */
	this._is = false;      /* isSelected */
	this._ls = false;      /* LastSibling */
	this._hc = false;      /* hasChildren */
	this._ai = 0;
    this._state = sstate >= 0 ? sstate : 0;
    this._defstate = defstate >1 ? defstate : 1;
    this._trackid = trackid;
    this.enabled = true;
    this.nextclicked = false;
    this.skipped = false;
	this._p;
};



// Tree object

function DynamicTree(objName, imgpath) {

	this.config = {

		target				: null,
		folderLinks			: false,
		useSelection		: true,
		useCookies			: false,
		useLines			: true,
		useIcons			: true,
		useStatusText		: true,
		closeSameLevel		: false,
		InsertInOrder		: false,
		clickInOrder	    : false,
		checkSkipped        : false
	}

	this.icon = {
		root				: imgpath + 'base.gif',
		folder				: imgpath + 'folder.gif',
        folderStarted		: imgpath + 'folder-s.gif',
        folderCompleted		: imgpath + 'folder-c.gif',
		folderOpen			: imgpath + 'folderopen.gif',
        folderOpenStarted	: imgpath + 'folderopen-s.gif',
        folderOpenCompleted	: imgpath + 'folderopen-c.gif',
		node_0				: imgpath + 'tnotstart.gif',
  		node_1				: imgpath + 'tincomp.gif',
        node_2				: imgpath + 'trejected.gif',
  		node_3				: imgpath + 'tcomp.gif',
		empty				: imgpath + 'empty.gif',
		line				: imgpath + 'line.gif',
		join				: imgpath + 'join.gif',
		joinBottom			: imgpath + 'joinbottom.gif',
		plus				: imgpath + 'plus.gif',
		plusBottom			: imgpath + 'plusbottom.gif',
		minus				: imgpath + 'minus.gif',
		minusBottom			: imgpath + 'minusbottom.gif',
		nlPlus				: imgpath + 'nolines_plus.gif',
		nlMinus				: imgpath + 'nolines_minus.gif'

	};

	this.obj = objName;
	this.aNodes = [];
	this.aIndent = [];
	this.root = new Node(-1);
	this.selectedNode = null;
	this.selectedFound = false;
	this.completed = false;
  this.showdebugfunc = null;
  this.currScrollItem = null;
  this.bStateModified = false;


};

DynamicTree.prototype.Modified = function()
{
	if (this.bStateModified == true)
	  this.showdebug('Modified() true');
	else
    this.showdebug('Modified() false');
	return this.bStateModified == true;
}
DynamicTree.prototype.SetModified = function(istrue)
{
	this.bStateModified = istrue ? true: false;
	return this.bStateModified;
}
DynamicTree.prototype.SetClickInOrder = function(istrue)
{
  this.config.clickInOrder = istrue ? true: false;
  if (this.config.clickInOrder)
    this.config.checkSkipped = false;
};

DynamicTree.prototype.SetCheckSkipped = function(istrue)
{
  if (this.config.clickInOrder == true)
  {
    this.config.checkSkipped = false;
  }
  else
  {
  	 this.config.checkSkipped = istrue ? true: false;
  }
}

DynamicTree.prototype.IsClickInOrder = function()
{
  return this.config.clickInOrder;
};
DynamicTree.prototype.StepEnabled = function(nstep)
{
  return nstep > 0 && nstep < this.aNodes.length && this.aNodes[nstep].enabled == true;
};

DynamicTree.prototype.showdebug = function(msg)
{
  if (this.showdebugfunc)
  {
    this.showdebugfunc('['+this.obj+']: '+msg);
    //alert(msg)
  }
};

DynamicTree.prototype.StepSkipped = function(nstep)
{
  if (this.config.checkSkipped)
  {
    this.showdebug('current._state = '+this.aNodes[nstep]._state + ',current.nextclicked='+this.aNodes[nstep].nextclicked+',current.skipped = '+this.aNodes[nstep].spipped);
    if (this.aNodes[nstep].skipped == true)
      return true;
  }
  return false;
};


DynamicTree.prototype.SetDebugFunc = function(fnc)
{
  this.showdebugfunc = fnc;
};

// Adds a new node to the node array
DynamicTree.prototype.add = function(id, pid, sname, url, starget, sstate,trackid,defstate,stitle) {

	this.aNodes[this.aNodes.length] = new Node(id, pid, sname, url, stitle, starget, sstate,trackid,defstate);


};

DynamicTree.prototype.CheckEnabledSteps = function()
{
  if (!this.IsClickInOrder()) return;

  var lastwasok = true;
  for(n=2; n< this.aNodes.length;n++)
  {
    if (this.aNodes[n].hc)
    {
      this.aNodes[n].enabled = true;
    }
    else
    {
      if (this.aNodes[n]._state > 0 && lastwasok == true)
      {
      	this.aNodes[n].enabled = true;
      }
      else
      {
      	lastwasok = false;
      	this.aNodes[n].enabled = false;
      }
    }
  }
  this.aNodes[0].enabled = true;this.aNodes[1].enabled = true;
};

// Open/close all nodes

DynamicTree.prototype.openAll = function() {

	this.oAll(true);

};

DynamicTree.prototype.closeAll = function() {

	this.oAll(false);

};


DynamicTree.prototype.GotoNext = function() {

 var ntemp = this.selectedNode;
 this.showdebug('GotoNext: current = '+ntemp);
 if (!ntemp)
 {
   ntemp = 0;
   if (this.aNodes[0]._hc)
   {
     ntemp = this.findNextNode(ntemp,0)
     if (ntemp >=0)
     {
       this.enableNode(ntemp);
       this.openTo(ntemp, true, false)
       this.doClick(ntemp);
     }
   }
   else
   {
   	 this.enableNode(ntemp);
     this.openTo(ntemp, true, true)
     this.doClick(ntemp);
   }
 }
 else
 {
   this.showdebug('aktuell: ' + this.aNodes[ntemp].name + ', id='+this.aNodes[ntemp].id+',_ai='+this.aNodes[ntemp]._ai+',pid='+this.aNodes[ntemp].pid);
   ntemp = this.findNextNode(ntemp,this.aNodes[ntemp].pid);

   this.showdebug('ntemp = '+ntemp);
   if (ntemp >=0)
   {
   	 this.enableNode(ntemp);
     this.openTo(ntemp, true, false)
     this.doClick(ntemp);
   }
 }

}

DynamicTree.prototype.GotoPrevious = function() {

  var ntemp = this.selectedNode;
  if (!ntemp) {
    this.GotoNext();
    return;
  }
  this.showdebug('GotoPrevious: aktuell =  ' + this.aNodes[ntemp].name + ', id='+this.aNodes[ntemp].id+',_ai='+this.aNodes[ntemp]._ai+',pid='+this.aNodes[ntemp].pid);
  ntemp = this.findPrevNode(ntemp,this.aNodes[ntemp].pid);

  this.showdebug('ntemp = '+ntemp);
  if (ntemp >=0)
  {
    this.openTo(ntemp, true, false)
    this.doClick(ntemp);
  }
}


DynamicTree.prototype.doClick = function(ntemp) {
  this.showdebug("doClick: "+ntemp);
  ni = 's'+ this.obj + ntemp;
  xx = document.getElementById(ni)
  if (xx.click)
  {
     xx.click();
     this.showdebug(ni+ ' manually clicked');
     return true;
  }
  else
  {
    this.showdebug(ni+ ' not found to click..' +document.location);
    nv = 'v' + this.obj + ntemp;
    xx = document.getElementById(nv);   // div suchen
    if (xx)
    {
      xx.getElementsByTagName('a');
      if (xx)
      {
        if (xx.hasChildNodes())
        {
       	  var Knoten = xx.firstChild;
          while (Knoten != null)
          {
            if (ni == Knoten.getAttribute('id'))
            {
                url = Knoten.getAttribute('href');
                eval(url);
            	break;
            }
            Knoten = Knoten.nextSibling;
          }
        }
      }
    }
  }
}




DynamicTree.prototype.findNextNode = function(nId,pid) {
  this.showdebug('findNextNode('+nId+','+pid+')');
  for (n= nId+1; n < this.aNodes.length; n++)
  {
    if (this.aNodes[n].pid == pid)
    {
      if (this.aNodes[n]._hc)
      {
        return this.findNextNode(n, n);
      }
      else
        return n;
    }
  }
  if (nId > 0)
  {
    anode = this.aNodes[nId];
    if (anode._p)
    {
      return this.findNextNode(anode._p._ai,anode._p.pid);
    }
  }
  return -1;
}

DynamicTree.prototype.findPrevNode = function(nId,pid) {
this.showdebug('findPrevNode('+nId+','+pid+')');
  for (n = nId-1; n >0; n--)
  {
    if (this.aNodes[n].pid == pid)
    {
      if (this.aNodes[n]._hc)
      {
        return this.findLastNode(n, n);
      }
      else
        return n;
    }
  }
  if (nId > 0)
  {
    anode = this.aNodes[nId];
    if (anode._p)
    {
      return this.findPrevNode(anode._p._ai,anode._p.pid);
    }
  }
  return -1;
}

DynamicTree.prototype.findLastNode = function(nId,pid) {
this.showdebug('findLastNode('+nId+','+pid+')');
lastok = -1
  for (n = nId; n < this.aNodes.length; n++)
  {
    if (this.aNodes[n].pid == pid)
    {
      lastok = n;
    }
  }
this.showdebug('findLastNode: lastok-1 = '+lastok);
  if (lastok > -1)
  {
    if (this.aNodes[lastok]._hc)
      {
        this.showdebug('findLastNode: node has children');
        return this.findLastNode(lastok, lastok);
      }
   }
   return lastok;
}

DynamicTree.prototype.findTrackingNode = function(trackid)
{
  this.showdebug('findTrackingNode('+trackid+')');
  for (n = 0; n < this.aNodes.length; n++)
  {
    if (this.aNodes[n]._trackid == trackid)
    {
      this.showdebug('findTrackingNode('+trackid+'), found item ='+n);
      return n;
    }
  }
  this.showdebug('findTrackingNode('+trackid+') not found');
  return "0";
}

DynamicTree.prototype.getCurrentTrackID = function()
{
  this.showdebug('getCurrentTrackID()');
  var ntemp = this.selectedNode;
  if (ntemp)
    return this.aNodes[ntemp]._trackid;
  return 0;
}

DynamicTree.prototype.updatestate = function(id)
{
  node = this.aNodes[id];
  this.showdebug('updatestate : '+node.name+ ' to state '+node._state);
  xx = document.getElementById('i'+this.obj + id)
  if (node._state == 0)
  {
    xx.src = this.icon.node_0;
  }
  else if (node._state == 1)
  {
    xx.src = this.icon.node_1;
  }
  else if (node._state == 2)
  {
    xx.src = this.icon.node_2;
  }
  else if (node._state == 3)
  {
    xx.src = this.icon.node_3;
  }
}

DynamicTree.prototype.updatenodestate = function(pid)
{
  bstarted = false;
  bcompleted = false;
  bnotstarted = false;
  node = this.aNodes[pid];
  this.showdebug('updatenodestate('+pid+') : '+node.name+ ', old state '+node._state);
  for(n=0; n< this.aNodes.length;n++)
  {

     if (this.aNodes[n].pid == pid)
     {
      this.showdebug('updatenodestate('+pid+') : '+this.aNodes[n].name+ ', state= '+this.aNodes[n]._state);
      if (this.aNodes[n]._hc)
      {
        if (this.aNodes[n]._state == 0)
          bnotstarted = true;
        else if (this.aNodes[n]._state == 1)
          bstarted = true;
        else if (this.aNodes[n]._state == 2)
          bcompleted = true;
      }
      else
      {
        if (this.aNodes[n]._state == 0)
          bnotstarted = true;
        if (this.aNodes[n]._state == 1 || (this.aNodes[n]._state == 2))
          bstarted = true;
        else if (this.aNodes[n]._state == 3)
          bcompleted = true;
      }
    }
  }
  newstate = 0
  if (bcompleted && ! bstarted && !bnotstarted)
    newstate = 2
  else if (bstarted || bcompleted)
    newstate = 1;
 this.showdebug('updatenodestate('+pid+') : '+node.name+ ', new state '+newstate);
  node = this.aNodes[pid];
  xx = document.getElementById('i'+this.obj+pid)
  if (pid > 0 && this.aNodes[pid]._state != newstate)
  {
    this.aNodes[pid]._state = newstate;
    this.bStateModified = true;
     this.showdebug("updatenodestate:setmodified = "+ this.bStateModified);
                    if (node._state == 0)
                    {
                      this.aNodes[pid].icon = this.icon.folder
                      this.aNodes[pid].iconOpen = this.icon.folderOpen
                    }
                    else if (node._state == 1)
                    {
                      this.aNodes[pid].icon = this.icon.folderStarted
                      this.aNodes[pid].iconOpen = this.icon.folderOpenStarted
                    }
                    else if (node._state == 2)
                    {
                      this.aNodes[pid].icon = this.icon.folderCompleted
                      this.aNodes[pid].iconOpen = this.icon.folderOpenCompleted
                    }

                     if (node._io)
                        xx.src = this.aNodes[pid].iconOpen;
                      else
                        xx.src = this.aNodes[pid].icon;

  }
 if (this.aNodes[pid].pid > 0)
   this.updatenodestate(this.aNodes[pid].pid)
 this.showdebug("updatenodestate:modified = "+ this.bStateModified);
}

DynamicTree.prototype.savetrackdata = function()
{
  totalItems = 0;
  totalCompleted = 0;

  for(n=0; n< this.aNodes.length-1;n++)
  {
    if (!this.aNodes[n]._hc)
    {
      totalItems++;
      if (this.aNodes[n]._state == 3)
        totalCompleted++;
    }
  }
  // Wenn nur der letzte Punkt "Abschliessen" noch nicht geklickt wurde, diesen als erledigt markieren.
  if (this.aNodes[n] && (totalCompleted +1) == totalItems && this.aNodes[n]._state != 3)
  {
	  this.aNodes[n]._state = 3;
	  totalCompleted++;
	  this.showdebug('savetrackdata: only last item was incompleted -- set to complete')
  } 
  this.showdebug('savetrackdata: totalItems='+totalItems+', totalCompleted='+totalCompleted);
  str = "";
  if (totalCompleted > 0)
    str = Math.round((totalCompleted * 100) / totalItems) + '::'
  else
    str = '0::';
  if (this.selectedNode)
  {
  	str = str + this.aNodes[this.selectedNode]._trackid + '::';
  }
  else
    str = str + '0::';
  for(n=1; n < this.aNodes.length;n++)
  {
    str = str + this.aNodes[n]._trackid + '|' + this.aNodes[n]._state + '::';
  }
  this.showdebug(str);
  this.bStateModified = false;
  this.showdebug("savetrackdata:modified = "+ this.bStateModified);
  return str;

}

DynamicTree.prototype.restoretrackdata = function(trackdata)
{
  var data = trackdata.split("::");
  var i ;
  var t;
  this.showdebug('restoretrackdata: data='+trackdata);
  if (data && data.length > 2)
  {
  	for (i = 2; i < data.length; i++)
  	{
  		t = data[i].split("|");
  		if (t && t.length == 2)
  		{
  		  this.restoretrackid(t[0], t[1],1);
  		}
  	}
  }
  this.bStateModified = false;
  this.showdebug("restoretrackdata:modified = "+ this.bStateModified);
}

DynamicTree.prototype.settracking = function(trackid, newstate)
{
  for(n=0; n< this.aNodes.length;n++)
  {
    if (this.aNodes[n]._trackid == trackid)
    {

       if (this.aNodes[n]._state < newstate)
       {
       	 this.aNodes[n]._state = newstate;
       	 this.updatestate(n);
       	 this.updatenodestate(this.aNodes[n].pid);
       	 this.bStateModified = true;
       }
    }
  }
  this.showdebug("settracking:modified = "+ this.bStateModified);
}

DynamicTree.prototype.overwritetracking = function(trackid, newstate)
{
 for(n=0; n< this.aNodes.length;n++)
  {
    if (this.aNodes[n]._trackid == trackid)
    {

       if (this.aNodes[n]._state != newstate)
       {
       	 this.aNodes[n]._state = newstate;
       	 this.updatestate(n);
       	 this.updatenodestate(this.aNodes[n].pid);
       	 this.bStateModified = true;
       }
    }
  }
  this.showdebug("overwritetracking:modified = "+ this.bStateModified);
}

DynamicTree.prototype.gettracking = function(trackid)
{
  for(n=0; n< this.aNodes.length;n++)
  {
    if (this.aNodes[n]._trackid == trackid)
    {
       return this.aNodes[n]._state;
    }
  }
  return 0;
}

DynamicTree.prototype.restoretrackid = function(trackid,state,setenabled)
{
 this.showdebug('restoretrackid('+trackid+','+state+','+setenabled + ')');
  for(var n=0; n < this.aNodes.length;n++)
  {
    if (this.aNodes[n]._trackid == trackid)
    {
   	   this.aNodes[n]._state = state;
       if (setenabled == 1)
       	 this.aNodes[n].enabled = true;
    }
  }
}

DynamicTree.prototype.allCompleted = function()
{
  totalItems = 0;
  totalCompleted = 0;

  for(n=0; n< this.aNodes.length-1;n++)
  {
    if (!this.aNodes[n]._hc)
    {
      totalItems++;
      if (this.aNodes[n]._state == 3)
        totalCompleted++;
    }
  }
  // Wenn nur der letzte Punkt "Abschliessen" noch nicht geklickt wurde, diesen als erledigt markieren.
  this.showdebug('allCompleted: check last entry, n='+n+', nodes='+this.aNodes.length+',' +this.aNodes[n].title +', totalItems='+totalItems+', totalCompleted='+totalCompleted);
  if (this.aNodes[n] && (totalCompleted +1) == totalItems && this.aNodes[n]._state != 3)
  {
	  this.aNodes[n]._state = 3;
	  totalCompleted++;
  }  
  this.showdebug('allCompleted: totalItems='+totalItems+', totalCompleted='+totalCompleted);
  return totalItems == totalCompleted;

}

DynamicTree.prototype.getSelectedPath = function()
{
  var r = '';
  var arr = [];
  var p = 0;
  var c = 0;
  if (this.selectedNode >0)
  {
  	c = this.selectedNode;
  	arr[arr.length] = this.aNodes[c].name;
  	p = this.aNodes[c].pid;
  	while (p > 0)
  	{
  	  c = p;
  	 arr[arr.length] = this.aNodes[c].name;
  	  p = this.aNodes[c].pid;
  	}
  	var i =0;
  	for (i = arr.length; i>0; i--)
  	{
      r = r + arr[i-1] + '/';
  	}
  	return r.substring(0,r.length-1);
  }
  return r;
}

DynamicTree.prototype.dumpnodes = function()
{
  for(n=1; n< this.aNodes.length;n++)
  {
    node =  this.aNodes[n];
    str = 'Node['+n+'] \n';
    str = str + 'id = '+node.id+', pid='+node.pid + '\n';
    str = str + 'name = ' + node.name + '\n';
    str = str + 'url = '+ node.url  + '\n';
    str = str + 'target = '+ node.target  + '\n';
    str = str + 'title = '+ node.title  + '\n';
    str = str + 'icon = ' + node.icon + '\n';
    str = str + 'iconOpen = '+node.iconOpen+'\n';
    str = str + '_state = ' + node._state+'\n';
    str = str + '_defstate='+node._defstate + '\n';
    str = str + '_trackid = '+node._trackid;
    str = str + 'enabled = '+(node.enabled ? "true" : "false") + '\n';
    this.showdebug(str + '\n\n')
  }

}
// Outputs the tree to the page

DynamicTree.prototype.toString = function() {

	this.CheckEnabledSteps();
	var str = '<div class="dynamictree">\n';

	if (document.getElementById) {

		if (this.config.useCookies) this.selectedNode = this.getSelected();

		str += this.addNode(this.root);

	} else str += 'Browser not supported.';

	str += '</div>';

	if (!this.selectedFound) this.selectedNode = null;

	this.completed = true;

	return str;

};



// Creates the tree structure

DynamicTree.prototype.addNode = function(pNode) {

	var str = '';

	var n=0;

	if (this.config.InsertInOrder) n = pNode._ai;

	for (n; n<this.aNodes.length; n++) {

		if (this.aNodes[n].pid == pNode.id) {

			var cn = this.aNodes[n];

			cn._p = pNode;

			cn._ai = n;

			this.setCS(cn);

			if (!cn.target && this.config.target) cn.target = this.config.target;

			if (cn._hc && !cn._io && this.config.useCookies) cn._io = this.isOpen(cn.id);

			if (!this.config.folderLinks && cn._hc) cn.url = null;

			if (this.config.useSelection && cn.id == this.selectedNode && !this.selectedFound) {

					cn._is = true;

					this.selectedNode = n;

					this.selectedFound = true;

			}

			str += this.node(cn, n);

			if (cn._ls) break;

		}

	}

	return str;

};



// Creates the node icon, url and text

DynamicTree.prototype.node = function(node, nodeId) {

	var str = '<div class="dynamictree" id="v'+this.obj + nodeId+'">' + this.indent(node, nodeId);
    var nc;
    if (node.enabled)
     nc = 'node';
    else
     nc = 'nodeDimmed';
	if (this.config.useIcons) {


                  if (this.root.id == node.pid)
                  {
                    node.icon = this.icon.root
                    node.iconOpen = this.icon.root;
                  }
                  else if (node._hc)
                  {
                    if (node._state == 0)
                    {
                      node.icon = this.icon.folder;
                      node.iconOpen = this.icon.folderOpen;
                    }
                    else if (node._state == 1)
                    {
                      node.icon = this.icon.folderStarted;
                      node.iconOpen = this.icon.folderOpenStarted;
                    }
                    else if (node._state == 2)
                    {
                      node.icon = this.icon.folderCompleted;
                      node.iconOpen = this.icon.folderOpenCompleted;
                    }
                  }
                  else
                  {
                    if (node._state == 0)
                    {
                      node.icon = node.iconOpen = this.icon.node_0;
                    }
                    else if (node._state == 1)
                    {
                      node.icon = node.iconOpen = this.icon.node_1;
                    }
                    else if (node._state == 2)
                    {
                      node.icon = node.iconOpen = this.icon.node_2;
                    }
                    else if (node._state == 3)
                    {
                      node.icon = node.iconOpen = this.icon.node_3;
                    }
                  }





		str += '<img id="i' + this.obj + nodeId + '" src="' + ((node._io) ? node.iconOpen : node.icon) + '" alt="" />';

	}

	if (node.url) {

		str += '<a id="s' + this.obj + nodeId + '" class="' + ((this.config.useSelection) ? ((node._is ? 'nodeSel' : nc)) : nc) + '" href="' + node.url + '"';

		if (node.title) str += ' title="' + node.title + '"';

		if (node.target) str += ' target="' + node.target + '"';

		if (this.config.useStatusText) str += ' onmouseover="window.status=\'' + node.name + '\';return true;" onmouseout="window.status=\'\';return true;" ';
//		str += ' onmouseup="return ' + this.obj + '.mouseUpEvent('+node.id+')"';
//		str += ' onmousedown="return ' + this.obj + '.mouseUpEvent('+node.id+')"';

		if (this.config.useSelection && ((node._hc && this.config.folderLinks) || !node._hc))

			str += ' onclick="javascript: ' + this.obj + '.s(' + nodeId + ');"';

		str += '>';

	}

	else if ((!this.config.folderLinks || !node.url) && node._hc && node.pid != this.root.id)
	{

		str += '<a href="javascript: ' + this.obj + '.o(' + nodeId + ');" class="node"';
		if (node.title) str += ' title="' + node.title + '"';
		if (this.config.useStatusText) str += ' onmouseover="window.status=\'' + node.name + '\';return true;" onmouseout="window.status=\'\';return true;" ';
		str +='>';
	}
	str += node.name; // + '('+node.id+'/'+node.pid+','+node._ls+')';

	if (node.url || ((!this.config.folderLinks || !node.url) && node._hc)) str += '</a>';

	str += '</div>';

	if (node._hc) {

		str += '<div id="d' + this.obj + nodeId + '" class="clip" style="display:' + ((this.root.id == node.pid || node._io) ? 'block' : 'none') + ';">';

		str += this.addNode(node);

		str += '</div>';

	}

	this.aIndent.pop();

	return str;

};



// Adds the empty and line icons

DynamicTree.prototype.indent = function(node, nodeId) {

	var str = '';

	if (this.root.id != node.pid) {

		for (var n=0; n<this.aIndent.length; n++)

			str += '<img src="' + ( (this.aIndent[n] == 1 && this.config.useLines) ? this.icon.line : this.icon.empty ) + '" alt="" />';

		(node._ls) ? this.aIndent.push(0) : this.aIndent.push(1);

		if (node._hc) {

			str += '<a href="javascript: ' + this.obj + '.o(' + nodeId + ');"><img id="j' + this.obj + nodeId + '" src="';

			if (!this.config.useLines) str += (node._io) ? this.icon.nlMinus : this.icon.nlPlus;

			else str += ( (node._io) ? ((node._ls && this.config.useLines) ? this.icon.minusBottom : this.icon.minus) : ((node._ls && this.config.useLines) ? this.icon.plusBottom : this.icon.plus ) );

			str += '" alt="" /></a>';

		} else str += '<img src="' + ( (this.config.useLines) ? ((node._ls) ? this.icon.joinBottom : this.icon.join ) : this.icon.empty) + '" alt="" />';

	}

	return str;

};



// Checks if a node has any children and if it is the last sibling

DynamicTree.prototype.setCS = function(node) {

	var lastId;

	for (var n=0; n<this.aNodes.length; n++) {

		if (this.aNodes[n].pid == node.id) node._hc = true;

		if (this.aNodes[n].pid == node.pid) lastId = this.aNodes[n].id;

	}

	if (lastId==node.id) node._ls = true;

};



// Returns the selected node

DynamicTree.prototype.getSelected = function() {

	var sn = this.getCookie('cs' + this.obj);

	return (sn) ? sn : null;

};
DynamicTree.prototype.mouseUpEvent = function(nitem) {

  if (this.aNodes[nitem].enabled == false)
  {
	alert('not enabled');
	return false;
  }
  return true;

};


// Highlights the selected node

DynamicTree.prototype.s = function(id) {

	if (!this.config.useSelection) return;

	var cn = this.aNodes[id];

	if (cn._hc && !this.config.folderLinks) return;

	if (!cn._hc && cn.enabled == false) return;

	cn.skipped = false;
	if (this.config.checkSkipped && this.selectedNode)
	{
	  if (!cn._hc)
	  {
	    if (cn._state == 0)     // Der anzuwählende Lernschritt wurde noch nie angeklickt
	    {
	      var  ntemp = this.findPrevNode(id,this.aNodes[id].pid);  // Schritt zurück suchen
	      if (ntemp == this.selectedNode)                          // Schritt zurück ist aktueller Schritt
	  	  {
    	  	if (this.aNodes[id].nextclicked == false)              // Nicht über NEXT gecklickt?
	  	  	  this.aNodes[id].skipped = true;                      // Skipped!
	  	  }
	    }
	  }
	  if (cn.skipped)
	    return;
	}
    if (cn._trackid && cn._defstate)
    {
      if ((cn._state < cn._defstate) && cn.enabled)
      {
        cn._state = cn._defstate;
        this.bStateModified = true;
        this.updatestate(id);
        this.updatenodestate(cn.pid)
      }
    }

	if (this.selectedNode != id) {

		if (this.selectedNode || this.selectedNode==0)
		{
			var nc = 'node';
			if (this.selectedNode < this.aNodes.length)
			{
			  if (!this.aNodes[this.selectedNode].enabled)
			    nc = 'nodeDimmed'	;
			}

			eOld = document.getElementById("s" + this.obj + this.selectedNode);
            if (eOld)
  			  eOld.className = nc;

		}

		eNew = document.getElementById("s" + this.obj + id);

		eNew.className = "nodeSel";

		this.selectedNode = id;

		if (this.config.useCookies) this.setCookie('cs' + this.obj, cn.id);
             if (cn._trackid && cn._defstate)
             {
               if ((cn._state < cn._defstate) && cn.enabled)
               {
                 cn._state = cn._defstate;
                 this.bStateModified = true;
                 this.updatestate(id);
               }
             }

	}

};



// Toggle Open or close

DynamicTree.prototype.o = function(id) {

	var cn = this.aNodes[id];

	this.nodeStatus(!cn._io, id, cn._ls);

	cn._io = !cn._io;

	if (this.config.closeSameLevel) this.closeLevel(cn);

	if (this.config.useCookies) this.updateCookie();

};



// Open or close all nodes

DynamicTree.prototype.oAll = function(status) {

	for (var n=0; n<this.aNodes.length; n++) {

		if (this.aNodes[n]._hc && this.aNodes[n].pid != this.root.id) {

			this.nodeStatus(status, n, this.aNodes[n]._ls)

			this.aNodes[n]._io = status;

		}

	}

	if (this.config.useCookies) this.updateCookie();

};



// Opens the tree to a specific node

DynamicTree.prototype.openTo = function(nId, bSelect, bFirst) {
 this.showdebug('openTo('+nId+','+bSelect+','+bFirst+')');
	if (!bFirst) {

		for (var n=0; n<this.aNodes.length; n++) {

			if (this.aNodes[n].id == nId) {

				nId=n;

				break;

			}

		}

	}

	var cn=this.aNodes[nId];
	if (cn.pid==this.root.id || !cn._p) return;
	cn._io = true;
	cn._is = bSelect;
	if (this.completed && cn._hc) this.nodeStatus(true, cn._ai, cn._ls);
	if (this.completed && bSelect) this.s(cn._ai);
	else if (bSelect) this._sn=cn._ai;
	this.openTo(cn._p._ai, false, true);
};



// Closes all nodes on the same level as certain node

DynamicTree.prototype.closeLevel = function(node) {

	for (var n=0; n<this.aNodes.length; n++) {

		if (this.aNodes[n].pid == node.pid && this.aNodes[n].id != node.id && this.aNodes[n]._hc) {

			this.nodeStatus(false, n, this.aNodes[n]._ls);

			this.aNodes[n]._io = false;

			this.closeAllChildren(this.aNodes[n]);

		}

	}

}



// Closes all children of a node

DynamicTree.prototype.closeAllChildren = function(node) {

	for (var n=0; n<this.aNodes.length; n++) {

		if (this.aNodes[n].pid == node.id && this.aNodes[n]._hc) {

			if (this.aNodes[n]._io) this.nodeStatus(false, n, this.aNodes[n]._ls);

			this.aNodes[n]._io = false;

			this.closeAllChildren(this.aNodes[n]);

		}

	}

}

DynamicTree.prototype.closeAllChildren = function(node) {

	for (var n=0; n<this.aNodes.length; n++) {

		if (this.aNodes[n].pid == node.id && this.aNodes[n]._hc) {

			if (this.aNodes[n]._io) this.nodeStatus(false, n, this.aNodes[n]._ls);

			this.aNodes[n]._io = false;

			this.closeAllChildren(this.aNodes[n]);

		}

	}

}

// Change the status of a node(open or closed)

DynamicTree.prototype.nodeStatus = function(status, id, bottom) {

	eDiv	= document.getElementById('d' + this.obj + id);

	eJoin	= document.getElementById('j' + this.obj + id);

	if (this.config.useIcons) {

		eIcon	= document.getElementById('i' + this.obj + id);

		eIcon.src = (status) ? this.aNodes[id].iconOpen : this.aNodes[id].icon;

	}

	eJoin.src = (this.config.useLines)?

	((status)?((bottom)?this.icon.minusBottom:this.icon.minus):((bottom)?this.icon.plusBottom:this.icon.plus)):

	((status)?this.icon.nlMinus:this.icon.nlPlus);

	eDiv.style.display = (status) ? 'block': 'none';

};

// Count open items in tree

DynamicTree.prototype.openCount = function(parent, currcounter) {
 this.showdebug('openCount: parent = '+parent+', currcounter='+currcounter);
  for (var n=0; n<this.aNodes.length; n++)
  {
    if (this.aNodes[n].pid == parent)
	{
      currcounter++;
      if (n == this.selectedNode)
        this.currScrollItem = currcounter;
 	  if (this.aNodes[n]._hc)
	  {
	  	if (this.aNodes[n]._io)
 	      currcounter = this.openCount(n,currcounter);
	  }
	}
  }
  return currcounter;
};


DynamicTree.prototype.resetStates = function() {
 this.showdebug('resetStates');
 var ienabled = true;
 if (this.IsClickInOrder())
 {
 	ienabled = false;
 }

  for (var n=0; n<this.aNodes.length; n++)
  {
    this.aNodes[n]._state = 0;
    this.aNodes[n].enabled = ienabled;
  }
  this.currScrollItem = 0;
  this.selectedNode = null;
  this.bStateModified = false;
};


DynamicTree.prototype.GetCurrScrollItem = function() {
  return this.currScrollItem;
}

DynamicTree.prototype.SetCurrScrollItem = function(nitem) {
  this.currScrollItem = nitem;
}

DynamicTree.prototype.enableNode = function(n)
{
  if (n >= 0 && n < this.aNodes.length)
  {
    this.aNodes[n].enabled = true;
    this.aNodes[n].nextclicked = true;
  }
}

// [Cookie] Clears a cookie

DynamicTree.prototype.clearCookie = function() {

	var now = new Date();

	var yesterday = new Date(now.getTime() - 1000 * 60 * 60 * 24);

	this.setCookie('co'+this.obj, 'cookieValue', yesterday);

	this.setCookie('cs'+this.obj, 'cookieValue', yesterday);

};



// [Cookie] Sets value in a cookie

DynamicTree.prototype.setCookie = function(cookieName, cookieValue, expires, path, domain, secure) {

	document.cookie =

		escape(cookieName) + '=' + escape(cookieValue)

		+ (expires ? '; expires=' + expires.toGMTString() : '')

		+ (path ? '; path=' + path : '')

		+ (domain ? '; domain=' + domain : '')

		+ (secure ? '; secure' : '');

};



// [Cookie] Gets a value from a cookie

DynamicTree.prototype.getCookie = function(cookieName) {

	var cookieValue = '';

	var posName = document.cookie.indexOf(escape(cookieName) + '=');

	if (posName != -1) {

		var posValue = posName + (escape(cookieName) + '=').length;

		var endPos = document.cookie.indexOf(';', posValue);

		if (endPos != -1) cookieValue = unescape(document.cookie.substring(posValue, endPos));

		else cookieValue = unescape(document.cookie.substring(posValue));

	}

	return (cookieValue);

};



// [Cookie] Returns ids of open nodes as a string

DynamicTree.prototype.updateCookie = function() {

	var str = '';

	for (var n=0; n<this.aNodes.length; n++) {

		if (this.aNodes[n]._io && this.aNodes[n].pid != this.root.id) {

			if (str) str += '.';

			str += this.aNodes[n].id;

		}

	}

	this.setCookie('co' + this.obj, str);

};



// [Cookie] Checks if a node id is in a cookie

DynamicTree.prototype.isOpen = function(id) {

	var aOpen = this.getCookie('co' + this.obj).split('.');

	for (var n=0; n<aOpen.length; n++)

		if (aOpen[n] == id) return true;

	return false;

};


DynamicTree.prototype.fireEvent = function(eventType, element)
{
	var o = document.getElementById(element);

    if (document.createEvent)
    {
        var evt = document.createEvent("Events");
        evt.initEvent(eventType, true, true);
        o.dispatchEvent(evt);
    } else if (document.createEventObject) {
        var evt = document.createEventObject();
        o.fireEvent('on' + eventType, evt);
    }
}


// If Push and pop is not implemented by the browser

if (!Array.prototype.push) {

	Array.prototype.push = function array_push() {

		for(var i=0;i<arguments.length;i++)

			this[this.length]=arguments[i];

		return this.length;

	}

};

if (!Array.prototype.pop) {

	Array.prototype.pop = function array_pop() {

		lastElement = this[this.length-1];

		this.length = Math.max(this.length-1,0);

		return lastElement;

	}

};
