/** Common Library functions **/

function Library_getInputValue(formItem, name) {
  var i;
  var ret = false;
  formItem = Library_getParentNodeByTagName(formItem, 'FORM');
  if (formItem) {
    var inputs = formItem.getElementsByTagName('INPUT');
    for (i = 0; i < inputs.length; i++) {
      if (
          (inputs[i].type != 'radio') &&
          (inputs[i].type != 'checkbox') &&
          (inputs[i].name == name)
         ) {
        ret = inputs[i].value;
        break;
      }
    }
  }

  return ret;
}

function Library_getRadioValue(formItem, name) {
  var i;
  var ret = false;
  formItem = Library_getParentNodeByTagName(formItem, 'FORM');
  if (formItem) {
    var inputs = formItem.getElementsByTagName('INPUT');
    for (i = 0; i < inputs.length; i++) {
      if (
        (inputs[i].type == 'radio') &&
        (inputs[i].checked) &&
        (inputs[i].name == name)
        ) {
        ret = inputs[i].value;
        break;
      }
    }
  }

  return ret;
}

function Library_setRadioValue(obj, value) {
  var i;
  var ret = false;
  var formItem = Library_getParentNodeByTagName(obj, 'FORM');
  var name = obj.name;
  if (formItem) {
    var inputs = formItem.getElementsByTagName('INPUT');
    for (i = 0; i < inputs.length; i++) {
      if (
        (inputs[i].type == 'radio') &&
        (inputs[i].name == name)
        ) {
          inputs[i].checked = (inputs[i].value == value);
          if (inputs[i].value == value) ret = true;
      }
    }
  }
  return ret;
}

function Library_setSelectValue(obj, value){
  if (!obj) return false;
  var index = -1;
  for (var i = 0; i < obj.options.length; i++){
    if (obj.options[i].value.toUpperCase() == value.toUpperCase()){//shoda na hodnotu
      index = i;
      break;
    }
    if ((index == -1) && (obj.options[i].innerHTML.toUpperCase() == value.toUpperCase())){ // shoda na popisek
      index = i;
    }
  }
  obj.selectedIndex = index;
  return (index != -1);
}

function Library_getFormItemValue(obj){
  var i;
  var ret = false;
  if (obj.tagName == 'INPUT'){
    switch (obj.type){
      case 'radio':
        if (!obj.name) {
            Library_debugAlert('Radio button has no name:'+obj.id);
            return null;
        } //TODO: osetrit
        return Library_getRadioValue(obj, obj.name);
      case 'checkbox':
        return obj.checked ? obj.value : null;
      case 'text':
      case 'hidden':
      default:
        return obj.value; 
    }
  } 
  if (obj.tagName == 'SELECT'){
    return obj.options[obj.selectedIndex].value;
  } 
  if (obj.tagName == 'TEXTAREA') {
    return obj.innerHTML;
  }
  Library_debugAlert('Unhandled type of object:'+obj.tagName);
  return null;
}

function Library_setValue(obj, value, onlyToEmpty){// vraci, zda-li doslo k nastaveni hodnoty
    if (!obj) return false;
    if (obj.tagName == 'INPUT'){
      switch (obj.type){
        case 'radio':
          if (!obj.name) {
            Library_debugAlert('Radio button without definition of name:'+obj.id);
            return false;
          }
          return Library_setRadioValue(obj, value);
        case 'checkbox':
          return element.checked = value ? true : false;
        case 'text':
        default:
          if (onlyToEmpty && (obj.value != '')) return false;
          obj.value = value;
          return true; 
      }
    }
    if (obj.tagName == 'SELECT'){
      if (onlyToEmpty && (obj.selectedIndex != -1) && (trim(obj.options[obj.selectedIndex].value) != '')) return false;
      return Library_setSelectValue(obj, value);
    }
    if (obj.tagName == 'TEXTAREA') {
      if (onlyToEmpty && (trim(obj.innerHTML) != '')) return false;
      obj.innerHTML = value;
      return true;
    }
    return false;
}

function Library_getFormValues(elForm, implodeUrl, filtrName, replace){
  if (!elForm) return false;
  var pars = new Object();
  var inps = elForm.elements;
  for (var i = 0; i < inps.length; i++) {
    var nam = inps[i].name;
    if (!nam || inps[i].type == 'button' || inps[i].type == 'submit' || inps[i].disabled) continue;    
    if (filtrName && nam.indexOf(filtrName) == -1) continue;
    if (replace || replace === ''){
      nam = nam.substring(0,nam.indexOf(filtrName))+replace+nam.substring(nam.indexOf(filtrName) + filtrName.length);
    }
    pars[nam] = Library_getFormItemValue(inps[i]);
  }
  if (!implodeUrl) return pars;
  else {
    var res = '';
    for (var n in pars){
      if (pars[n] !== null){
        res += '&'+n+'='+pars[n];
      }
    }
    return res;
  }
}

function Library_addClass(el, cl) {
  el.className += (el.className ? ' ' : '') + cl;
}

function Library_removeClass(el, cl) {
  var classesOld = el.className.split(' ');
  var classesNew = new Array();
  var i;
  
  for (i in classesOld) {
    if (classesOld[i] != cl) {
      classesNew.push(classesOld[i]);
    }
  }
  el.className = classesNew.join(' ');
}

function Library_hasClass(element, classes, separator){
    var sep =  separator ? separator : ' ';
    var parts = element.className.split(sep);
    if (!classes) return parts;
    for (var index in parts){
      if (parts[index] == classes) return true; 
    }
    return false;
}

function Library_getParentNodeByTagName(element, name) {
  element = element.parentNode;
  while (element && element.nodeName != name) {
    element = element.parentNode;
  }
  return element;
}

