/* ******************************************************************************
najit predchozi sourozenecky uzel nebo vratit null pokud zadny neni. Nevraci
textove uzly ani komentare

@param    obj - objekt od ktereho se hleda
@param    ev - typ eventu
@param    fce - callback funkce
@return   vraci uzel nebo null
****************************************************************************** */
function addEvent(obj, ev, fce) {
  // pro FF, Operu, Chrome a jine co to podporujou
  if(obj.addEventListener) {
    obj.addEventListener(ev, fce, false);
  }
  // pro blbou MSIE
  else {
    if(obj.attachEvent) {
      obj.attachEvent("on" + ev, fce);
    }
  }
}

/* ******************************************************************************
najit predchozi sourozenecky uzel nebo vratit null pokud zadny neni. Nevraci
textove uzly ani komentare

@param    obj - objekt od ktereho se hleda
@return   vraci uzel nebo null
****************************************************************************** */
function previousSibling(obj) {
  // pokud existuje previousSibling
  if(obj.previousSibling) {
    do { // pokracovat dokud nenarazi na node nebo zacatek
      obj = obj.previousSibling;
    } while(!(obj == null || obj.nodeType == 1)) // pokud to neni element nebo zadny predchozi neni
  }
  else {
    obj = null;
  }

  return obj;
}


/* ******************************************************************************
najit nasledujici sourozenecky uzel nebo vratit null pokud zadny neni. Nevraci
textove uzly ani komentare

@param    obj - objekt od ktereho se hleda
@return   vraci uzel nebo null
****************************************************************************** */
function nextSibling(obj) {
  // pokud existuje nextSibling
  if(obj.nextSibling) {
    do { // pokracovat dokud nenarazi na node nebo konec
      obj = obj.nextSibling;
    } while(!(obj == null || obj.nodeType == 1)) // pokud to neni element nebo zadny dalsi neni
  }
  else {
    obj = null;
  }

  return obj;
}


/* ******************************************************************************
najit prvni dceriny uzel nebo vratit null pokud zadny neni. Nevraci textove uzly
ani komentare

@param    obj - objekt od ktereho se hleda
@return   vraci uzel nebo null
****************************************************************************** */
function firstChild(obj) {
  // pokud existuje firstChild
  if(obj.firstChild) {
    obj = obj.firstChild;
  }

  return (obj == null || obj.nodeType == 1) ? obj : nextSibling(obj);
}


/* ******************************************************************************
najit posledni dceriny uzel nebo vratit null pokud zadny neni. Nevraci textove
uzly ani komentare

@param    obj - objekt od ktereho se hleda
@return   vraci uzel nebo null
****************************************************************************** */
function lastChild(obj) {
  if(obj.lastChild) {
    obj = obj.lastChild;
  }

  return (obj == null || obj.nodeType == 1) ? obj : previousSibling(obj);
}


/* ******************************************************************************
Zkratit retezec na maximalni delku len. Neusekava slova ale zkrati retezec od
posledni mezery, carky, tecky nebo stredniku

@param    str - textovy retezec
@param    len - delka na kterou se ma retezec zkratit
@return   zkraceny retezec
****************************************************************************** */
function cutString(str, len) {
  // pokud je to retezec
  if(typeof(str) == 'string') {
    // pokud je retezec delsi nez nez je pozadovana hodnota
    if(str.length > len) {
      var match = new Array(" ", ",", ".", ";");
      str = str.substring(0, str.lastIndexOf(match[0], len - 3)) + "...";
    }
  }

  return str;
}


/* ******************************************************************************
Neni to sice fce ale prida udalost onload initForms ktera projde vsechny
formulare a nastavi jim pozadi, romecky atd. Vynechava Konueror kterej to
nezvlada.
****************************************************************************** */
if(navigator.appName != "Konqueror") {
  // pro FF, Operu, Chrome a jine co to podporujou
  addEvent(window, "load", function() {
    initForms(null);
    });
}


