/**
 * Zalozky
 * *** knihovna ktera umi zalozky ***
 * @author 2008 Michal Sobola, msobola@seznam.cz
 * @revision 2009-11-12
 * @version 1.3.2
 **/

/**
 * ~ changelog from 1.3.0
 * 1.3.1 - pridana vychozi hodnota pro tabMenuId
 *       - moznost vypnout prepinani kotev v url
 *       - rozsireni metdy Tabs.displayOne() o prednastavenou vysku
 * 1.3.2 - kdyz inicializujeme a zalozky nejsou nalezeny, nehazi to errory
 *       - divy zalozek mohou mit i vice trid - uprava metody getElementsByTagAndClassName()  
 **/

/**

  Zalozky = new Tabs();
  // Zalozky.setTabMenu('tabs'); // id menu
  // Zalozky.setTabElement('div'); // prvek, ktery je zalozka (vychozi je div)
  // Zalozky.setTabClassName('dombox'); // css trida zalozky (vychozi je d_box)
  // Zalozky.setActiveClass('active'); // trida aktivni polozky odkazu menu (vychozi je active)
  // Zalozky.setCookieName('showTab'); // jmeno cookie, kt. budeme ukladat (vychozi je showTab)
  // Zalozky.setCookieRemember(false); // nastavi, zda-li budeme uprednostnovat zalozky podle cookie
  // Zalozky.setGetVar('tab'); // jmeno get promenne
  // Zalozky.setSwitchUrl(false); // vypne prepinani v url
  // Zalozky.setActiveTabNo(0); // poradi zalozky, ktera bude zobrazena defaultne (vychozi je nulta)
  // Zalozky.setPlynulyPrechod(true); // budeme vyjizdej plynule (vychozi je ne)
  // Zalozky.setTimeoutValue(10); // hodnota timeoutu v milisec. pro vyjizdeni (vychozi je 10)
  // Zalozky.setDimension('x'); // smer, kterym vyjizdime zalozky (pokud vyjizdime) - v pripade ze je hodnota X - je nutne nastavit sirku zalozky (vychozi je Y)
  // Zalozky.setTabWidth(200); // pokud vyjizdime ze strany na stranu (osa X), je nutne nastavit css sirku objektu zalozek (nema vychozi hodnotu)
  Zalozky.init();

**/

/**
 * ziskani danych elementu s urcitou html tridou
 * @param string htmlTagName jmeno html tagu
 * @param string htmlClassName jmeno html tridy
 * @access private
 * @return array          
 **/
function getElementsByTagAndClassName(htmlTagName, htmlClassName) {
  j = 0;
  elems = [];
  maybeElems = document.getElementsByTagName(htmlTagName);
  for (i = 0; i < maybeElems.length; i++) {
    if ((maybeElems[i].className).indexOf(htmlClassName) != -1) {
      elems[j] = maybeElems[i];
      j++;
    }
  }
  return elems; 
}

/**
 * vytahne a rozparsuje kotvu z url
 * @return array 
 **/ 
function get_hash() {
  hash = document.location.hash.replace(new RegExp('^(.*)#'), '');
  get = {}
  if (hash) {
    hash = hash.split('&');
    for (i = 0; i < hash.length; i++) {
      hash[i] = (hash[i]).split('=');
      get[hash[i][0]] = (hash[i][1] ? hash[i][1] : null);
    }
  }
  return get;
}

/**
 * vrati cookie dle name
 * @param string Name
 **/
function getCookie(Name) {
  replace = new RegExp(Name + "=[^;]+", "i");
  if (document.cookie.match(replace)) {
    return document.cookie.match(replace)[0].split("=")[1]
  }
  return null;
}

/**
 * nastavi cookie
 * @param string name
 * @param string value
 **/
function setCookie(name, value) {
  expires = new Date();
  expires_str = expires.setDate(expires.getDate()+parseInt(365));
  document.cookie = name + "=" + value + "; expires=" + expires.toGMTString() + "; path=/";
}
 