function Library_getNextSiblingByTagName(element, name, count) {
  if (!count) { count = 1; }
  do {
    element = element.nextSibling;
    if (element && element.nodeName == name) { count--; }
  } while (element && ((element.nodeName != name) || (count != 0)));
  return element;
}

function Library_getPreviousSiblingByTagName(element, name) {
  element = element.previousSibling;
  while (element && element.nodeName != name) {
    element = element.previousSibling;
  }
  return element;
}

function Library_getFirstChildByTagName(element, name) {
  element = element.firstChild;
  while (element && element.nodeName != name) {
    element = element.nextSibling;
  }
  return element;
}

function Library_getElementAttributes(element){
  var w = document.getElementById('dumpElement'+element.id);
  if (!w){
    w = document.createElement('table');
    w.setAttribute('id', 'dumpElement'+element.id);
//    element.parentNode.appendChild(w);    
    }
  w.nodeValue = '';
  var row = document.createElement('tr');
  var thD = document.createElement('th');
  var tdD = false;
  var tdC = false;
  thD.innerHTML = 'Description';
  var thC = document.createElement('th');
  thC.innerHTML = 'Contain';
  row.appendChild(thD);
  row.appendChild(thC);
  w.appendChild(row);
  for (var a in element){
    row = document.createElement('tr');
    tdD = document.createElement('td');
    tdD.innerHTML = a;
    row.appendChild(tdD);
    tdC = document.createElement('td');
    tdC.innerHTML = ''+element[a];
    row.appendChild(tdC);
    w.appendChild(row);
  }
  return w;
}

  function Library_getOffsetTop(el) {
    var offsetTop = 0;
    if (el.offsetParent) {
      offsetTop = el.offsetTop;
      el = el.offsetParent;
      while (el) {
        offsetTop += el.offsetTop;
        el = el.offsetParent;
      }
    }                                     
    return offsetTop;
  }

  function Library_getOffsetLeft(el) {
    var offsetLeft = 0;
    if (el.offsetParent) {
      offsetLeft = el.offsetLeft;
      el = el.offsetParent;
      while (el) {
        offsetLeft += el.offsetLeft;
        el = el.offsetParent;
      }
    }                                     
    return offsetLeft;
  }

  function Library_getComputedStyle(el) {
   if (window.getComputedStyle) {
     return window.getComputedStyle(el, null);
   } else {
     return el.currentStyle;
   }
  }

  function Library_isPositioned(el) {
   var position = Library_getComputedStyle(el).position;
   return (position != '') && (position != 'static');
  }

//function returns date if date is valid or false if date is invalid (czech date format)
function Library_isValidDate(string, isBirthDate) {
   var parsedDate = string.split (".");
   if (parsedDate.length != 3) return false;
   var day, month, year;
   month = (parsedDate[1]-1);
   day = parsedDate[0];
   year = parsedDate[2];

   var objDate = new Date (year,month,day);
   if (month != (objDate.getMonth())) return false;
   if (day != objDate.getDate()) return false;
   if (year != objDate.getFullYear()) return false;

   if (objDate && isBirthDate) {
     var chk = new Date();
     return (chk.getFullYear() - 100) < objDate.getFullYear();
   }

   return objDate;
}

function Library_insertAfter(newElement, targetElement) {
  var daddy = targetElement.parentNode;
  if (daddy.lastChild == targetElement) {
    daddy.appendChild(newElement);
  }
  else {
    daddy.insertBefore(newElement, targetElement.nextSibling);
  } 
}

function Library_replaceNode(new_node, old_node) {
  var daddy = old_node.parentNode;
  var next_sibling = old_node.nextSibling;
  daddy.removeChild(old_node);
  if (daddy.lastChild == old_node) {
    daddy.appendChild(new_node);
  }
  else {
  daddy.insertBefore(new_node,next_sibling);
  }
}

function Library_insertTemplateVar(string,template,temp_content) {
  return string.replace("{"+template+"}",temp_content)
}

function Library_purge(d) {
    var a = d.attributes, i, l, n;
    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            n = a[i].name;
            if (typeof d[n] === 'function') {
                d[n] = null;
            }
        }
    }
    a = d.childNodes;
    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            Library_purge(d.childNodes[i]);
        }
    }
}

function Library_getFormElementsByName(sName, sForm){
  if (!sForm) sForm = this;
  while (sForm && sForm.tagName != "FORM")sForm = sForm.parentNode; 
  var res = new Array();
  for (var i = 0; i < sForm.elements.length; i++){
    if (sForm.elements[i].name && sForm.elements[i].name == sName){
      res.push(sForm.elements[i]);
    }
  }
  return res;
}

function trim(str, chars) {
    return ltrim(rtrim(str, chars), chars);
}

function ltrim(str, chars) {
    chars = chars || "\\s";
    return str.replace(new RegExp("^[" + chars + "]+", "g"), "");
}

function rtrim(str, chars) {
  chars = chars || "\\s";
  return str.replace(new RegExp("[" + chars + "]+$", "g"), "");
}

function Library_length(ar){
  var i = 0;
  for (var k in ar){
    i++;
  } 
  return i;
}

function Library_inArray(ar, val){
  for (var k in ar){
    if (ar[k] == val) return k;
  } 
  return false;
}

function Library_join(ar, delimiter, includeZero){
  if (!delimiter) delimiter = '';
  var text = '';
  for (var i in ar){
    if (!ar[i] && (!includeZero || (ar[i] !== 0 && ar[i] !== '0' && ar[i] !== "0"))) continue;
    text += (text == '' ? '' : delimiter) + ar[i];
  }
  return text;
}

function Library_unset(ar, index){
  delete ar[index];
  return ar;
}

function Library_ReplaceHolders(value, placeHolders){
  var nVal = value;
  for (var i in placeHolders){
    var re = new RegExp("\{"+i+"\}", "g");
    nVal = nVal.replace(re, placeHolders[i]);
    re = null;
  }
  return nVal;
}