/* ******************************************************************************
Projit formular(e) v dokumentu a zavolat obsluzne fce pro jednotlive typy poli
formularu. Pokud je zadan obj tak projde jen tento formular.

@param    obj - pokud neni null tak projit cely document. Jinak projde jen
          formular predany v objektu obj
@return   (void)
****************************************************************************** */
function initForms(obj) {
  var elm;

  // pokud byl predan formular tak nasimulovat jako by to byl
  // objekt document a projit jen tento formular
  if(obj != null) {
    obj.forms = new Array(obj);
    obj.forms.length = 1;
  }
  // projit vsechny formulare
  else {
    if(document.forms.length == 0) {
      return;
    }
    obj = document;
  }

  for(var i = 0; i < obj.forms.length; i++) {
    for(var j = 0; j < obj.forms[i].elements.length; j++) {
      elm = obj.forms[i].elements[j];
      switch(elm.tagName.toLowerCase()) {
        case 'input' :
          switch(elm.type.toLowerCase()) {
            case 'text' :
            case 'password' :
              initInputText(elm);
              break;
            case 'checkbox' :
              initInputCheckBox(elm);
              break;
            case 'button' :
            case 'submit' :
              initInputButton(elm);
              break;
          }
          break;
        case 'select' :
          // u Opery to dela bordel s jejim skinem
          if(navigator.appName == 'Opera') {
            break;
          }
        case 'textarea' :
          initTextArea(elm);
          break;
      }
    }
  }
}


/* ******************************************************************************
Inicializovat CheckBox. Misto checkboxu vlozi preklapeci obrazek a schova samotny
checkbox. Volano z fce initForms()

@param    cBox - objekt CheckBox
@return   (void)
****************************************************************************** */
function initInputCheckBox(cBox) {
  var img, label;
  label = cBox.parentNode;

  img = document.createElement('img');
  img.src = '/img/spacer.gif';
  img.width = img.height = 14;
  img.style.background = 'url(/img/checkbox.gif) no-repeat';
  img.style.backgroundPosition = cBox.checked ? '-28px 0px' : '0px 0px';

  // nazaskrtnuty checkbox ma hover efekt
  if(!cBox.checked) {
    //addEvent(label, 'mouseover', function() { this.firstChild.style.backgroundPosition = '-14px 0px';});
    //addEvent(label, 'mouseout', function()  { this.firstChild.style.backgroundPosition = '0px 0px';});
    label.onmouseover = function() { this.firstChild.style.backgroundPosition = '-14px 0px';};
    label.onmouseout = function()  { this.firstChild.style.backgroundPosition = '0px 0px';};
  }

  label.style.cursor = 'pointer';
  label.insertBefore(img, cBox);

  addEvent(cBox, 'click', function() { return switchCBox(this); });
  cBox.style.visibility = 'hidden';
}


/* ******************************************************************************
Prepnout CheckBox a preklopit obrazek

@param    cbox - objekt checkboxu
@return   false - aby kliknuti dal neprobublavalo
****************************************************************************** */
function switchCBox(cbox) {
  var label, img;
  label = cbox.parentNode; // label
  img = label.firstChild;

  if(cbox.checked) {
    img.style.backgroundPosition = '-28px 0px';
    label.onmouseover = null;
    label.onmouseout = null;
  }
  else {
    img.style.backgroundPosition =  '0px 0px';
    label.onmouseover = function() { firstChild(this.firstChild).style.backgroundPosition = '-14px 0px';};
    label.onmouseout = function() { firstChild(this.firstChild).style.backgroundPosition = '0px 0px';};
  }

  return true;
}


