/**
 * Projekt WAP - Formular se zalozkami
 * Michal Sebek, xsebek00
 * 
 * Script prevede zalozkovatelne formulare na strance po spusteni
 * scriptu na zalozkovane a umoznuje mezi nimiprepinat a presouvat
 * zalozky mezi sebou.  
 *  
 * (c) 2008, Vsechna prava vyhrazena 
 */

/******************************************************************************/
/******************************************************************************/


/* Definice konstant */
var CLASS_NAME_FORM_TABBLED       = "tabbed";
var CLASS_NAME_TAB                = "tab";
var CLASS_NAME_BOOKMARK_ACTIVE    = "bookmark-active";
var CLASS_NAME_BOOKMARK_INACTIVE  = "bookmark-inactive";
var CLASS_NAME_BOOKMARK_DRAG_DROP = "bookmark-dropping";
var CLASS_NAME_BOOKMARK_HEADER    = "bookmark-header";
var CLASS_NAME_ACTIVE_TAB         = "active";
var UNDEFINED_TYPE = "undefined";

var DISPLAY_BLOCK  = "block";
var DISPLAY_NONE   = "none";

var POSITION_RELATIVE  = "relative";
var POSITION_ABSOLUTE  = "absolute";

var BOOKMARKS_STYLE_MARGIN = 6;


/******************************************************************************/


/* Globalni objekty*/
var actDraggedObj             = null;   /* Prave presouvany objekt */
var actDraggedObjMouseOffset  = null;   /* Offset mysi v ramci actDraggedObj */


/******************************************************************************/



function hasClass(n, c) {

	if (!n || !c)
		return false;

	return (' ' + n.className + ' ').indexOf(' ' + c + ' ') !== -1;
}
		
/**
 * Predikat urcijici, jestli elem je element DIV kontejner. 
 */
function isDivElement(elem) {
    if (!elem)
      return false;
    return ( elem.nodeName=="DIV" );
} /* isDivElement() */

/**
 * Predikat urcijici, jestli elem je element SPAN kontejner. 
 */
function isSpanElement(elem) {
    if (!elem)
      return false;
    return ( elem.nodeName=="SPAN" );
} /* isSpanElement() */

/**
 * Predikat urcijici, jestli elem je element DIV s tridou "tab". 
 */
function isDivTabElement(elem) {
    if (!elem)
      return false;
    return ( isDivElement(elem) && hasClass(elem, CLASS_NAME_TAB) );
} /* isDivTabElement() */


/**
 * Dodefinovana metoda - vlozi uzel node1 za uzel node2.
 */
function insertAfter(node1, node2) {

    parentNode = node1.parentNode;
    var i; 
    var node2index = -1;
    
    // Ziskani pozice uzlu node2, za ktery se bude vkladat
    for (i=0; i<parentNode.childNodes.length; i++)    
        if ( parentNode.childNodes[i] == node2 )
            node2index = i;

    if (node2index == parentNode.childNodes.length-1 || node2==null )
        // pokud node2 neni, nebo se vklada na konec, 
        // tak vlozime prvek do parentNode na konec
        parentNode.appendChild(node1);
    else if (node2index>=0)
        // vlozi prvek za uzel node2 (pozice index+1)
        parentNode.insertBefore(node1, parentNode.childNodes[node2index+1]);

} /* insertAfter() */


/**
 * Inicializacni funkce pro Formular se zalozkami. Vyhleda vsechny formulare
 * na strance, zjisti, jestli jsou zalozkovatelne a pripadne je zpracuje.
 * Zneviditelni vsechny zalozky krom prvni a spolecne a vytvori hlavicku
 * se zalozkami.   
 */
function initTabbedForms() {
    var i ;
    
    /* Projde vsechny formulare a zjisti, ktere tabelovat */
    var tabs = document.getElementsByClassName("tabbed-form");
    for (i=0; i<tabs.length; i++) {
          var actForm = tabs[i];
          initForm( actForm ); /* inicializuj */
          displayTabBookmarks( actForm ); /* zobraz zalozky */
        
    }
    

} /* initTabbedForms() */