function Library_addEvent(obj, evType, fn, useCapture){
  if (obj.addEventListener){
    obj.addEventListener(evType, fn, useCapture);
    return true;
  } else if (obj.attachEvent){
    var r = obj.attachEvent("on"+evType, fn);
    return r;
  } else {
    alert("Handler could not be attached");
    return false;
  }
}

function Library_debugMessage(message, delimiter){
  if (!window.debugMessageEl){
    if (!window.debugMessageId) window.debugMessageId = 'debugDiv';
    window.debugMessageEl = document.getElementById(window.debugMessageId);
    if (!window.debugMessageEl && false) {
      window.debugMessageEl = document.createElement('div');
      window.debugMessageEl.innerHTML = '';
      window.debugMessageEl.id = window.debugMessageId;
      var b = document.getElementsByTagName('body');
      b[0].appendChild(window.debugMessageEl);
    }
  }
  if (!delimiter) delimiter = "<br />";
  if (window.debugMessageEl) window.debugMessageEl.innerHTML += delimiter + message;
}

function Library_debugAlert(message, type){
  if(!type) type = "error";
  var consoleDefinition = typeof(console) != "undefined";
  if(type=="error") {
    if (!consoleDefinition) {
      if (window.debug) alert('console:'+message);
    } else {
      console.error(message);
    }
  }
  else if(type=="warning" && consoleDefinition) {
    console.warn(message);
  }
  else if(type=="info" && consoleDefinition) {
    console.info(message);
  }
  else if(type=="debug" && consoleDefinition) {
    console.debug(message);
  }
}

/*******************************************************************
 * F U N K C E  pro manipulaci s casti linku H A S H (target)      *
 *******************************************************************
 * zakazane parametry:
 * @ oddelovac parametru
 * | oddelovac prvku neidexovaneho pole
 * . v nazvu atributu adresovani objektu
 * momentalne neumi ukladat hodnotu 0, tento parametr preskakuje
 */