/* ******************************************************************************
Inicializovat Input typu text. Pred a za pole vlozi obrazek a policku nastavi
pozadi. Volano z fce initForms()

@param    tBox - objekt textoveho pole
@return   (void)
****************************************************************************** */
function initInputText(tBox) {
  var img;
  // MSIE nezvlada ramecek pred a po
  if(navigator.appName == 'Microsoft Internet Explorer') {
    return;
  }
  // pridat levy ramecek
  img = document.createElement('img');
  img.style.cssFloat = 'left';
  img.src = '/img/spacer.gif';
  img.width = 3;
  img.height = 22;
  img.style.background = 'url(/img/text_left.png) 0px 0px no-repeat';
  tBox.parentNode.insertBefore(img, tBox);

  // pridat pravy ramecek
  img = document.createElement('img');
  img.style.cssFloat = 'left';
  img.src = '/img/spacer.gif';
  img.width = 3;
  img.height = 22;
  img.style.background = 'url(/img/text_right.png) 0px 0px no-repeat';
  if(tBox.nextSibling != 'undefined') {
    tBox.parentNode.insertBefore(img, tBox.nextSibling);
  } else {
    tBox.parentNode.appendChild(img, tBox.parentNode);
  }


  // nastavit input element
  tBox.style.background = 'url(/img/text_center.png) 0px 0px repeat-x #FFFFFF';
  tBox.style.border = '0px';
  tBox.style.cssFloat = 'left';
  tBox.style.padding = '3px 0px';


  // pridat udalost onfocusu
  addEvent(tBox, 'focus', function() {
    this.style.backgroundPosition = '0px -22px';
    this.previousSibling.style.backgroundPosition = '0px -22px';
    this.nextSibling.style.backgroundPosition = '0px -22px';
    });
  // pridat udalost onblur
  addEvent(tBox, 'blur', function() {
    this.style.backgroundPosition = '0px 0px';
    this.previousSibling.style.backgroundPosition = '0px 0px';
    this.nextSibling.style.backgroundPosition = '0px 0px';
    });
}


/* ******************************************************************************
Inicializovat Input typu button, submit a reset. Tlacitku nastavi preklapeci
obrazek na pozadi. Volano z fce initForms()

@param    button - objekt tlacitka
@return   (void)
****************************************************************************** */
function initInputButton(button) {
  button.style.border = '0px';
  button.style.height = '22px';
  //elm.style.fontWeight = "bold";

  if(button.scrollWidth <= 100) {
    button.style.background = 'url(/img/button_xs.png) 0px 0px no-repeat';
    button.style.width = '100px';
  }
  else {
    button.style.background = 'url(/img/button_s.png) 0px 0px no-repeat';
    button.style.width = '150px';
  }

  addEvent(button, 'mouseover', function() { button.style.backgroundPosition = '-' + button.style.width + ' 0px'; });
  addEvent(button, 'mouseout', function() { button.style.backgroundPosition = '0px 0px'; });
  addEvent(button, 'mouseup', function() { button.style.backgroundPosition = '0px 0px'; });
  addEvent(button, 'click', function() { button.style.backgroundPosition = '-' + (button.offsetWidth * 2) + 'px 0px'; });
  addEvent(button, 'mousedown', function() { button.style.backgroundPosition = '-' + (button.offsetWidth * 2) + 'px 0px'; });
}


/* ******************************************************************************
Inicializovat TextArea. Elementu nastavi ramecek. Volano z fce initForms()

@param    tArea - objekt TextArea
@return   (void)
****************************************************************************** */
function initTextArea(tArea) {
  tArea.style.border = '#808C96 1px solid';

  addEvent(tArea, 'focus', function() { this.style.borderColor = '#3A6389'; });
  addEvent(tArea, 'blur', function(){ this.style.borderColor = '#808C96'; });
}