/**
 * Inicializace formulare fInit. Najde vsechny zalozky, zobrazi z nich prvni,
 * ostatni skryje. Resi problem s ruznou delkou zalozek tak, ze velikost vsech
 * nastavi na velikost nejvyssiho kontejneru.   
 */
function initForm( fInit ) {
    var i            = 0;
    var isFirstDIV   = true;
    var maxTabHeight = 0;    // Docasne ulozeni nejvyssiho konejneru
    var firstTabElem = null;

    /* Pokud formular neni prazdny kontejner... */
    if ( fInit.hasChildNodes() ){
       var formChilds = fInit.childNodes;
       
       /* Vybereme potomky formulare a zneviditelnime vsechny "tab" krom prvniho */
       for (i=0; i<formChilds.length; i++) {
          if ( isDivTabElement(formChilds[i]) ) { // Jde o zalozku - kontejner?
            
              /* Zjistime vysku kontejneru, pokud je vyssi nez nejvyssi, nahradime nejvyssi */
              maxTabHeight = ( maxTabHeight > formChilds[i].offsetHeight ? maxTabHeight : formChilds[i].offsetHeight );
  
              
              if (isFirstDIV) {// jde o prvni ?
                  formChilds[i].style.display = DISPLAY_BLOCK; // zobrazit
                  firstTabElem = formChilds[i];
              }    
              else // nejde o prvni , skryt
                  formChilds[i].style.display = DISPLAY_NONE;
                    
              
              if ( hasClass(formChilds[i], CLASS_NAME_ACTIVE_TAB) ){
                firstTabElem.style.display = DISPLAY_NONE;
                formChilds[i].style.display = DISPLAY_BLOCK; // zobrazit
              }
                 
              isFirstDIV = false; // jiz neni prvni              
              
          } /* if() */ 
       } /*for()*/

       /* Nastavi vsechny kontejnery na velikost nejvyssiho */
       for (i=0; i<formChilds.length; i++) {
          if ( isDivTabElement(formChilds[i]) ) 
              formChilds[i].style.height = maxTabHeight+"px";
       } /*for()*/

    } /* if(hasChildNodes) */ 

} /* initForm() */


/**
 * Vytvori pro formular fForm pred prvni zalozku kontejner div tridy "bookmark-header"  
 * pro zobrazeni vsech zalozek formulare.   
 */
function displayTabBookmarks( fForm ) {
    var i = 0;
    var isFirstDIV = true;

    if ( fForm.hasChildNodes() ) {
       // Pokud formular ma nejaky obsah
       var formChilds = fForm.childNodes;
       
       /* Pred prvni element DIV vlozi zalozkovy kontejner */
       for (i=0; i<formChilds.length; i++) {
           if ( isDivElement(formChilds[i]) ) {
                
              /* Pred prvni div vlozime zalozky */  
              if (isFirstDIV) {
                  // Vytvori element DIV tridy bookmark-header
                  var bookmarksDIV = document.createElement("DIV");
                  var newAttr = document.createAttribute("class");
                  newAttr.nodeValue = CLASS_NAME_BOOKMARK_HEADER;
                  bookmarksDIV.setAttributeNode(newAttr); 

                  // Vlozi vytvoreny kontejner pred zalozky a 
                  // spusti vygenerovani zalozek
                  fForm.insertBefore(bookmarksDIV, formChilds[i]);
                  createBookmarks( fForm, bookmarksDIV );
                  break;
              }    
              //isFirstDIV = false;
            
          } /* if() */ 
       } /*for()*/

    } /* if(hasChildNodes) */ 

} /* displayTabBookmarks() */


/**
 * Vytvori pro formular fForm zalozky do elementu  bookmarksDIV. 
 * Vsechny puvodni zalozky nejdrive zrusi. Zalozku vytvori Pro kazdy
 * kontejner tab vytvori prislusnou zalozku s popiskem odpovidajicim title 
 * kontejneru. Nastavi pro zalozky prilusne udalosti. Aktivitu zalozek
 * urcije podle vlastnosti style.display prislusneho tab kontejneru (obsahu zalozky).    
 */