function UrlHash(){
    this.get = function(index){
      // pokud se pouziva zamek hashe a neni primo nastavovana location.hash
      if (this.alternativeHashSource instanceof Array){
        if (index) return this.alternativeHashSource[index] ? this.alternativeHashSource[index] : false;
        else return this.alternativeHashSource;
      }
      var a = new Array();
      var str = location.hash.toString();
      if (str && str.substring(0,1) == '#') str = str.substring(1);
      if (!str || str == this.defaultEmptyValue) return index ? false : a;
      if (str == this.lastHash) a = this.lastHashAry;
      else Library_getObjectByPath(str, this.urlByArrays, a, this.itemSeparator, this.arraySeparator, this.objectPathSeparator);
      return index ? false/*polozka nenalezena*/ : a;
    };
    this.set = function(a){
      if (!(a instanceof Array)) return false;
      this.isModifiedHash = true;
      if (this.blockSettingHash){
        this.alternativeHashSource = a;
        return true;
      }
      var h = Library_getPathByObject('', a, this.objectPathSeparator, this.itemSeparator, this.arraySeparator);
      this.isModifiedHash = false; // zmena vypropagovana->dulezite pri zamceni uprav
      if (h == this.lastHash) return false;
      if (!h) h = this.defaultEmptyValue;
      if (this.saveHistoryChangesToHash){
        // funkcionalitu pro IE je potreba realizovat skryty IFrame
        location.hash = h;
      } else {
        location.replace('#'+h); //problem s chovani v IFrame
      }
      this.lastHash = h;
      this.lastHashAry = a;
      this.setStorage(h);
      return true;
    };

    this.setStorage = function(h, skipSave/*preskok ajaxoveho ulozeni*/){
      //zajistuje ukladani hodnot do formularu a tim propagaci do historie
      if (!this.itemsStoringHash){
        this.itemsStoringHash = new Array();
        if (this.hashSourceName){
          var stor = null;
          var forms = document.getElementsByTagName('form');
          for (var iForm = 0; iForm < forms.length; iForm++){
            stor = Library_getFormElementsByName(this.hashSourceName, forms[iForm]);
            if (stor[0]) stor = stor[0];
            else {
              stor = document.createElement('input');
              stor.type = 'hidden';
              stor.name = this.hashSourceName;
              forms[iForm].appendChild(stor);
            }
            this.itemsStoringHash.push(stor);
          }
          if (this.itemsStoringHash[0] && this.ajaxActualization) {
            this.itemsStoringHash[0].actualizeHash = this.ajaxActualization;
          }
        }
      }
      // mechanizmus pro ulozeni Hash pro odesilani pres formulare
      for (var iItem in this.itemsStoringHash){
        if (this.itemsStoringHash[iItem]) this.itemsStoringHash[iItem].value = h;
      }
      if (!skipSave && this.itemsStoringHash[0] && this.itemsStoringHash[0].actualizeHash) this.itemsStoringHash[0].actualizeHash(h); // AJAXOVA REGISTRACE
      forms = null; stor = null;
      return true;
    };

    this.modify = function(key, val, plus){ // vraci, zda doslo ke zmene hash
      // Pozor: pri definovani indexu, jez jsou imlicitnimi metodami tridy array, v IE6 nedojde k jejich vraceni, napr: index => sort
      // vraci false pokud nedojde ke zmene Hash
      if (plus){
        return this.add(key, val, plus == 2);
      } else {
        return this.remove(key, val);
      }
    };
    this.add = function(key, val, replace, source){
      // vraci, zda doslo ke zmene hash
      // Pozor: pri definovani indexu, jez jsou imlicitnimi metodami tridy array, v IE6 nedojde k jejich vraceni, napr: index => sort
      // vraci false pokud nedojde ke zmene Hash
      var a = source ? source : this.get();
      if (Library_setIndexByPath(val, a, key, this.objectPathSeparator, replace)){
        return this.set(a);
      }
      return false;
    };
    this.remove = function(key, val, source){
      // pri specifikovani val hleda val v neindexovanem poli
      var a = source ? source : this.get();
      if (Library_removeIndexByPath(val, a, key, this.objectPathSeparator)){
        return this.set(a);
      }
      return false;
    };
    this.saveToHistory = function(val){
      val = !!val;
      this.saveHistoryChangesToHash = val;
    };
    this.lock = function(lockKey){ // umoznuje vicestupnove zamykani
      if (this.blockSettingHash) return false;
      this.alternativeHashSource = this.get();
      this.blockSettingHash = 'lock'+lockKey;
      this.isModifiedHash = false;
      return true;
    };
    this.unlock = function(lockKey){
      if (this.blockSettingHash != 'lock'+lockKey) return false;
      this.blockSettingHash = false;
      if (this.isModifiedHash){
        this.set(this.alternativeHashSource);
      }
      this.alternativeHashSource = false;
      return true;
    };
    this.ajaxActualizationHandler = function(hash, frame){
      // prida se k prvnimu formularovamu elementu
      // na zaklade upravy hashe provede aktualizaci historie
      if (!window.Library_ajaxRequest) return false;
      var url = '';
      if (this.ajaxUrl){
        url = this.ajaxUrl;
      } else {
        url = location.href;
        if (url.indexOf('?') != -1) url = url.substring(0, url.indexOf('?'));
      }
      var separator = (url.indexOf('?') == -1) ? '?' : '&';
      url  = url + separator + 'action=eAjaxSetTarget' +
        (frame ? '&frame='+frame : '')+
        '&'+this.hashSource+'=' +hash;
      Library_ajaxRequest('actualizeHash', url, Library_ajaxHashActualizationResultHandler, this, 0, 1);
      return true;
    };
    this.onloadPrepare = function(){
      window.urlHash.lastHash = location.hash;
      window.urlHash.lastHashAry = window.urlHash.get();
      window.urlHash.setCheckIntervalDelay(window.urlHash.checkIntervalDelay);
      if (!location.hash) return false;
      window.urlHash.setStorage(location.hash.substring(1)); // pri zadavani do linku musi dojit k automatizovanemu zpracovani
      return true;
    };
    this.modifyByHash = function(){
      if (this.changingByHash || this.blockSettingHash || !this.isChanged()) return false;
      this.changingByHash = true;
      if (this.onModifyByHashHandler){
         var hashAry = this.get();
         var appendedAry = Library_arrayMissing(this.lastHashAry, hashAry);
         var removedAry = Library_arrayMissing(hashAry, this.lastHashAry);

         if (Library_lengthNoEmpty(removedAry) + Library_lengthNoEmpty(appendedAry) > 0){
            this.onModifyByHashHandler(appendedAry, removedAry);
            this.lastHash = location.hash;
            this.lastHashAry = hashAry;
         }
      }
      this.changingByHash = false;
      return true;
    };
    this.isChanged = function(){
      var h = location.hash.toString();
      return (this.isEmpty(this.lastHash) != this.isEmpty(h)) || (this.lastHash && this.lastHash != h);
    };
    this.isEmpty = function(val){
      return (!val) || (val == '#') || (val == this.defaultEmptyValue) || (val == '#'+this.defaultEmptyValue);
    }
    this.setOnModifyByHashHandler = function(handle){
      this.onModifyByHashHandler = handle;
    };
    this.setCheckIntervalDelay = function(secs){// nulovym casem se vypne
      //if (this.checkIntervalDelay != secs && this.checkInterval) return false;
      this.checkIntervalDelay = secs;
      if (this.checkInterval) window.clearInterval(this.checkInterval);
      if (this.checkIntervalDelay) this.checkInterval = window.setInterval('window.urlHash.modifyByHash();', this.checkIntervalDelay);
      return true;
    };
/*local function for array operations*/
  function Library_getIndexByPath(ary, path, del){
    if (!del) del = '.';
    if (path.indexOf(del) >= 0){
      var key = path.substring(0, path.indexOf(del));
      if (Library_isObject(ary[key])) return Library_getIndexByPath(ary[key], path.substring(path.indexOf(del)+del.length), del);
      else return null;
    } else {
      if (Library_isDefined(ary[path])) return ary[path];
      else return null;
    }
  }

/*otazka resit vlozeni hodnoty null, "" a false jako remove ? */
  function Library_setIndexByPath(value, ary, path, del, repl){
    if (!del) del = '.';
    var change = false;
    //if (!ary) ary = new Object();
    if (path.indexOf(del) >= 0){
      var key = path.substring(0, path.indexOf(del));
      if (!Library_isObject(ary[key])) {
        ary[key] = isNaN(ary*1) ? new Object() : new Array();
      }
      change = Library_setIndexByPath(value, ary[key], path.substring(path.indexOf(del)+del.length), del, repl);
    } else {
      if (Library_isEmpty(path)) return false;
      if (Library_isEmpty(ary[path])){
        ary[path] = value;
        change = true;
      } else if(ary[path] != value){
        if (repl){
          ary[path] = value;
          change = true;          
        } else {//append
          var subcase = false;
          if (Library_isEmpty(value)) return false; //souvisi s uvodni otazkou
          if (!Library_isObject(value)) value = [value];
          if (!Library_isObject(ary[path])) ary[path] = [ary[path]];
          var saArr = Library_hasSubArray(ary[path]);
          var saVal = Library_hasSubArray(value);
          if (saArr != saVal){
            Library_debugAlert('Unknown way to merge unindexed and indexed array');
          } else if(saArr/* && saVal*/){/* pokud se merguji hluboka pole */
            for (subcase in value){
              if (Library_setIndexByPath(value[subcase], ary[path], subcase, del, repl)) change = true;
            }
          } else {
            for (subcase in value){
              if (Library_inArray(ary[path], value[subcase]) === false){
                if (Library_isEmpty(value[subcase])) continue;
                ary[path].push(value[subcase]);
                change = true;
              }
            }
          }
        }
      }
    }
    return change;
  }

  function Library_removeIndexByPath(value, ary, path, del){
    /*snazi se v poli hledat cestu,
      je-li zadana hodnota, hledaji ve vysledku, jinak odstrani vysledek */
    if (!del) del = '.';
    if (Library_isEmpty(path)) return false;
    var change = false;
    var key = path.toString();
    if (key.indexOf(del) >= 0){
      key = key.substring(0, path.indexOf(del));
      if (Library_isObject(ary[key])) {
        change = Library_removeIndexByPath(ary[key], path.substring(path.indexOf(del)+del.length), del);
      }
    } else {
      if (ary[key]){
        if (value){//hleda pouze konkretni hodnotu
          if (Library_isObject(ary[key])){
            var index = Library_inArray(ary[key], value);
            if (index !== false){
              Library_unset(ary[key], index);
              change = true;
            }
          } else if(ary[key] == value){
            ary[key] = null;
            change = true;
          }
        } else {
          ary[key] = null;
          change = true;
        }
      }
    }
    if (Library_isEmpty(ary[key]) || (Library_isObject(ary[key]) && Library_lengthNoEmpty(ary[key])==0)){
      Library_unset(ary, key); // odstraneni posledniho
    }
    return change;
  }

  function Library_getObjectByPath(path, likeAry, ary, delPar, delSplit, del){
    if (!ary) ary = new Object();
    if (!del) del = '.';
    if (!delPar) delPar = '@';
    if (!delSplit) delSplit = '|';

    if (!path) return null;
    var parts = false;
    var subparts = false;

    if (path.indexOf(delPar))
      parts = path.split(delPar);
    else
      parts = [path];

    for (var i in parts){
      if (parts[i].indexOf('=')>=0)
        subparts = parts[i].split('=', 2);
      else
        subparts = [path, true];
      var val = subparts[1];
      //TODO: problem s urceni, zda jde o retezec
      if (val && val.indexOf && val.indexOf(delSplit) >= 0){
        subparts[1] = val.split(delSplit);
      }
      if (likeAry && !(subparts[1] instanceof Array)) subparts[1] = [subparts[1]];
      Library_setIndexByPath(subparts[1], ary, subparts[0], del);
    }
    return ary;
  }

  function Library_getPathByObject(path, ary, del, delPar, delSplit){
    if (!del) del = '.';
    if (!delPar) delPar = '@';
    if (!delSplit) delSplit = '|';
    if (!path) path = '';
    var val = '';
    //if (!ary) ary = new Object();
    if (!Library_isObject(ary) || Library_lengthNoEmpty(ary) == 0) return val;
    if (!Library_hasSubArray(ary)){// pro neindexovane pole neobsahujici dalsi pole
      return path+"="+Library_join(ary, delSplit, true);
    }
    for (var a in ary){
      if (!Library_isDefined(ary[a])) continue;
      if (Library_isObject(ary[a])){
        val += (val ? delPar : '')+Library_getPathByObject(path+(path ? del : '')+a, ary[a], del, delPar, delSplit);
      } else {
        val += (val ? delPar : '')+(path ? path+del : '')+a+(ary[a] !== true ? ("="+ary[a]) : '');
      }
    }
    return val;
  }

  function Library_arrayMissing(ary1, ary2){ // vraci co chybi ary1 vuci ary2
    var missPar = [];
    if (ary1 == ary2) return missPar;
    if (!Library_isObject(ary1)){
      if (!Library_isObject(ary2)) return [ary2];
      else {
        missPar = ary2;
        var index = Library_inArray(missPar, ary1);
        if (index !== false) Library_unset(missPar, index);
        return missPar;
      }
    }
    if (Library_isObject(ary2)){
      for (var i in ary2){
        if ((i in ary1) && (ary1[i] == ary2[i])) continue;
        if (isNaN(i*1) || Library_isObject(ary2[i])){ // indexovane pole
          var ni = i in ary1 ? Library_arrayMissing(ary1[i], ary2[i]) : ary2[i];
          if (Library_lengthNoEmpty(ni)){
            missPar[i] = ni;
          }
        } else { // neindexovane pole
          if (!Library_isObject(ary2[i])){
            if (Library_inArray(ary1, ary2[i]) === false){
              missPar.push(ary2[i]);
            }
          }
        }
      }
      return missPar;
    } else return [ary2];
  }

  function Library_hasSubArray(ary){ //TODO: co s polem type reference: a[55555] = 1; ??
    if (Library_isObject(ary)){// pro neindexovane pole neobsahujici dalsi pole
      for (var a in ary){
        if (Library_isObject(ary[a]) || isNaN(a*1)){
          return true;
        }
      }
    } else {
      Library_debugAlert('This value cannot be used instead of Object in hasSubArray');
    }
    return false;
  }

  function Library_lengthNoEmpty(o){ /* pocita neprazdne prvky pole*/
    var len = 0;
    if (!Library_isObject(o)) return Library_isEmpty(o) ? 0 : 1;
    for (var i in o){
      len += Library_lengthNoEmpty(o[i]) ? 1 : 0;
    }
    return len;
  }

  function Library_isObject(val){
    return (val instanceof Object && !(val instanceof String));
  }

  function Library_isDefined(val){ // povoluje jakoukoli definovanou hodnotu
    return (typeof(val) != "undefined" && val !== null);
  }

  function Library_isFunction(val){
    return (typeof(val) == "function");
  }

  function Library_isEmpty(val){ // povazuje string 0 i cislo 0 za spravny obsah
    return (!val && val !== '0' && val !== "0" && val !== 0);
  }

  this.onModifyByHashHandler = false;
  this.checkIntervalDelay = 1000; //interval pro zjistovani zmen v Hash
  this.defaultEmptyValue = "USED";
  this.isModifiedHash = false;
  this.changingByHash = false;
  this.saveHistoryChangesToHash = false;
  this.blockSettingHash = false;
  this.hashSource = "__hashSource";
  this.hashSourceName = false; // polozky formulare pro ukladani hashe
  this.alternativeHashSource = false; //pro ukladani stavu hashe v prubehu zamceni
  this.itemsStoringHash = false; // kolekce elementu pro ukladani hashe
  this.lastHash = false;
  this.lastHashAry = false;

  this.itemSeparator = "@";
  this.arraySeparator = "|";
  this.objectPathSeparator = ".";
  this.urlByArrays = true;

  if (window.Library_prepareUrlHash) Library_prepareUrlHash(this);
  //automatic for add action onload
  Library_addEvent(window, 'load', this.onloadPrepare, false);
}

