/*
  MAZ - v04 - 2007-06-07 - tratamos de compatibilizarla con jQUERY 
  MAZ - v02 - 2007-05-15 - se redefine el arbol

  Variantes de configuracion

    Variante 1:
    - click sobre un nodo, expande o collapsa el nodo de acuerdo a su estado
      nodeToggleOnClick = true
      nodeShowOnSelected = estilo a aplicar cuando esta seleccionado
    - las imagenes solo muestran estado, pero no son clickeables
      btnToggleOnClick = false
      btnCollapsedImg= ""; btnExpandedImg= ""; btnLeafImg= "" ;

    Variante 2:
    - click sobre un nodo, invoca a la funcion asociada.
      nodeToggleOnClick = false
      nodeShowOnSelected = estilo a aplicar cuando esta seleccionado
    - las imagenes son navegables
      btnToggleOnClick = true
      btnCollapsedImg= ""; btnExpandedImg= ""; btnLeafImg= "" ;

  Estructura
    Cada nodo esta representado por un elemento "li", que contiene tres elementos hijos:
       img  - contiene el "icono" del nodo, este icono tiene sentido solo si es una hoja
              si es un nodo se usaran las imagenes "expanded" o "collapsed"
       span - contiene el "titulo" del elemento, puede incluirse cualquier cosa valida dentro de este tag
              usualmente tendra un "a" y otros textos ...
       div  - contiene la "info" asociada al nodo, puede incluirse cuaqluier cosa valida dentro de este tag
              usualmente contendra una tabla, parrafos, etc ... inclusive formularios

    El subarbol (puede ser solo uno) del elemento esta representados por un elemento "ul" hijo.

    Una hoja (no contiene subarboles) tendra la estructura:
         "<li><img/><span>... titulo</span><div>... contenido</div></li>"

    Un nodo con subarboles tendra la estructura:
         "<li><img/><span>... titulo</span><div>... contenido</div>
              <ul> ... subarbol
              </ul>
          </li>"

    Nota: cuando el elemento img represente un nodo (no una hoja) tendra la clase "panel-id:btn",
          que respondera a la expansion o contraccion de los subnodos.

    Las funciones para setear/acceder a los elementos del nodo actuan siempre sobre el elemento seleccionado.
    Estas son:
          set/getSelectedNodeIcon, set/getSelectedNodeTitle, set/getSelectedNodeInfo

    La funcion que setea el nodo "activo" es selectNode(ev). La funcion getSelectedNode() devuelve el nodo completo.

*/

// constructor for the Minia TreePanel class
function TreePanel(panelId) {
   // save the ID and other info
   this.treeId= "";
   this.panelId= panelId; // uses
   this.selected= null;
   this.btnClassName= this.panelId+":btn" ;  // create the class name for the button

   // private vars which define how the TreePanel works
   // define how a node must act when it is clicked
   this.nodeToggleOnClick = false;
   this.nodeShowOnSelected= "";
   // define how the toggle button must work
   this.btnToggleOnClick = false;
   this.btnCollapsedImg  = "images/expander1.gif" ;
   this.btnExpandedImg   = "images/collapser1.gif";
   this.btnLeafImg       = "images/ender.gif" ;

   // constants
   this.html            = function() { return document.getElementById(this.panelId).innerHTML ; };
   this.selectedIcon    = function() { return this.selected.childNodes[0]; };
   this.selectedTitle   = function() { return this.selected.childNodes[1]; };
   this.selectedInfo    = function() { return this.selected.childNodes[2]; };
   this.selectedSubtree = function() { for (var i=3; i < this.selected.childNodes.length; i++) {
                                            if (this.selected.childNodes[i].tagName == "UL") {
                                                return this.selected.childNodes[i] ;
                                            } } };
   this.hasSubtree = function() {
	   var aList = null;
	   var i=0;
	   var cant=$("#tree-content span.node-selected").parent().find("ul").length;
	   while (i<cant){
		   aList= this.selected.getElementsByTagName("ul")[i];
		   if (aList) {
		       var tag = aList.parentNode.tagName;
			   if (tag == "DIV") {
				   i++;
			   }
			   else{
				   return 1;
			   }
		   }
	   }      
       return 0;
   };
}