/* ******************************************************************************
vrati obsah formulare v stringu pouzitelnem pro GET i POST dotaz
alert(getFormContent(document.forms[0]))

@param    obj - objekt formulare ke zpracovani
@return   str - textovy retezec s obsahem formularu
****************************************************************************** */
function getFormContent(obj) {
  var elm, data, name;
  data = "";
  name = "";

  for(var i = 0; i < obj.elements.length; i++) {
    elm = obj.elements[i];

    // pokud je disablovany nebo nema jmeno tak nepokracovat
    if(elm.disabled || elm.name == "") {continue;}

    switch(elm.nodeName.toLowerCase()) {
      case "input" :
        // pokud je to nezaskrtnuty checkbox nebo radiobutton, nepokracovat
        if((elm.type == "checkbox" || elm.type == "radio") && !elm.checked) {break;}
        if(elm.type == "button" || elm.type == "submit") {break;} // tlacitka neodesilat
      case "textarea" :
        data += elm.name + "=" + encodeURIComponent(elm.value) + "&";
        break;

      case "select" :
        name = elm.multiple ? elm.name + "[]" : elm.name;
        // projit vsechny prvky selektu
        for(var j = 0; j < elm.options.length; j++) {
          if(elm.options[j].seleced) {
            data += name + "=" + encodeURIComponent(elm.options[j].value) + "&";
          }
        }
    }
  }

  data = data.substr(0, str.length - 1); // odstranit posledni &

  return str;
}


/* ******************************************************************************
overit spravnost vyplneneho formulare

@param    obj - objekt formulare ke kontrole
@return   result - true pokud je formular v poradku, jinek false
****************************************************************************** */
function validateForm(obj) {
  var elm, label, msg, result;
  msg = "Some fields are not filled or are filled incorrectly:\n\n"; // chybova hlaska v pripade neuspechu
  result = true; // vysledek je implicitne na true

  // zajistit aby obj byl form
  if(obj.nodeName.toLowerCase() != "form") {
    obj = obj.form;
  }

  // projit cely formular
  for(var i = 0; i < obj.elements.length; i++) {
    elm = obj.elements[i];

    // pokud je prvek vyzadovan
    if(elm.className.indexOf("required") >= 0) {
      // pokud neni prvek vyplnen
      if(elm.value.length == 0) {
        label = findFormLabel(elm); // najit popisek
        label.style.color = "#B00000"; // zcervenat popisek
        msg += '- field ' + label.textContent + ' is required\n'; // pripojit chybovou hlasku
        // pokud je to prvni chyba
        if(result) {
          elm.focus(); // nastavit prvku focus
        }
        result = false; // nastavit vysledek na false
      }
      // Prvek je vyplnen
      else {
        findFormLabel(elm).style.color = ""; // zacernat popisek
      }
    }
    // pokud je prvek e-mail a je vyplnen
    if(elm.className.indexOf("email") >= 0 && elm.value.length > 0) {
      // pokud neodpovida platnemu e-mailu
      if(elm.value.search(/^[a-z0-9]+([\._-]{1}[a-z0-9]+)*@[a-z0-9_-]+(\.[a-z0-9_-]+)+$/ig) == -1) {
        label = findFormLabel(elm); // najit popisek
        label.style.color = "#A00000"; // zcervenat popisek
        msg += '- field ' + label.textContent + ' is not valid e-mail.\n'; // pripojit chybovou hlasku
        result = false; // nastavit vysledek na false
      }
      // pokud je e-mail OK
      else {
        findFormLabel(elm).style.color = ""; // zacernat popisek
      }
    }
  }

  // pokud validace neuspela
  if(!result) {
    alert(msg);   // vyhodit chybovou hlasku
  }

  return result;
}


/* ******************************************************************************
najit obpovidajici label prvku formulare

@param    obj - objekt prvku formulare
@return   elm - odpovidajici label
****************************************************************************** */
function findFormLabel(obj) {
  var elm;

  elm = obj.form.getElementsByTagName("label"); // pole vsech label elementu ve formulari

  // projit vsechny labely a najit ten spravny
  for(var i = 0; i < elm.length; i++) {
    // pokud se name prvku formulare shoduje s for labelu
    if(elm[i].htmlFor == obj.id) {
      return elm[i];  // vratit dany popisek
    }
  }

  return null; // popisek nebyl nalezen
}


/* *****************************************************************************
definovat XMLHttpRequest pro stary MSIE
***************************************************************************** */
if(typeof XMLHttpRequest == 'undefined') {
  XMLHttpRequest = function() {
  return new ActiveXObject(navigator.userAgent.indexOf("MSIE 5") >= 0 ? "Microsoft.XMLHTTP" : "Msxml2.XMLHTTP");
  }
}