window.urlHash = new UrlHash();
/*******************************
 *        datove konverze      *
 *******************************/

function Library_parseHumanDate(value, inFormat, forceValue){
  /* return res.month 1-12, res.day 1-31*/
  var res = {'year': false, 'month': false, 'day': false, 'format': false};
  var d_arr = null;
  if (!inFormat){
    if (value.indexOf(".") != -1) {
      d_arr = value.split(".");
      res.day = d_arr[0] && !isNaN(d_arr[0]*1) ? d_arr[0] : false;
      res.month = d_arr[1] && !isNaN(d_arr[1]*1) ? d_arr[1] : false;
      res.year = d_arr[2] && !isNaN(d_arr[2]*1) ? d_arr[2] : false;
      res.format =  'd.m.Y';
      res.separator = '.';
    } else if(value.indexOf("-") != -1) {
      d_arr = value.split("-");
      res.year = d_arr[0] && !isNaN(d_arr[0]*1) ? d_arr[0] : false;
      res.month = d_arr[1] && !isNaN(d_arr[1]*1) ? d_arr[1] : false;
      res.day = d_arr[2] && !isNaN(d_arr[2]*1) ? d_arr[2] : false;
      res.format =  'Y-m-d';
      res.separator = '-';    
    } else if(value.indexOf("/") != -1) {
      d_arr = value.split("/");
      res.month = d_arr[0] && !isNaN(d_arr[0]*1) ? d_arr[0] : false;
      res.day = d_arr[1] && !isNaN(d_arr[1]*1) ? d_arr[1] : false;
      res.year = d_arr[2] && !isNaN(d_arr[2]*1) ? d_arr[2] : false;
      res.format =  'm/d/Y';
      res.separator = '/';    
    } else if(value.indexOf("_") != -1) {
      d_arr = value.split("_");
      res.year = d_arr[0] && !isNaN(d_arr[0]*1) ? d_arr[0] : false;
      res.month = d_arr[1] && !isNaN(d_arr[1]*1) ? d_arr[1] : false;
      res.day = d_arr[2] && !isNaN(d_arr[2]*1) ? d_arr[2] : false;
      res.format =  'Y_m_d';      
      res.separator = '_';
    }
  } else {
    res.format = inFormat;
    var con = new Array();
    res.separator = false;
    for (var iLet = 0; iLet < inFormat.length; iLet++){ //parsovani formatu
      switch (inFormat.charAt(iLet)){
        case 'y':
        case 'Y':
          con.push('year');
          break;
        case 'm':  
        case 'M':  
          con.push('month');
          break;        
        case 'd':  
        case 'D':  
          con.push('day');
          break;        
        case '-':  
        case '/':  
        case '.':  
        case '_':  
          res.separator = inFormat.charAt(iLet);
          break;        
        default:
          break;        
      }
    }
    if (con && res.separator){ //parsovani hodnoty
      d_arr = value.split(res.separator);
      for (var i = 0; i < d_arr.length; i++){
        if (!con[i] || isNaN(d_arr[i]*1)) continue;
        res[con[i]] = d_arr[i]*1;
      }
    }
  }

  if (forceValue){
    if (forceValue.year) res.year = forceValue.year;
    if (forceValue.month || forceValue.month === 0) res.month = forceValue.month+1;/*vstup 0..11*/
    if (forceValue.day) res.day = forceValue.day;
  }
  
  if (inFormat) format = inFormat;
  if (res.year<100){// prevod year -> full Year
    if (res.year>=70) res.year += 1900;
    else res.year += 2000;
  }
  return res;
}
/* pozor na  problemy typu:
     31.5.2009 -> 1.6.2009
     10.2.2009 -> 30.4.2009  
*/
function Library_getHumanToDate(value, params){
  if (!params) params = new Array();
  var dateVal = params.defaultDate ? params.defaultDate : new Date();
  var dateAry = Library_parseHumanDate(value, params.format, params.forceValue);
  var day = dateAry.day;
  var month = dateAry.month - 1;
  var year = dateAry.year;
  var checkDate = null;

  if ((year !== false && !isNaN(year * 1) && (year > 0))
    && (month !== false && !isNaN(month * 1) && (month>=0))
    && (day !== false && !isNaN(day * 1) && (day >=0))){ // existuje-li datum zadane uplne
    
    checkDate = new Date(year, month-1, day);
    if (year == checkDate.getFullYear() && month-1 == checkDate.getMonth() && day == checkDate.getDate()){
      dateVal = Library_setDateLimits(year, month , day , dateVal, params.minimalDate, params.maximumlDate);
      return dateVal;      
    }    
  } else if ((month !== false && !isNaN(month * 1) && (month>=0))
    && (day !== false && !isNaN(day * 1) && (day >=0))){ // existuje-li datum bez specifikace roku
    checkDate = new Date(dateVal.getFullYear(), month-1, day);
    if (month-1 == checkDate.getMonth() && day == checkDate.getDate()){
      dateVal = Library_setDateLimits(dateVal.getFullYear(), month , day , dateVal, params.minimalDate, params.maximumlDate);
      return dateVal;  
    }
  }

  checkDate = new Date(dateVal);
//  checkDate.setDate(1); // viz problemy v zakladu -> vyreseno dosazenim, 31.3.09 -> false.4.09 => 31.3.09, ale nyni 31.4. = 1.5.09
  
  var useYear = false;
  var useMonth = false;
  var useDay = false;
  var checksDate = null;

  if (year !== false && !isNaN(year * 1) && (year > 0)){
    checkDate.setFullYear(year);
    useYear = true;
  }
  if (month !== false && !isNaN(month * 1) && (month>=0)){
    checksDate = new Date(checkDate);
    checksDate.setMonth(month);
    if (month*1 == checksDate.getMonth()){ // proti 13.mesici etc.
      checkDate = checksDate;
      useMonth = true;
    }
  }
  if (day !== false && !isNaN(day * 1) && (day >=0)){
    checksDate = new Date(checkDate);
    checksDate.setDate(day);
    if (day*1 == checksDate.getDate()){ // proti 30.2. etc.
      checkDate = checksDate;
      useDay = true;
    }
  }    
    
  dateVal = Library_setDateLimits(useYear ? year : false, useMonth ? month : false, useDay ? day : false, dateVal, params.minimalDate, params.maximumlDate);
  return dateVal;
}