// Setting TreePanel options

// define how the Node will behave
TreePanel.prototype.setNodeOptions = function(toggleOnClick, showSelectedSts) {
    this.nodeToggleOnClick = toggleOnClick;
    this.nodeShowOnSelected= showSelectedSts;
}

// define how the toggle Btn will behave
TreePanel.prototype.setBtnOptions = function(toggleOnClick, expandedImg, collapsedImg, leafImg) {
    this.btnToggleOnClick = toggleOnClick;
    this.btnCollapsedImg = collapsedImg ;
    this.btnExpandedImg= expandedImg;
    this.btnLeafImg     = leafImg ;
}

// Busca el treeId dentro del panel en el que esta incluido
TreePanel.prototype.autosetTreeId = function()  {
   var container= document.getElementById(this.panelId) ; // use the container panel
   // get the first child of the container, must be an "ul" tag
   var childs= container.getElementsByTagName("ul") ;
   // use the first child ...
   if (childs.length==0){
    alert("El tiempo de la sesión ha expirado");
    window.close();
   }
   else{
   if (childs[0].tagName == "UL") {
        this.treeId = childs[0].id ; // get the ID from the included subtree
        // alert("tree id=" + this.treeId);
        // set the first LI node contained in this UL as selected
        var container= childs[0].getElementsByTagName("li")[0]; // get the first LI inside this UL
        this.selected = container;                    // set it as the currently selected node
        this.selectedTitle().className= this.nodeShowOnSelected ;    // change its style
   }
   }
}

// Fully collapses the tree
TreePanel.prototype.collapseAll = function()  {
   var subtree= document.getElementById(this.treeId) ; // find the root
   // get the list of all UL elements inside the node
   if(subtree!=null){
   var ulList= subtree.getElementsByTagName("ul") ; // use lowercase for "ul" tag
   // navigate the UL elements, and collapse them all
   for (var i=0; i < ulList.length; i++) {
        // collapse the subtree
        ulList[i].style.display='none';
   }
   // show the root node
   this.setButton(subtree, this.btnCollapsedImg) ;
   subtree.style.display='';
   }
}

// Fully expands the tree
TreePanel.prototype.expandAll = function() {
   var subtree= document.getElementById(this.treeId) ; // find the root
   // get the list of all UL elements inside the node
   if(subtree!=null){
   var ulList= subtree.getElementsByTagName("ul") ; // use lowercase for "ul" tag
   // navigate the UL elements, and expand them all
   for (var i=0; i < ulList.length; i++) {
        // expand the subtree
        ulList[i].style.display='';
   }
   // show the root node
   this.setButton(subtree, this.btnExpandedImg) ;
   subtree.style.display='';
   }
}

TreePanel.prototype.hijos = function(ulList) {	
	if (ulList.length > 0) {
		for (var i=0; i < ulList.length; i++) {		
	       var tag = ulList[i].parentNode.tagName;
		   if (tag == "LI") 
			   return true
		}		
	}
	else{
		return false;
	}
}

// Setea el Boton (y su icono) para cada nodo
TreePanel.prototype.setButton = function(tNode, btnImg) {
   // get the list of all LI elements and assign the 'ender' or 'img' icon
   var liList= tNode.getElementsByTagName("li") ; // use lowercase for "li" tag
   // navigate the LI list
   for (var i=0; i < liList.length; i++) {
        var itm= liList[i];
        // find if the item contains an UL element inside it
        var ulList= itm.getElementsByTagName("ul") ;
        if (this.hijos(ulList)) {
           // contains one or more subtrees, assign a button to it
           itm.firstChild.src= btnImg ;
           itm.firstChild.className= this.btnClassName ;  // asign the class to the button
        }
        else {
           // its a leaf node, no subtrees
//           itm.firstChild.src= this.btnLeafImg ;
//           itm.firstChild.className= "" ;  // asign NULL class to the button = no action on leaf
        }
   }
}