function createBookmarks( fForm, bookmarksDIV ) {
    var i;
    
    if ( bookmarksDIV.hasChildNodes() ) {
        /* Pokud ma div s hlavickou zalozky, smazeme je */
        while (bookmarksDIV.childNodes.length) 
            bookmarksDIV.removeChild(bookmarksDIV.childNodes[0]);       
    }

    if ( fForm.hasChildNodes() ) {
       /* Pokud formular neni prazdny */
       var formChilds = fForm.childNodes;
       
       /* Pro kazdy div tab vytvorime zalozku */
       for (i=0; i<formChilds.length; i++) {
          if ( isDivTabElement(formChilds[i]) ) {
                // pokud jde o kontejner zalozky
                
                var actTab = formChilds[i]; // aktualni kontejner zalozky
                
                // vytvori novou zalozku
                var newBookmark   = document.createElement("SPAN");
                var newClassAttr  = document.createAttribute("class");
                
                /* Rozhodne o aktivite zalozky*/
                if (actTab.style.display == DISPLAY_NONE) {
                    /* neaktivni zalozka, kontejner skryt */
                    newClassAttr.nodeValue = CLASS_NAME_BOOKMARK_INACTIVE;   
                    /* Pri kliknuti akce prepnuti zalozek */
                    newBookmark.onclick = function() { activateBookmark(this); };
                } else {
                    /* aktivni zalozka */
                    newClassAttr.nodeValue = CLASS_NAME_BOOKMARK_ACTIVE;
                }
                
                
                // Nove zalozce vytvori obsah podle titluku kontejneru
                newBookmark.setAttributeNode(newClassAttr);                                 
                newBookmark.appendChild( document.createTextNode(actTab.title) );
                
                // vlozi novou zalozku do ontejneru zalozek
                bookmarksDIV.appendChild(newBookmark);
                bookmarksDIV.appendChild( document.createTextNode(" ") );
                /**
                 * V zalozce vypne funkci oznaceni textu
                 *                                 
                 * Inspirovano kodem Disable Text Selection script
                 * URL: http://www.dynamicdrive.com/dynamicindex9/noselect.htm                        
                 */
                if (typeof newBookmark.onselectstart != UNDEFINED_TYPE) //IE 
                  	newBookmark.onselectstart = function(){return false;};
                else if (typeof newBookmark.style.MozUserSelect != UNDEFINED_TYPE) //Firefox 
                	  newBookmark.style.MozUserSelect="none";
                              
            
          } /* if() */ 
       } /*for()*/

    } /* if(hasChildNodes) */   
         
} /* createBookmarks() */


/**
 * Ziska index zalozky bookmark v ramci ostatnich (pocitano od 0-prvni).
 * Vraci -1 pokud dojde k neocekavane chybe DOM modelu.     
 */
function getBookmarkIndex(bookmark){
     var iDivs = 0; /* Indexace poradi kontejneru div */
     /* Zjistime poradi zalozky */
     for (i=0; i<bookmark.parentNode.childNodes.length; i++) {
        // Projdeme vsechny zalozky a pocitame index
        if (isSpanElement((bookmark.parentNode.childNodes)[i]))
        {
            if  (bookmark == (bookmark.parentNode.childNodes)[i] )
                return iDivs;
            iDivs++; // inkrementace indexu kontejneru 
        }    
     } /*for()*/  
     
     return -1;
} /* getBookmarkIndex() */


/**
 * Funkce aktivuje zalozku bookmark, zobrazi prislusny formular a 
 * reinicializuje vsechny zalozky.    
 */
function activateBookmark( bookmark ){     
     var formChilds = bookmark.parentNode.parentNode.childNodes; /* Ziska kontejnery zalozek*/
     var i; 
     var iDivs = 0; /* Indexace poradi kontejneru div */
     
     /* Ziska index zalozky (poradi) */
     var bookmarkId = getBookmarkIndex(bookmark); 
     
     /* Pres vsechny zalozky (a jine polozky) */
     for (i=0; i<formChilds.length; i++) {
        if ( isDivTabElement(formChilds[i]) ) { // jde o kontejner zalozky?
              
            if ( iDivs == bookmarkId ) // pokud index aktivovane zalozky je roven aktualni
                formChilds[i].style.display = DISPLAY_BLOCK;  // zviditelni kontejner 
            else // a skryj ostatni kontejnery zalozek
                formChilds[i].style.display = DISPLAY_NONE;
            
            iDivs++; // inkrementace indexu kontejneru 
        
        } /* if() */ 
     } /*for()*/    
    
     // Znovu-vygeneruje vsechny zalozky (podle viditelnosti kontejneru)
     createBookmarks( bookmark.parentNode.parentNode, bookmark.parentNode );
} /* activateBookmark() */