function Tabs() {
  
  /**
   * id zalozkoveho menu
   * @var string
   **/   
  var tabMenuId = 'tabs';

  /**
   * trida zalozky
   * @var string   
   **/   
  var tabClassName = 'dombox';
  
  /**
   * name elementu, ktery je zalozkou - pro rychlejsi vyfiltrovani
   * @var string   
   **/   
  var tabElement = 'div';
  
  /**
   * trida aktivniho odkazu zalozkoveho menu
   * @var string   
   **/   
  var activeClass = 'active';
  
  /**
   * jmeno cookie, kt. budeme ukladat
   * @var string   
   **/   
  var cookieName = 'showTab';

  /**
   * poradi defaultne aktivni zalozky
   * @var int   
   **/   
  var activeTabNo = 0;
  
  /**
   * budeme vyjizdet plynule?
   * @var bool   
   **/   
  var plynulyPrechod = false;
  
  /**
   * prime prepinani kotev v url
   * @var bool
   * @access public   
   **/     
  this.switchUrl = true;
  
  /**
   * timeout v ms
   * @var int   
   **/   
  var timeoutValue = 10;
  
  /**
   * sirka zalozky - pro plynule vyjizdeni do strany
   * @var int   
   **/   
  var saveWidth = 0;
  
  /**
   * smer pri plynulem vyjizdeni - x | y
   * @var string enum ('x','y')  
   **/   
  var dimension = 'y';

  /**
   * zalozkove menu - pouze odkazy
   * @var array   
   **/   
  var tabMenu = [];
  
  /**
   * pocitadlo timeoutu
   * @var int   
   **/   
  var counter = 0;
  
  /**
   * bezici timeouty
   * @var array   
   **/   
  var runningTimeouts = [];
  
  /**
   * regular pro kotvu v url
   * @var object   
   **/   
  var locationHash = new RegExp('^#');
  
  /**
   * jmeno get promenne pro detail zalozky
   * @var string   
   **/     
  var getVar = 'tab';

  /**
   * aktualni kotva
   * @var string   
   **/   
  var kotva;
  
  /**
   * aktualni cookie
   * @var string   
   **/   
  var cookieShow;
  
  /**
   * aktivni index
   * @var int   
   **/   
  var activeIndex;

  /**
   * sam svuj metlos
   * @var object   
   **/   
  var that = this;
  
  /**
   * budeme uprednostnovat zalozky podle cookie?
   * @var bool
   * @access public   
   **/   
  this.cookieRemember = true;
   
  /**
   * zalozkove divy
   * @var array
   * @access public   
   **/   
  this.domTabs = [];
  
  /**
   * nastavi zalozkove menu
   * @param string html id
   **/
  this.setTabMenu = function(id) {
    tabMenuId = String(id);
    itemId = document.getElementById(id);
    if (itemId) {
      tabMenu = itemId.getElementsByTagName('a');
    }
  };
    
  /**
   * nastavi jmeno elementu, kt. budou zalozky - pro lepsi filtrovani
   * @param string elem html tag name       
   **/
  this.setTabElement = function(elem) {
    tabElement = String(elem);
  };
  
  /**
   * nastavi html tridu zalozek
   * @param string html class    
   **/
  this.setTabClassName = function(tabClassNameArg) {
    tabClassName = String(tabClassNameArg);
  };
  
  /**
   * nastavi aktivni tridu odkazu menu - mohou mit pouze jednu tridu   
   * @param string html class   
   **/
  this.setActiveClass = function(activeClassArg) {
    activeClass = String(activeClassArg);
  };
  
  /**
   * jmeno cookie, kt.budmeme nastavovat
   * @param string cookieName      
   **/
  this.setCookieName = function(cookieNameArg) {
    cookieName = String(cookieNameArg);
  };
  
  /**
   * nastavi, jestli u zalozek budeme uprednostnovat hodnotu ulozenou v cookie
   * @param bool remember   
   **/
  this.setCookieRemember = function(remember) {
    this.cookieRemember = (remember ? true : false);
  };
  
  /**
   * nastavi, zda-li se budou zalozky prepinat v kotve
   * @param bool sw   
   **/
  this.setSwitchUrl = function(sw) {
    this.switchUrl = (sw ? true : false);
  };
  
  /**
   * nastavi cislo defaultne aktivni zalozky   
   * @param int no poradi zalozky zacinajici od 0
   **/
  this.setActiveTabNo = function(no) {
    activeTabNo = parseInt(no);
  };
  
  /**
   * budou zalozky vyjizdet plynulym pohybem?
   * @param bool prechod
   **/
  this.setPlynulyPrechod = function(prechod) {
    plynulyPrechod = (prechod ? true : false);
  };
  
  /**
   * nastavi hodnotu timeoutu v milisekundach
   * @param int value   
   **/   
  this.setTimeoutValue = function(value) {
    timeoutValue = parseInt(value);
  };
  
  /**
   * nastavi smer plynuleho prechodu
   * @param string enum value (x | y)
   **/
  this.setDimension = function(value) {
    if (value == 'x' || value == 'y') {
      dimension = value;
    }
  };
  
  /**
   * ulozi sirku zalozky - kvuli rozpinani do stran
   * @param int width
   **/
  this.setTabWidth = function(width) {
    saveWidth = parseInt(width);
  };
  
  /**
   * jen jmeno promenne pro zalozku v getu
   * @param string   
   **/     
  this.setGetVar = function(get) {
    getVar = String(get);
  };

  /**
   * zrusi vsechny probihajici timeouty
   * @access private   
   **/
  function destroyTimeouts() {
    for (i = 0; i < runningTimeouts.length; i++) {
      clearTimeout(runningTimeouts[i]);
    }
  }

  /**
   * inicializace
   *   
   **/
  this.init = function() {
    if (!tabMenu.length) {
      this.setTabMenu(tabMenuId);
    }
  
    this.domTabs = getElementsByTagAndClassName(tabElement, tabClassName);
    kotva = get_hash();
    cookieShow = getCookie(cookieName);
    
    if (!this.domTabs.length) {
    	return false; 
    }

    if (kotva && kotva[getVar]) {
      activeIndex = kotva[getVar];
    } else if (cookieShow && this.cookieRemember) {
      activeIndex = cookieShow;
    } else {
      if (typeof this.domTabs[activeTabNo] == 'object') {
        activeIndex = this.domTabs[activeTabNo].id;
      } else {
        activeIndex = 0;
      }
    }

    this.displayTabs();
    this.activateAnchors(true);
  };

  /**
   * zmena tridy odkazu, pridani akce na onclick
   * @param bool addAction s timto parametrem volame pouze pri loadu stranky
   * @param string toActivate hodnota odkazujici kotvy elementu, ktery bude aktivni       
   **/
  this.activateAnchors = function(addAction, toActivate) {
  
    // nepovinny argument
    if (toActivate === undefined) {
      toActivate = activeIndex;
    }

    winLocHref = (window.location.href).replace(new RegExp('#(.*)'), '');
    wasActivated = false;
   
    // aktivace menu
    for (i = 0; i < tabMenu.length; i++) {
      href = tabMenu[i].href.replace(new RegExp('^([^#]*)#'), '');
      
      // prisli jsme z onclicku, v hrefu je neco navic nez pred tim
      if (!addAction) {
        href = href.split('=')[1];
      }
      
      // rozparsujeme href, pridame akci
      if (addAction) {
        tabMenu[i].href = winLocHref + '#' + getVar + '=' + href;

        // this je tuna objekt, kteremu je pridavan onclick a that je this
        tabMenu[i].onclick = function() {
          link = (this.href).replace(new RegExp('^([^#]*)#' + getVar + '='), '');
          that.activateAnchors(false, link);
          that.displayTabs(link, true);
          if (that.cookieRemember) {
            setCookie(cookieName, link);
          }
          return that.switchUrl;
        };
      }
      
      if (href == toActivate && !wasActivated) {
        tabMenu[i].className = activeClass;
        wasActivated = true;
      } else {
        tabMenu[i].className = '';
      }
    }
    
    // kdyby neco selhalo, aktivujeme prvni
    if (!wasActivated && typeof tabMenu[0] == 'object') {
      tabMenu[0].className += ' ' + activeClass;
    }
  };

  /**
   * zobrazeni zalozek
   * @param string toActivate ID zalozky na zobrazeni
   * @param bool wasClicked pri loadu stranky preskocime pripadny plynuly efekt
   **/
  this.displayTabs = function(toActivate, wasClicked) {
    
    // nepovinne argumenty
    if (toActivate === undefined) {
      toActivate = activeIndex;
    }
    
    if (wasClicked === undefined) {
      wasClicked = false;
    }
    
    wasDisplayed = false;
    
    // zobrazeni zalozek
    for (i = 0; i < this.domTabs.length; i ++) {
      if (toActivate == this.domTabs[i].id && !wasDisplayed) {
        this.domTabs[i].style.display = 'block';
        toShow = this.domTabs[i];
        wasDisplayed = true;
      } else {
        this.domTabs[i].style.display = 'none';
      }
    }
    
    // kdyby neco selhalo, zobrazime prvni
    if (!wasDisplayed && typeof this.domTabs[0] == 'object') {
      this.domTabs[0].style.display = 'block';
    }

    // vyjizdime plynule?
    if (plynulyPrechod && wasClicked) {
      toShow.style.overflow = 'hidden';
      counter = 0;
      
      // zlikvidujeme bezici timeouty
      destroyTimeouts();
      
      // podminka pro vyjizdeni do strany nebo dolu
      if (dimension == 'x') {
        toShow.style.width = 0;
        runningTimeouts[counter] = setTimeout(function() { 
          that.showElemX(toShow, counter); }, timeoutValue
        );
      } else if (dimension == 'y') {
        toShow.style.height = 0;
        runningTimeouts[counter] = setTimeout(function() { 
          that.showElemY(toShow, counter); }, timeoutValue
        );
      }
    }
  };
  
  /**
   * plynule zobrazi zalozku shora dolu
   * @param object elem zalozky, se kt. pracujeme
   * @param int counter pocet probehlych timeoutu
   * @param callback extraFunction       
   **/
  this.showElemY = function(elem, counter, extraFunction) { 
    if (extraFunction) {
      extraFunction();
    }
    counter++;
    if (elem.scrollHeight > elem.offsetHeight){
      posun = Math.round((elem.scrollHeight-elem.offsetHeight) / timeoutValue);
      if (posun < 1) {
        posun = 1;
      }
      elem.style.height = (elem.offsetHeight+posun) + 'px';
      runningTimeouts[counter] = setTimeout(function() { that.showElemY(elem, counter, extraFunction); }, timeoutValue);
    }
  };
  
  /**
   * plynule zobrazi zalozku ze strany na stranu
   * @param object elem zalozky, se kt. pracujeme
   * @param int counter pocet probehlych timeoutu    
   **/
  this.showElemX = function(elem, counter) {
    counter++;
    if (saveWidth > elem.offsetWidth){
      posun = Math.round((saveWidth-elem.offsetWidth) / timeoutValue);
      if (posun < 1) {
        posun = 1;
      }
      elem.style.width = (elem.offsetWidth+posun) + 'px';
      runningTimeouts[counter] = setTimeout(function() { that.showElemX(elem, counter); }, timeoutValue);
    }
  };
  
  /**
   * rozsireni
   * pro plynule rozjeti jednoho prvku
   * @param string id HTML id prvku     
   **/
  this.displayOne = function(id, self, originalLabel, onchangeLabel, extraFunction, origHeight) {
    toShow = document.getElementById(id);
    if (typeof extraFunction == 'undefined') {
      extraFunction = null;
    }
    if (!toShow.offsetHeight || (origHeight && origHeight == toShow.offsetHeight)) {
      if (self && onchangeLabel) {
        self.innerHTML = onchangeLabel;
      }
      toShow.style.height = (Number(origHeight) ? origHeight : 0);
      toShow.style.display = 'block';
      toShow.style.overflow = 'hidden';
      counter = 0;
      destroyTimeouts();
      runningTimeouts[counter] = setTimeout(function() { that.showElemY(toShow, counter, extraFunction); }, timeoutValue);
    } else {
      if (self && originalLabel) {  
        self.innerHTML = originalLabel;
      }
      toShow.style.height = (Number(origHeight) ? origHeight + 'px' : 0);
      if (!toShow.style.height) {
        toShow.style.display = 'none';
      }
    }
  }
}