// Muestra el nodo actualmente seleccionado
TreePanel.prototype.selectNode = function(ev) {
   if (this.selected) { this.selectedTitle().className= ''; } // desactivate the previously selected node
   var container= ev.target.parentNode ;             // find the ancestor which contains the clicked node
   while (container.tagName != "LI") {               // be careful - it MUST be an LI node
          container= container.parentNode;
   }
   this.selected = container;                         // set it as the currently selected node
   this.selectedTitle().className= this.nodeShowOnSelected ;    // change its style
}

// Devuelve completo el nodo actualmente seleccionado
TreePanel.prototype.getSelectedNode = function() {
   if (this.selected) {
       return this.selected ;
   }
   return null;
}

// Captura el evento 'node clicked'
TreePanel.prototype.nodeClicked = function(ev) {
   this.selectNode(ev);
   // check if Toggle is activated
   if (this.nodeToggleOnClick) { this.toggleSubtree(ev); }
}

// Captura el evento 'button clicked'
TreePanel.prototype.btnClicked = function(ev) {
   // check if Toggle is activated
   if (this.btnToggleOnClick) { this.toggleSubtree(ev); }
}

// Expande o contrae el nodo
TreePanel.prototype.toggleSubtree = function(ev) {
   if (this.selected) { this.selectNode(ev); } // if no node selected, we select the clicked node
   // get the UL child of the container
   var subtree= this.selectedSubtree();
   if (subtree) {
       // expand or collapse according to current state
       if (subtree.style.display == 'none') { // currently is collapsed, must EXPAND
           subtree.style.display='';
           this.selectedIcon().src= this.btnExpandedImg ;
       }
       else {                                 // currently is expandend, must COLLAPSE
           subtree.style.display='none';
           this.selectedIcon().src= this.btnCollapsedImg ;
       }
   }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*
   GET/SET de propiedades del Nodo (icon, title, info)
*/

// Devuelve icono del nodo actualmente seleccionado
TreePanel.prototype.getSelectedIcon = function() {
   if (! this.selected) { return("") ; } // no selected node !!!
   return this.selectedIcon() ;
}

// Setea titulo del nodo actualmente seleccionado
TreePanel.prototype.setSelectedIcon = function(tx) {
   if (! this.selected) { return ; } // no selected node !!!
   this.selectedIcon().innerHTML= tx ;
}

// Devuelve titulo del nodo actualmente seleccionado
TreePanel.prototype.getSelectedTitle = function() {
   if (! this.selected) { return("") ; } // no selected node !!!
   return this.selectedTitle() ;
}

// Setea titulo del nodo actualmente seleccionado
TreePanel.prototype.setSelectedTitle = function(tx) {
   if (! this.selected) { return ; } // no selected node !!!
   this.selectedTitle().innerHTML= tx ;
}

// Devuelve informacion del nodo actualmente seleccionado
TreePanel.prototype.getSelectedInfo = function() {
   if (! this.selected) { return("") ; } // no selected node !!!
   return this.selectedInfo() ;
}

// Setea la informacion del nodo actualmente seleccionado
TreePanel.prototype.setSelectedInfo = function(tx) {
   if (! this.selected) { return ; } // no selected node !!!
   this.selectedInfo().innerHTML= tx ;
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*
   ELIMINACION DE NODOS
*/

// Elimina completamente el nodo actualmente seleccionado
TreePanel.prototype.removeSelectedNode = function()
{
   if (! this.selected) { return ; } // no selected node !!!
   var thisNode = this.selected ;
   var theList = thisNode.parentNode ;  // this is the UL list where the current node resides
   var theParent = theList.parentNode ; // this is the grandparent of all of them
   theList.removeChild(thisNode) ; // remove all, may remove the parent UL node too !
   // check to see if we still have LI nodes inside the UL list
   var childs= theList.getElementsByTagName("li") ;
   if (childs.length == 0) { // NO LI nodes remain !
       theParent.removeChild(theList) ; // first remove completely the UL node
       // then change the parent status
       theParent.firstChild.src= this.btnLeafImg ;
       theParent.firstChild.className="";
   }
}

// Removes all childs of the currently selected node
TreePanel.prototype.removeSelectedChilds = function()
{
   if ((! this.selected)||(this.hasSubtree()<1)){ return ; } // no selected node !!!
   var thisNode = this.selected ;
   // find the UL node inside this node
   var theList= this.getNodeUL(); // use lowercase for "ul" tag
   thisNode.removeChild(theList) ; // remove all childs
   // change the actual node image class and button
   thisNode.firstChild.src= this.btnLeafImg ;
   thisNode.firstChild.className="";
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*
   CUT / COPY / PASTE DE NODOS
*/

// CUT the node
TreePanel.prototype.cutSelectedNode = function()
{
   if (! this.selected) { return ; } // no selected node !!!
   var thisNode = this.selected ;
   var theList = thisNode.parentNode ;  // this is the UL list where the current node resides
   var theParent = theList.parentNode ; // this is the grandparent of all of them
   theList.removeChild(thisNode) ; // remove all, may remove the parent UL node too !
   // check to see if we still have LI nodes inside the UL list
   var childs= theList.getElementsByTagName("li") ;
   if (childs.length == 0) { // NO LI nodes remain !
       theParent.removeChild(theList) ; // first remove completely the UL node
       // then change the parent status
       theParent.firstChild.src= this.btnLeafImg ;
       theParent.firstChild.className="";
   }
   return thisNode ;
}

// COPY the node
TreePanel.prototype.copySelectedNode = function()
{
   if (! this.selected) { return ; } // no selected node !!!
   var thisNode = this.selected ;
   return thisNode ;
}

// PASTE the node (inside the selected node ...)
TreePanel.prototype.pasteSelectedNode = function(theNode)
{
   if (! theNode) { return ; }
   if (! this.selected) { return ; } // no selected node !!!
   // find the UL list where we want to insert the new node
   var aList= this.getNodeUL(); // use lowercase for "ul" tag
   // if no List, then it must be a leaf node !
   if (! aList) {
       // create a new UL list, and include the new nodes inside it
       var x= document.createElement("ul") ;
       // copy the node !
       x.innerHTML="<li>"+theNode.innerHTML+"</li>" ;
       // append to the actual node
       this.selected.appendChild(x) ;
       // change the actual node image class and button
       this.selected.firstChild.src= this.btnExpandedImg ;
       this.selected.firstChild.className= this.btnClassName ;
   }
   else {
       // get the current last child node, and modify its text
       var childs= aList.childNodes ;
       // navigate all childs ... just to get the last node
       /* note: other ways of getting the last node return a Text obj, so something is not working ...
          lastNode = childs[childs.length - 1] ;
          -- tried this, but returns a Text object ... which is not what I expected
          -- seems to be some blank text at the end, counted as a child element
       */
       for (var i=0; i < childs.length; i++) {
            // if its the LI tag, it should be subTree
            if ((childs[i].tagName == "LI")) {
               var lastNode= childs[i] ; // we store the last node !
            }
       }
       // now ... create the element to insert
       var x= document.createElement("li") ;
       x.innerHTML= theNode.innerHTML; // copy the node !
       // and insert just before the last item in the list !
       aList.insertBefore(x, lastNode);
   }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*
   MOVING NODES UP AND DOWN
*/

// Moves the node one element up in the hierarchy
TreePanel.prototype.moveUpSelectedNode = function()
{
   if (! this.selected) { return ; }    // no selected node !!!
   var thisNode = this.selected ;
   var theList = thisNode.parentNode ;  // this is the UL list where the current node resides
   if (! theList) { return ; }          // if no List, then it must be a leaf node, something is wrong here !
   var theParent = theList.parentNode ; // this is the grandparent of all of them
   // is this the first node ? if it is, then do nothing
   var childs= theList.childNodes ; var count=0; var k=-1;
   for (var i=0; i < childs.length; i++) {
        if (childs[i].tagName == "LI") {
               if (thisNode == childs[i]) {
                   if (count == 0) { return ; }    // we already are at the TOP ! return ...
                   var sHtml = childs[k].innerHTML ;  // we switch nodes ...
                   childs[k].innerHTML = thisNode.innerHTML ;
                   childs[i].innerHTML = sHtml ;
                   // switch selected nodes
                   this.selectedTitle().className="";
                   this.selected = childs[k];
                   this.selectedTitle().className = this.nodeShowOnSelected;
                   return ;
               }
               else {
                   k = i ; // we store here the previous node position
               }
               count++;
        }
   }
}

// Moves the node one element down in the hierarchy
TreePanel.prototype.moveDownSelectedNode = function()
{
   if (! this.selected) { return ; }    // no selected node !!!
   var thisNode = this.selected ;
   var theList = thisNode.parentNode ;  // this is the UL list where the current node resides
   if (! theList) { return ; }          // if no List, then it must be a leaf node, something is wrong here !
   var theParent = theList.parentNode ; // this is the grandparent of all of them
   // is this the first node ? if it is, then do nothing
   var childs= theList.childNodes ; var count=0; var k=-1;
   for (var i=childs.length-1; i >= 0 ; i--) {
        if (childs[i].tagName == "LI") {
               if (thisNode == childs[i]) {
                   if (count == 0) { return ; }    // we already are at the BOTTOM ! return ...
                   var sHtml = childs[k].innerHTML ;  // we switch nodes ...
                   childs[k].innerHTML = thisNode.innerHTML ;
                   childs[i].innerHTML = sHtml ;
                   // switch selected nodes
                   this.selectedTitle().className="";
                   this.selected = childs[k];
                   this.selectedTitle().className = this.nodeShowOnSelected;
                   return ;
               }
               else {
                   k = i ; // we store here the previous node position
               }
               count++;
        }
   }
}

/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*
   INSERCION DE NODOS
*/

/*
   appendNode ( descr )
   Agrega el nodo cuya descripcion se da, al final de la lista de hijos del nodo actualmente seleccionado.
   El nodo agregado quedara inicialmente en estado "collapsed"
*/

TreePanel.prototype.getNodeUL = function(){
   var aList = null;
   var i=0;
   var cant=$("#tree-content span.node-selected").parent().find("ul").length;
   while (i<cant){
	   aList= this.selected.getElementsByTagName("ul")[i];
	   if (aList) {
	       var tag = aList.parentNode.tagName;
		   if (tag == "DIV") {
			   i++;
		   }
		   else{
			   return aList;
		   }
	   }
   }
   return null;
}

TreePanel.prototype.appendNode = function(txTitle, txInfo) {
   // find the UL list where we want to insert the new node
//  var aList= this.selected.getElementsByTagName("ul")[0] ; // use lowercase for "ul" tag
   var aList = this.getNodeUL();
   if (! aList) {
       // create a new UL list, and include the new nodes inside it
       var x= document.createElement("ul") ;
       x.innerHTML="<li><img class='' src='"+this.btnLeafImg+"'/>"+
                        "<span>"+txTitle+"</span>"+
                        "<div>"+txInfo+"</div>"+
                    "</li>" ;
       // append to the newly created UL node
       this.selected.appendChild(x) ;
       // change the actual node image class and button
       this.selected.firstChild.src= this.btnExpandedImg ;
       this.selected.firstChild.className= this.btnClassName;
   }
   // aList exists, insert at the end of the current UL list
   else {
       // now ... create the element to insert
       var x= document.createElement("li") ;
       x.innerHTML="<img class='' src='"+this.btnLeafImg+"'/>"+
                            "<span>"+txTitle+"</span>"+
                            "<div>"+txInfo+"</div>" ;
       // append inside the actual UL node
       aList.appendChild(x) ;
   }
}

/*
    Mueve el ultimo nodo un lugar hacia arriba
*/
TreePanel.prototype.moveLastNodeUp = function() {
   var thisNode = this.selected ;   
   var theList = this.getNodeUL(); // this is the UL
   if (! theList) { return ; }          // if no List, then it must be a leaf node, something is wrong here !
   // is this the first node ? if it is, then do nothing
   var childs= theList.getElementsByTagName("li") ;
   var k=childs.length-1  ; // the last node
   var j=childs.length-2 ; // the previous one
   if ((j<0) | (k <0)) return ;
   // now we can switch nodes ...
   var sHtml = childs[k].innerHTML ;
   childs[k].innerHTML = childs[j].innerHTML ;
   childs[j].innerHTML = sHtml ;
}