/**
 * Ziska kontejner zalozky podle indexu id ve formularu tabForm.
 * Pri neuspechu vraci null. 
 */
function getBookmarkTabById(tabForm, id) {
    var iDivs = 0; // Index kontejneru
    var formChilds = tabForm.childNodes; // Ziska potomky formulare
    
    for (i=0; i<formChilds.length; i++) {
      if ( isDivTabElement(formChilds[i]) ) { // jde o kontejner  zalozky?
            
          if ( iDivs == id ) // pokud ma spravnou polozku, vrati ji
              return formChilds[i];
          
          iDivs++;    
      
      } /* if() */ 
    } /*for()*/  
    
    // index mimo pole
    return null;

} /* getBookmarkTabById() */


/**
 * Reakce na pohyb mysi. Pokud existuje nejaky objekt k presunu, tak s 
 * nim pohybuje. 
 */
function mouseMove(ev){
  // IE kompatibilni
	ev           = ev || window.event;
	// Ziskani pozice mysi
	var mousePos = getMousePosition(ev); 
	
	if (actDraggedObj){ // pokud je nejaky objekt presunovan
	    // Objekt posunuje vuci relativni pozici
      actDraggedObj.style.position = POSITION_RELATIVE;
      // Nove souradnice objektu podle pozice mysi
      actDraggedObj.style.top      = mousePos.y-actDraggedObjMouseOffset.y+'px';
      actDraggedObj.style.left     = mousePos.x-actDraggedObjMouseOffset.x+'px';
      // Trida objektu je "bookmark-drop"
      actDraggedObj.className      = CLASS_NAME_BOOKMARK_DRAG_DROP;
      return false; // dalsi reakce nejsou umozneny!!
  }
	
} /* mouseMove() */


/**
 * Ziska pozici elementu pres offsety rodice, rekurzivne. 
 * Vraci strukturu (x,y) s pozici.
 */
function getElementPosition(elem){
  var position = {x:0, y:0};
  
  /* Dokud element existuje, pripocteme offset a prejde na rodice */
  for (;elem != null; elem = elem.offsetParent)
  {
      position.x += elem.offsetLeft;
      position.y += elem.offsetTop;
  }

  return position;
} /* getElementPosition() */


/**
 * Funkce ziska pozici mysi (x,y) z objektu ev.
 *  
 * Funkce castecne inspirovana resenim na URL:
 *   http://www.webreference.com/programming/javascript/mk/column2/
 */
function getMousePosition(ev){
    ev           = ev || window.event;
    
  	if(ev.pageX || ev.pageY){
  		  return {x:ev.pageX, y:ev.pageY};
  	}

    // Varianta pro IE, nutne pocitat i scroll-souradnice
    var xScroll = 0;
    var yScroll = 0;

  	if (document.documentElement && document.documentElement.scrollTop)
  	{ // DTD 4.01+
  	   xScroll = document.documentElement.scrollLeft - document.documentElement.clientLeft;
       yScroll = document.documentElement.scrollTop - document.documentElement.clientTop;            
    }   
    else if (document.body && document.body.scrollTop)
    { // stare DTD HTML
       xScroll = document.body.scrollLeft - document.body.clientLeft;
       yScroll = document.body.scrollTop - document.body.clientTop;  
    }

  	return {
    		x:ev.clientX + xScroll /*+ document.body.scrollLeft - document.body.clientLeft*/,
    		y:ev.clientY + yScroll /* - document.body.clientTop*/
  	};
} /* getMousePosition() */


/******************************************************************************/
/******************************************************************************/