function Library_setDateLimits(y,m,d, defaultDate, minDate, maxDate){
  var checkDate = new Date(defaultDate);
  var validSet = ['d','m','y'];
  if (minDate && checkDate < minDate) return minDate;
  if (maxDate && checkDate > maxDate) return maxDate;
  
  for (var iSet = validSet.length; iSet>0; iSet--){
    var resDate = null;
    if (iSet == validSet.length && y !== false && m !== false && d !== false){
      resDate = new Date(y,m,d);
    } else {
      resDate = new Date(defaultDate);
      for (var iDate = 0; iDate < iSet; iDate++){
        if (validSet[iDate] == 'y'){
          if (y !== false)
            resDate.setFullYear(y);
        }
        if (validSet[iDate] == 'm'){
          if (m !== false)
            resDate.setMonth(m);
        }
        if (validSet[iDate] == 'd'){
          if (d !== false)
            resDate.setDate(d);
        }
      }
    }
    for (var i = iSet; i < validSet.length; i++){ // vybalancovani do rozsahu
      if (validSet[i] == 'd'){
        if (minDate && resDate < minDate) resDate.setDate(minDate.getDate());
        else if (maxDate && resDate > maxDate) resDate.setDate(maxDate.getDate());
      }
      if (validSet[i] == 'm'){
        if (minDate && resDate < minDate){ 
          resDate.setMonth(minDate.getMonth());
          if (resDate < minDate) resDate.setMonth(minDate.getMonth()+1);
        } else if (maxDate && resDate > maxDate){
          resDate.setMonth(maxDate.getMonth());
          if (resDate > maxDate) resDate.setMonth(maxDate.getMonth()-1);
        }
      }
      if (validSet[i] == 'y'){
        if (minDate && resDate < minDate){ 
          resDate.setMonth(minDate.getFullYear());
          if (resDate < minDate) resDate.setFullYear(minDate.getFullYear()+1);
        } else if (maxDate && resDate > maxDate){
          resDate.setMonth(maxDate.getFullYear());
          if (resDate > maxDate) resDate.setFullYear(maxDate.getFullYear()-1);
        }
      }
    }
    if ((!minDate || resDate >= minDate) && (!maxDate || resDate <= maxDate)) return resDate;
  }
  return false;
}