/* *****************************************************************************
Odeslat dotaz pres HTTP na server

@param    reqMethod - HTTP metoda dotazu (GET,POST,HEAD,...)
@param    reqURL - URL adresa pozadavku
@param    callBack - fce ktera se ma zavolat pri zmene stavu pozadavku
@param    reqData - data ktery se maji poslat pres POST dotaz
@return   vraci vzdy true (?)
***************************************************************************** */
function httpSendRequest(reqMethod, reqURL, callBack, reqData) {
  var request = new XMLHttpRequest();

  if(callBack) {
    request.onreadystatechange = function() {callBack(request);};
  }
  request.open(reqMethod, reqURL, true);
  request.setRequestHeader("Content-Type", "application/x-www-form-urlencoded; charset=UTF-8");
  request.send(reqData);

  return true;
}


/* ******************************************************************************
nacte XML objekt do pole. kazdy element XML je v indexovanem poli podle nazvu
a dlsi pole ciselny index poradi prvku v dokumentu (arr['response'][0])
podobna fce je parseXMLToObj()

@param    xml - XML objekt
@return   XML prevedene do pole
****************************************************************************** */
function parseXML(xml) {
  var arr = new Array();

  if(xml.firstChild) {
    xml = firstChild(xml);

    do {
      // pokud jsou dcerinne uzly
      if(firstChild(xml)) {
        arr[xml.nodeName] = [parseXML(xml)];
      }

      // dcerine uzly nejsou - ziskat obsah uzlu
      else {
        arr[xml.nodeName] = [xml.firstChild.nodeValue];
      }

      xml = nextSibling(xml);
    } while(xml != null); // pokracovat dokud jsou nejake dcrinne uzly
  }

  return arr;
}


/* ******************************************************************************
nacte XML objekt do objektu. Objekt ma strukturu obj.nodeName[.childNode atd]
textova hodnota je az v posledni vlastnosti objektu
podobna fce je parseXML()

@param    xml - XML objekt
@return   XML prevedene do objektu
****************************************************************************** */
function parseXMLToObj(xml) {
  var obj = new Object();
  if(xml.nodeName == '#document') { xml = firstChild(xml); }

  if(xml = firstChild(xml)) {
    do {
      // pokud jsou dcerinne uzly
      if(firstChild(xml)) {
        obj[xml.nodeName] = new parseXMLToObj(xml);
      }

      // dcerine uzly nejsou - ziskat obsah uzlu
      else {
        obj[xml.nodeName] = xml.firstChild.nodeValue;
      }

      xml = nextSibling(xml);
    } while(xml != null); // pokracovat dokud jsou nejake dcrinne uzly
  }

  return obj;
}


/* ******************************************************************************
nacte XML objekt do objektu. Na rozdil od parseXMLToObj podporuje vice uzlu se
stejnym jmenem na jedne urovni Objekt ma strukturu
obj.nodeName[x][.childNode[y] atd] textova hodnota je az v posledni vlastnosti
objektu podobna fce je parseXMLToObj()

@param    xml - XML objekt
@return   XML prevedene do objektu
****************************************************************************** */
function parseXMLToObjArray(xml) {
  var obj = new Object();
  if(xml.nodeName == '#document') { xml = firstChild(xml); }

  if(xml = firstChild(xml)) {
    do {
      // if there are some child nodes
      if(firstChild(xml)) {
        // if is not set, create new array
        if(!obj[xml.nodeName]) {
          obj[xml.nodeName] = new Array();
        }
        obj[xml.nodeName][obj[xml.nodeName].length] = new parseXMLToObjArray(xml);
      }

      // no child nodes, write value
      else {
        if(!obj[xml.nodeName]) {
          obj[xml.nodeName] = new Array();
        }
        obj[xml.nodeName][obj[xml.nodeName].length] = xml.firstChild.nodeValue;
      }

      xml = nextSibling(xml);
    } while(xml != null); // continue while there are some child nodes
  }

  return obj;
}