function Library_checkHumanDate(value, params){ // pokud je v poradku, vrati true, jinak vraci navrhovanou opravu
  if (!params) params = new Array();
  var dateVal = Library_getHumanToDate(value, params); // vcetne aplikace ohraniceni
  var dateAry = Library_parseHumanDate(value, params.format, params.forceValue);

  var day = dateAry.day;
  var month = dateAry.month - 1;
  var year = dateAry.year;

  if (year === false || isNaN(year * 1) || (year < 0) || year != dateVal.getFullYear()){
    return Library_getDateToHuman(dateVal, dateAry.format);
  }
  if (month === false || isNaN(month * 1) || (month < 0) || month != dateVal.getMonth()){
    return Library_getDateToHuman(dateVal, dateAry.format);
  }
  if (day === false || isNaN(day * 1) || (day < 0) || day != dateVal.getDate()){
    return Library_getDateToHuman(dateVal, dateAry.format);
  }    
  return false;
}

function Library_getDateToHuman(dat, format){
  if (!format) format = 'd.m.Y';
  if (!(dat instanceof Date)) return '';
  var res = '';
  var oper = '';
  var last = false;
  for (var i = 0; i < format.length; i++){
    oper = format.substring(i,i+1);
    if (oper == last) continue;
    switch (oper){
      //cas
      case 'h': res += dat.getHours() % 12; break;// 0-12
      case 'H': res += dat.getHours(); break;// 0-23
      case 'i': res += dat.getMinutes(); break;
      case 's': res += dat.getSeconds(); break;
      case 'a': res += dat.getHours()<12 ? 'am' : 'pm'; break;
      case 'A': res += dat.getHours()<12 ? 'AM' : 'PM'; break;
      //datum
      case 'Y': res += dat.getFullYear(); break;
      case 'y': res += dat.getYear(); break;
      case 'm': res += (dat.getMonth() < 9 ? '0' : '')+(dat.getMonth()+1); break;
      case 'j': res += dat.getMonth()+1; break;
      case 'd': res += (dat.getDate() < 10 ? '0' : '')+dat.getDate(); break;
      case 'n': res += dat.getDay(); break;
      case 'w': res += dat.getDay(); break;
      default: res += oper;
    }
    last = oper;
  }
  return res;
}

function Library_compareDates(part, date1, date2, supposedVal, isGreater){
  var today = new Date(date1);
  var secDate = new Date(date2);
  if (!part) part = '';
  switch (part.toUpperCase()){
    case 'Y':
      Library_resetTime(secDate, 'Y');
      Library_resetTime(today, 'Y');
      if (supposedVal || supposedVal !== 0) today.setFullYear(supposedVal);
    break;
    case 'M':
       Library_resetTime(secDate, 'M');
       Library_resetTime(today, 'M');
       if (supposedVal || supposedVal !== 0) today.setMonth(supposedVal);
    break;
    case 'D':
    case '':
       Library_resetTime(secDate, 'D');
       Library_resetTime(today, 'D');
       if (supposedVal || supposedVal !== 0) today.setDate(supposedVal);
    break;
    case 'Y-M-D':
    case 'D.M.Y':
       var separ = false;
       if (part.toUpperCase() == 'Y-M-D') separ = '-';
       if (part.toUpperCase() == 'D.M.Y') separ = '.';
       Library_resetTime(secDate, 'D');
       Library_resetTime(today, 'D');
       if (supposedVal) {
          supposedVal = supposedVal.split(separ);
          if ((supposedVal.length != 3) || isNaN(1*supposedVal[0]) || isNaN(1*supposedVal[1]) || isNaN(1*supposedVal[2])){
            Library_debugAlert('bad type for new Enter of date for compare');
            return false;
          } else {
            today.setFullYear(supposedVal[0]);
            today.setMonth(supposedVal[1]);
            today.setDate(supposedVal[2]);
          }
       }
    break;
    default:
      Library_debugAlert('unrecognized part of date for compare:'+part);
      return false;
    break;
  }
  return isGreater ? today > secDate : today < secDate;
}

function Library_resetTime(date, part){
  date.setHours(0, 0, 0, 0);
  if (!part || part == "D") return date;
  date.setDate(1);
  if (part == "M") return date;
  date.setMonth(1);
  return date;
}

/********************/
function Library_getStyle(x,styleProp)
{
	if (x.currentStyle)
		var y = x.currentStyle[styleProp];
	else if (window.getComputedStyle)
		var y = document.defaultView.getComputedStyle(x,null).getPropertyValue(styleProp);
	return y;
}
/** Ajax Library functions **/

var LibraryVar_ajaxRequests = new Array();
var LibraryVar_ajaxRequestsObjects = new Array();
var LibraryVar_ajaxRequestsPostData = new Array();

function Library_ajaxRequest(type, url, handler, element, delay, post) {
  var httpRequest = false;
  post = post ? 1 : 0;
  var postData = null;

  if (post) {
    var urlDataStart = url.indexOf('?');
    if (urlDataStart > -1) {
      postData = url.substring(urlDataStart + 1, url.length);
      url = url.substring(0,urlDataStart);
    }
  }

  if (window.XMLHttpRequest) {
    httpRequest = new XMLHttpRequest();
    if (httpRequest.overrideMimeType) {
      httpRequest.overrideMimeType('text/xml');
    }
  } else if (window.ActiveXObject) { 
    try {
      httpRequest = new ActiveXObject("Msxml2.XMLHTTP");
    } catch (e) {
      try {
        httpRequest = new ActiveXObject("Microsoft.XMLHTTP");
      } catch (e) {
        alert('Problem with generating ajax request');
      }
    }
  }
  if (httpRequest) {
    var ident = Math.random();
    LibraryVar_ajaxRequests[type] = ident;
    LibraryVar_ajaxRequestsObjects[type] = httpRequest;
    LibraryVar_ajaxRequestsPostData[ident] = postData;
    httpRequest.onreadystatechange = function () { handler(httpRequest, type, ident, element); };
    httpRequest.open(post ? 'POST' : 'GET', url, true);
    if (!delay) {
      Library_ajaxRequestSend(httpRequest, post, postData);
    } else {
      window.setTimeout("Library_ajaxRequestDelayed('"+ type +"','"+ ident +"',"+ post +");", delay);
    }
    return ident;
  }
  return false;
}

function Library_ajaxRequestDelayed(type, ident, post) {
  if (LibraryVar_ajaxRequests[type] == ident) {
    Library_ajaxRequestSend(LibraryVar_ajaxRequestsObjects[type], post, LibraryVar_ajaxRequestsPostData[ident]);
  }
}

function Library_ajaxRequestSend(httpRequest, post, postData) {
  httpRequest.setRequestHeader("X-Requested-With", "XMLHttpRequest");/* usable for debug infos */
  if (post) {
    httpRequest.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
    httpRequest.setRequestHeader("Content-length", postData.length);
    httpRequest.setRequestHeader("Connection", "close");
  }
  httpRequest.send(postData);
}

function Library_ajaxUrlEncode(val) {
  var ret = val.toString();
  return encodeURIComponent(ret);
}

function Library_ajaxHashActualizationResultHandler(httpRequest, type, ident, element) {
  if (httpRequest.readyState == 4 && LibraryVar_ajaxRequests[type] == ident) {
    if (httpRequest.status == 200) {
      var errors = httpRequest.responseXML.getElementsByTagName('error');
      if (errors.length) {
        for (var i = 0; i < errors.length; i++){
          alert(errors[i].nodeValue);
        }
      }
      
      LibraryVar_ajaxRequests[type] = null;
      LibraryVar_ajaxRequestsObjects[type] = null;  
    }
  }
}


