// JavaScript Document - pracovní verze pro sociálního poradce

// Seznam aktuálních varování
var warnings = {};

// konstanta konec posuzování OZP od
var ozpDate = new Date(2012,1 - 1,1);

/** Náhrada nestandardní funkce innerText
*/
function myInnerText(elem) {
  var retText = "";
  $A(elem.childNodes).each(function(n) {
    if (n.nodeName == '#text') {
      retText += n.nodeValue
    } else if (n.nodeName == 'BR') {
      retText += ' '
    } else {
      retText += myInnerText(n)
    }
  });
  return retText
}

Element.addMethods({ 'myInnerText': myInnerText });

// Přidá metody pro všechny HTML elementy
Element.addMethods({
  'myInnerText': myInnerText,

  /** Přepíše obsah elementu
  * Něco uloží do .value
  * Něco zobrazí. Zobrazí v podstatě totéž, ale možná formátované.
  * Zavolá událost 'onchange', pokud se hodnota suktečně změnila.
  * Nevolá onchange při prvním naplnění (.value==undefined)
  * @param elem - element, kterého je to metoda
  * @param toSave - hodnota, která se má uložit
  * @param [fmt] - zjednodušený formátovací řetězec. Př: "%d&nbsp;Kč". %d se nahradí hodnotou. Pokud je zadáno, formátuje se tím hodnota pro zobrazení.
  * @param [toShow] - řetězec, který se má zobrazit. Pokud je zadáno, přebije fmt.
  */
  updateValue: function(elem, toSave, fmt, toShow) {
    // Implicitní text - zobrazí se, pokud se nepodaří vytvořit hodnota toShow
    // Jinak se zobrazuje v title
    if (elem.defaultText == undefined) {
      elem.defaultText = (elem.title == undefined) ? '' : elem.title;
    };

    // Hodnota, která se uloží. Obvykle stejná, jako se zobrazí, ale ne nutně.
    if (toShow == undefined && toSave != undefined && toSave != unValue) {
      toShow = fmt ? formatUnits(toSave, fmt) : toSave;
    }
    var changed = (elem.value != undefined && elem.value != toSave);
    elem.value = toSave;

    // Hodnota, která se zobrazí
    // Nápověda v Title
    if (toShow == undefined || toShow == unValue) {
      toShow = (elem.defaultText == "") ? unValue : elem.defaultText;
      elem.title = txtCannotCount
    } else {
      elem.title = elem.defaultText;
    };
    elem.update(toShow);

    // Vyvolat událost, pokud se hodnota změnila
    if (changed) { elem.fire('sp:onchange') };
  },

  // Nastaví element se souhrnem podmínek za dávku
  updateCondition: function(elem, fitts, elemZadost) {
    
    elem.updateValue(fitts, undefined, fitts ? okStr : noStr);
    // Pokud je zadaný odkaz na žádost, vloží se také pod kladný text doporučení podat žádost.
    var myOkStrTxt = elemZadost ? okStrLink.replace('###', elemZadost) : okStrTxt; 
    $(elem.id + '_txt').update(fitts ? myOkStrTxt : noStrTxt);
    // Pokud jsou podmínky splněné, pokusí se odkrýt detaily o žádosti.
    if (fitts) {
      var myZadostDetailId = elem.id.replace(/dav_([^_]*)_.*/,'dav_$1_zadost_detail');
      // alert(myZadostDetailId);
      if($(myZadostDetailId) != undefined){
        $(myZadostDetailId).show();
      }
    }
  }

})

// Přidá metody pro pole formuláře
Element.addMethods(['INPUT', 'SELECT'], {
  // Vynulovat pole formuláře
  clearInput: function(fld) {
      switch (fld.type){
          case 'text':
            fld.value = '';
            break;
          case 'select-one':
            fld.options[0].selected = true;
            break;
          case 'select-multiple':
             for(var i=0, j=fld.options.length; i<j; ++i) {
               fld.options[i].selected = false
             }
            break;
          case 'radio':
            fld.checked = false;
            break;
          case 'checkbox':
            fld.checked = false;
            break;
          default: throw "Unkwnown type of field in form: " + fld.type;
       } // switch
  } // clearInput
}); 
  
    // Zobrazí/Skryje elementy jedné sekce
    function toggleSection(sectionId) {
      // alert('toggleSection called');
      // alert($(sectionId + '_skryt').id);
      $(sectionId + '_skryt').toggle();
      $(sectionId + '_odkryt').toggle();
      $(sectionId + '_detail').toggle();
      // alert('toggleSection finished');
    }
    
    // Zobrazí jen zajímavé dávky
    function showSelected(){
      // Zmapuje stav checkboxů - optimalizace
       mapZs();
       var cntShown=0;
       var cntFamily=false;
       var cntStrange=0;
       trc.trace('showSelected - start');
       $('dav_seznam').childElements().each(function(dav){
          trc.trace('showSelected - ' + dav.id, 5);
          if (dav.showMe != undefined) {
            // cntShown += setVisibility(dav,dav.showMe()) ? 1 : 0;
            var davInfo = setVisibility(dav)
            cntShown += davInfo.visible ? 1 : 0;
            cntFamily += davInfo.family ? 1 : 0;
            cntStrange += davInfo.strange ? 1 : 0;
          }
      })
      
        trc.trace('showSelected - Default');
        // setVisibility($('dav_Default'),cntShown == 0);
        if (cntShown <= 0) {
          $('dav_Default').show();
        } else {
          $('dav_Default').hide();
        }
        if (cntFamily > 0 || $('rodina').isValid()) {
          $('rodina').show();
          $('obr').hide();
        } else {
          $('rodina').hide();
          $('obr').show();
        };
        trc.trace('showSelected - finish');
        // Upozornění na vevyplněnou rodinu
        if (cntFamily > 0 && !$('rodina').isValid() && !($('davky_filtr_').value == 'show_all')/*$('show_all').checked*/) {
          $('label_dav_missing').show();
        } else {
          $('label_dav_missing').hide();
        };
        // Upozornění na divné dávky
        if (cntStrange > 0 ) {
          var txtAlert = 'Varování.\nNezačali jste vyplňovat formulář pro někoho jiného než dosud?\n';
          txtAlert += cntStrange == 1 ? 
            'V seznamu je dávka se splněnými podmínkami, která neodpovídá zvoleným životním situacím.' :
            'V seznamu jsou dávky se splněnými podmínkami, které neodpovídají zvoleným životním situacím.';
          txtAlert += '\n\n';
          txtAlert += 'Pokud chcete začít práci znovu od začátku, doporučujeme Vám VYČISTIT FORMULÁŘ.';
          alert(txtAlert);
        }
        
        // Setřídí dávky
        // Předtím si musí zapamatovat hodnoty polí formuláře.
        // Jinak se přesouváním elementů ztratí.
        // Po setřídění hodnoty zase obnoví
        trc.trace('sortElementsBy - start');
        // Uvolní a zapamatuje nepřístupná pole (jinak by se nezahrnula do .serialize)
        var myDisabled = [];
        $('SocPr').getElements().each(function(fld){
          if (fld.disabled) {
            myDisabled.push(fld);
            fld.enable();
          }
        })
        // Zapamatuje si hodnoty
        var formData = $H($('SocPr').serialize(getHash = true));
        // alert('DEBUG:formData saved: '  + formData.toJSON());
        if($('davky_filtr_').value == 'show_all') {
          $('dav_seznam').sortElementsBy(function(e){return e.order});
        } else {
          $('dav_seznam').sortElementsBy(function(e){return e.currPriority ? -1*e.currPriority() : 0});
        };
        // alert('DEBUG:formData to load: ' + formData.toJSON());
        $('SocPr').populate(formData);
        // Znepřístupní dočasně uvolněná pole
        myDisabled.invoke('disable');
        trc.trace('sortElementsBy - end');
   
     // }
      // prepocitatDavky();
       // Ukáže varování, pokud se něco podstatně změnilo
       showWarningGlobal(); 
    }
    
    // Zmapuje životní situace. Nastaví u každé virtuální hodnotu (virtValue).
    // virtValue == true, pokud je situace zaškrtnutá nebo vyplývá z rodiny
    function mapZs() {
      trc.trace('mapZs - start');
      $('zs_seznam').select('input').each(
        function(inp){
          if(!(inp.virtValue = inp.getValue())) {
            if (inp.seemsTo != undefined) {
              inp.virtValue = inp.seemsTo();
            }
          }
        }
      );
      trc.trace('mapZs - finish');
    }
    
    // Nastaví viditelnost jedné dávky
    function setVisibility(davkaTR, nastaveni) {
      trc.trace('setVisibility - start',7);
      // var davkaTR = 'dav_' + davkaZkr;
      davkaZkr = davkaTR.id;
      var expSet = checkSwitch(davkaZkr);
      var visi = true; // má být vidět?
      var fami = false; // byla by vidět, kdyby byla vyplněná rodina
      var strange = false; // divná situace. Podmínky jsou splněné, ale se vlastně nemá ukazovat.
      var recalculated = false; // už jsme nechali dávku přepočítat?
      // Jsou splněné podmínky i po přepočítání dávky?
      function conditionsFit() {
                var davkaConditionsFit =  ($(davkaZkr + '_p_vse') != undefined && $(davkaZkr + '_p_vse').value);
                if (davkaConditionsFit) { // Podmínky splněny
                  // přepočítat
                  if (davkaTR.recalculate != undefined) {
                    davkaTR.recalculate();
                    // podívat se, jestli jsou podmínky stále splněné
                    davkaConditionsFit =  ($(davkaZkr + '_p_vse') != undefined && $(davkaZkr + '_p_vse').value);
                   };
                   recalculated = true;
                 }
               return davkaConditionsFit;
              }
      trc.trace('setVisibility - checkValidity',7);
      if (!checkValidity(davkaZkr)) { // Není platná pro datum - neukáže se nikdy
        visi = false
      } else { // je platná pro datum
        if(($('davky_filtr_').value == 'show_all')) {
          visi = true;
        } else if(($('davky_filtr_').value == 'show_pinnedUp')){
          visi = (expSet == 1)
        } else if(($('davky_filtr_').value == 'show_excluded')){
          visi = (expSet == 2)
        } else if($('davky_filtr_').value == 'show_recommended') {
          if (expSet == 2){ // Dávka explicitně vypnutá
            visi = false;
          } else if (expSet == 1){ // Dávka explicitně zapnutá
            visi = true;
          } else if (conditionsFit()) {// podmínky splněny (i po přepočtu dávky)
             visi = true;
             if (davkaTR.showMe != undefined) {
                strange = !davkaTR.showMe(); // Divná situace. Podmínky jsou splněné, ale se vlastně nemá ukazovat.
             }
          }  else if (nastaveni != undefined) { // Podmínka předaná volajícím kódem
            visi = nastaveni
          } else if (davkaTR.showMe != undefined) { // existuje metoda dávky, která řekne, kdy se má ukázat
            visi = davkaTR.showMe();
          } else { // Není řečeno nic - vidět pořád
            visi = true
          }
        } // show_recommended
        
        // pokud je vidět (a ještě jsem ji nepřepočítal), přepočítat dávku
        if (visi && !recalculated) {
          if (davkaTR.recalculate != undefined) {davkaTR.recalculate()}
        }       
      }; // je platná pro datum
      
      if ($(davkaTR).requiresFamily) {
        if (visi) { // Je třeba ukázat panel domácnosti
          fami = true;
          if (!$('rodina').isValid() && !(
            ($('davky_filtr_').value == 'show_all') ||
            ($('davky_filtr_').value == 'show_recommended')
          )) { // Domácnost není vyplněná (a neukazuje se vše) -> zakrýt
            visi = false;
          }
        }
      }
      
      trc.trace('setVisibility - setting visibility',7);
      if ($(davkaTR) != undefined) {
        if (visi && !$(davkaTR).visible()) {
          $(davkaTR).show();
        } else if(!visi && $(davkaTR).visible()){
          $(davkaTR).hide();
        }
      }
      return {'visible':visi,'family':fami, 'strange':strange};
    }
    
    // Zjistí explicitní nastavení viditelnosti pro jednu dávku 
    function checkSwitch(davkaZkr){
      // var myForm = $('SocPr');
      var davId = davkaZkr;
      //var myCheck = myForm['davka_' + davkaZkr];
      var retVal = undefined;
      if ($(davId + '_pinUp') != undefined && $(davId + '_pinUp').checked) {
        retVal = 1
      }
      if ($(davId + '_turnDown') != undefined && $(davId + '_turnDown').checked) {
        retVal = 2
      }
      return retVal;
    }
    
    // Ošetří klepnutí na checkbox 'vybrat'
    function pinUp(chBox) {
      var mySuf = '_pinUp';
      var hisSuf = '_turnDown';
      davId = chBox.id.replace(mySuf,'');
      // Zruší zaškrtnutí u druhého checkboxu
      if (chBox.checked) {
        $(davId + hisSuf).checked = false;
      }
    }
    
    // Ošetří klepnutí na checkbox 'vyřadit'
    function turnDown(chBox) {
      var mySuf = '_turnDown';
      var hisSuf = '_pinUp';
      davId = chBox.id.replace(mySuf,'');
      // Zruší zaškrtnutí u druhého checkboxu
      if (chBox.checked) {
        $(davId + hisSuf).checked = false;
        // Pokud nemá být vidět vše, schová se
        if (!($('davky_filtr_').value == 'show_all')) {
          $(davId).hide();
        }
      }      
    }

    // Ověří platnost dávky vůči datu
    function checkValidity(davkaZkr){
		
		var dateRef = splitDate($('referencni_datum').value);
		var dateFrom = $(davkaZkr).validFrom == undefined ? -Infinity : splitDate($(davkaZkr).validFrom);
		var dateTo = $(davkaZkr).validTo == undefined ? Infinity : splitDate($(davkaZkr).validTo);
		var validity = (dateFrom <= dateRef && dateRef <= dateTo);
		
		return validity;
    }
    
    // Jsou všechny zadané životní situace zaškrtnuté?
    function checkAll() {
      var myForm = $('SocPr');
      var retVal = true;
      for(i=0;i<arguments.length;i++){
        var myCheck = myForm[arguments[i]];
        // if (!checkOne(myCheck)) {
        if (myCheck == undefined || !myCheck.virtValue) {
          retVal=false;
          break;
        }
      };
      return retVal
    }

    // Je aspoň jedna ze zadaných životních situací zaškrtnutá?
    function checkAny() {
      var myForm = $('SocPr');
      var retVal = false;
      for(var i=0;i<arguments.length;i++){
        var myCheck = myForm[arguments[i]];
        // if (checkOne(myCheck)) {
        if (myCheck != undefined && myCheck.virtValue) {
          retVal=true;
          break;
        }
      };
      return retVal
    }
    
    // Je daná životní situace zaškrtnutá?
    function checkOne(zs) {
        if ($(zs).getValue() == 'on') {
          return true;
        } else if ($(zs).seemsTo == undefined) {
          return false;
        } else {
          return $(zs).seemsTo();
        }
    }

    // Jsou všechny podmínky dávky zaškrtnuté?
    function checkAllConditions(davkaZkr) {
      var retVal = true;
      var currVal;
      var condBaseName = "dav_" + davkaZkr + '_p';
      var i = 0;
      do {
        currVal = checkCondition(condBaseName + ++i);
        if (currVal != undefined) {retVal = retVal && currVal};
        if (!retVal) break;
      } while (currVal != undefined)
      
      return retVal
    }

    // Je aspoň jedna podmínka dávky zaškrtnutá?
    function checkAnyCondition(davkaZkr) {
      var retVal = false;
      var currVal;
      var condBaseName = 'dav_' + davkaZkr + '_p';
      var i = 0;
      do {
        currVal = checkCondition(condBaseName + ++i);
        // condElem = $(myForm[condBaseName + ++i]);
        if (currVal != undefined) {retVal = retVal || currVal};
        if (retVal) break;
      } while (currVal != undefined)
      
      return retVal
    }

    // Je daná podmínka dávky zaškrtnutá?
    function checkCondition(condName) {
      var myForm = $('SocPr');
      var condElem;
      var retVal = undefined;
      condElem = $(myForm[condName]);
      if (condElem != undefined) {retVal = condElem.getValue() == 'on'};
      return retVal
    }

    // Přidá řádek na člena do domácnosti
    function addMember(clenTyp) {
      var poradi = ($('rodina_seznam').childElements().size())/2+1;
      // alert(poradi);
      clenId = 'clen' + poradi;
      novyClen = defaultMember.replace(/clenX/g,clenId);
      // alert(novyClen);
      $('rodina_seznam').insert(novyClen);
      
      /** Při každé změně člena
      */
      $(clenId).refresh = function() {
        this.setView();
        // $('rodina').refresh();
        $('rodina').setValid(false);
       };
       
      /** Zakryje / odkryje ovládací prvky podle kontextu
      */      
      $(clenId).setView = function() {
        $(this.id + '_smazat').show();
        $(this.id + '_ozp_check').disabled = false;
        $(this.id + '_dluh_check').disabled = false;
        //$(this.id + '_jmeno').disabled = false;
        
        // Nezaopatřenost
        var vek = +$(this.id + '_vek').value;
        if (vek < 15) {
          $(this.id + '_neza').checked = true;
          $(this.id + '_neza').disabled = true;
          $(this.id + '_stud').checked = false;
        } else if (vek >= 26) {
          $(this.id + '_neza').checked = false;
          $(this.id + '_neza').disabled = true;  
          $(this.id + '_stud').checked = false;          
        } else {
          $(this.id + '_neza').disabled = false;
        }
        // Viditelnost
        // Neviditelné prvky se vždy vyčistí
        if (vek < 26) {
          $(this.id).select('.spJenDite').each(function(line){line.show()});
          if (vek < 15) {
            $(this.id + '_stud_text').hide();
          }
        } else {
          $(this.id).select('.spJenDite').each(function(line){line.hide()});
          $(this.id).select('input.spJenDite', 'select.spJenDite').each(function(inp){inp.clearInput()}); //alert('DEBUG:About to clear input: ' + inp.id);
        }
        if ($(this.id + '_ozp_check').checked) {
          $(this.id).select('.spJenOZP').each(function(line){line.show()});
          if ($(this.id + '_ozp') != undefined) {$(this.id + '_ozp').show()};
        } else {
          $(this.id).select('.spJenOZP').each(function(line){line.hide()});
          if ($(this.id + '_ozp') != undefined) {
            $(this.id + '_ozp').hide()
            $(this.id + '_ozp').select('input', 'select').each(function(inp){inp.clearInput()});
          };
        }
     $('rodina').scan();
     if ($('rodina').memberList.size() >= $('rodina').actualLines()) {
        addMember();
      };
      } // clen.setView
    }
     
        
    // Spočítá existenční minimum
    // .. provizorní varianta - bez posuzování stavu zaměstnanosti
    function getEM(datum, vyjimka, zm) {
      return vyjimka ? zm : existencniMinimum.search({platnost:datum});
    }

    // Spočítá normativní nákaldy na bydleni
    function getNNByd(datum, velikostMesta, pocetVRodine, typBytu) {
    
      return tabNnByd.search({
        typBytu: typBytu,
        pocetObyv: velikostMesta,
        pocetOsob: pocetVRodine
      });
    }
// Přiřadí nové vlastnosti elementu 'zs_seznam'
function initSituations(situationElem) {
  situationElem.refresh = function() {
    if ($('rodina').isValid()) {
      $(this).select('label').each(function(lab) {
        var inp = $(lab.htmlFor);
        if ((inp.seemsTo == undefined) || !inp.seemsTo()) {
          lab.removeClassName('spSeemsTo');
        } else {
          lab.addClassName('spSeemsTo');
        }
      })
    } else {
      $(this).select('label').each(function(lab) {
        var inp = $(lab.htmlFor);
        lab.removeClassName('spSeemsTo');
      })    
    }
  };
}

// Přiřadí nové vlastnosti elementu 'dav_seznam'
function initDav(davElem) {
  davElem.sortElementsBy = function(fceName) {
    var myArr = this.childElements();
    myArr = myArr.sortBy(fceName);
    var that = this;
    myArr.each(function(e){that.insert(e);});
  }
}


// Inicializace rodiny
function initFamily(familyElem) {
    // Zjistí, kolik řádků je vidět v panelu domácnosti.
    // Vyplněných i prázdných
    familyElem.actualLines = function() {
      return $('rodina_seznam').childElements().size()/2;
    }

    // Různá počítadla o rodině.
    var counters=[
      'pocetCelkem', // Celkový počet osob v domácnosti
      'pocetDeti', // Počet nezaopatřených dětí
      'pocetDospelych', // Počet členů domácnosti, kteří nejsou nezaopatřenými dětmi
      'pocetDetiPP', // Počet dětí v pěstounské péči
      'pocetDetiPPNez', // Počet dětí v pěstounské péči, které jsou nezaopatřené nebo nezletilé
      'pocetDetiMalych', // Počet dětí do jednoho roku
      'pocetOZP', // Počet osob se zdravotním postižením
      'pocetOZPDeti', // Počet nezaopatřených dětí se zdravotním postižením
      'pocetDluh',     // Počet osob, které dluží na výživném (Příznak je normálně skrytý.)
      'pocetPostizenych', // Počet osob dlouhodobě zdravotně postižených - podle zákona č. 117/1995 Sb., o státní sociální podpoře, § 30b odstavec 2)
      'pocetPostizenychDeti', // Počet nezopatřených dětí dlouhodobě zdravotně postižených - podle zákona č. 117/1995 Sb., o státní sociální podpoře, § 30b odstavec 2)
      'pocetOZPVyhod', // Už se nepoužívá - počet osob s přiznanými výhodami ZTP
      'pocetOZPTezce', // Počet těžce zdravotně postižených osob. Závislé na cizí páči nebo dlouhodobě zdravotně postižené na stupni aspoň 3.
      'pocetZavislych', // Počet osob závislých na cizí péči - § 8-9 zákona 108/2006 Sb., o sociálních službách
      'pocetZavislychDosp', // Počet osob závislých na cizí péči, které nejsou nezaopatřenými dětmi - § 8-9 zákona 108/2006 Sb., o sociálních službách
      'pocetZavislychDeti', // Počet nezaopatřených dětí závislých na cizí péči - § 8-9 zákona 108/2006 Sb., o sociálních službách
      'pocetNevidomych', // Počet nevidomých
      'zivotniMinimum', // Životní minimum všech členů domácnosti
      'existencniMinimum', // Existenční minimum všech členů domácnosti
      'zivobyti' // Přibližná částka živobytí všech členů domácnosti. U každého člena se pohybuje mezi existenčním a životním minimem. Ve skutečnosti se počítá strašně složitě. Zde velmi zjednodušené.
    ]
    // counters.each(function(cnt){this['onchange_' + cnt] = new CustomEvent();},familyElem);
    // familyElem.onchange_rodina = new CustomEvent();
    // familyElem.onclear_rodina = new CustomEvent();

  // Přiřadí nové vlastnosti elementu 'rodina'
  
    familyElem._valid = false;
 
    /**
    * Ověří, jestli je rodina správně vyplněná.
    * Před něčím varuje (rozpor se životními situacemi).
    * Něco nepovolí (prázdná rodina, rodina bez dospělého).   
    * Vrací true/false - jestli kontrola prošla.         
    */
    familyElem._validate = function() {
      // alert('familyElem.validate. pocetCelkem:' + this.pocetCelkem + '; pocetDospelych:' + this.pocetDospelych);

      var familyOK = true;
      if (this.pocetCelkem == undefined) {
        alert('V domácnosti musí být aspoň jeden člen. Musí mít vyplněný alespoň věk.');
        return false;
      }
      if (this.pocetDospelych < 1) {
        alert('V domácnosti musí být aspoň jeden člen, který není nezaopatřené dítě.');
        return false;
      }

      // Kontrola konzistence rodiny s životními situacemi
      var bugNumber = 0;
      var bugList = '';
      $('zs_seznam').select('input').each(
        function(inp) {
          if (inp.seemsTo != undefined) {
            if (inp.getValue() && !inp.seemsTo()) {
              bugNumber++;
              bugList += "\n - " + $(inp.id + '_label').myInnerText();
              if (inp.expl != undefined) { // Vysvětlení
                bugList += " (" + $(inp.id).expl + ')';
              }
            };
          }
        }
      );

        if (bugNumber > 0) {
          familyOK = !confirm('Varování: Údaje o domácnosti neodpovídají označeným životním situacím:' + stripTags(bugList) +'\n Chcete je opravit?');
      }

      // ToDo
      // alert('Ještě nefunguje');
      // familyOK = confirm('Něco je blbě. Chcete přesto pokračovat?');
      return familyOK;
    }

    
    /**
    * Nastaví platnost rodiny.
    * Ošetří vzhled, vyvolá příslušné události.  
    * @param valid - má se nastavit na platnou/neplatnou?      
    */
    familyElem.setValid = function(valid){
      if (valid != this._valid) {
        this._valid = valid;
        $('family_ok').checked = valid;
        if (valid) {
          $('family_submit').disabled = true;
          $('family_submit').addClassName('spSubmitSed');
          this.fire('sp:onfinish')
        } else {
          $('family_submit').disabled = false;
          $('family_submit').removeClassName('spSubmitSed');
          this.fire('sp:oninvalidate')
        }
      }
    }
    
    
    /**
    * Prohlásí rodinu za nevyplněnou
    * Vymaže některé vlastnosti;
    */
    familyElem._invalidate = function() {
      
      this.scan();
        for (i=0, j=this.memberList.size(); i<j; ++i){
          currClen = this.memberList[i]
          clenId = currClen.id;
          
          // Životní minimum
           currClen.zm = undefined;
          $(clenId + '_zm').updateValue(currClen.zm,FMT_KC0_TAB);
          
          // Existenční minimum
          currClen.em = undefined;
          $(clenId + '_em').updateValue(currClen.em,FMT_KC0_TAB);
          
          // Částka živobytí - přibližně
          currClen.zivobyti = undefined;

      }
      
      this.zivotniMinimum = undefined;
      $('rodina_zm').updateValue(this.zivotniMinimum,FMT_KC0_TAB);
      this.existencniMinimum = undefined;
      $('rodina_em').updateValue(this.existencniMinimum,FMT_KC0_TAB);
      this.zivobyti = undefined;
      counters.each(function(cnt){this[cnt] = undefined;},this);

      // Vyvolá událost - rodina se změnila 
        this.fire('sp:onchange_rodina');

      // Vyvolá události u změněných počítadel
      for (var i=0, j=counters.length; i<j;++i) {
        this.fire('sp:onchange_' + counters[i]);
      }

      // Schová dávky, které vyžadují údaje o rodině
      $('zs_seznam').refresh();
      showSelected();

    }
    
    /**
    * Zahodí pracovní objekty o rodině a znovu je vytvoří podle dat ve formuláři
    * Pracovní objekty jsou:
    * members - objekt (hash) indexovaný přes id člena
    * memberList - pole seřazené podle věku sestupně
    */
    familyElem.scan = function() {
      this.members = {};
      this.memberList = [];
      var myMembers = $('rodina_seznam').select('tr.spZaklad');
      for (i=0, j=myMembers.size(); i<j; ++i){
        clenId = myMembers[i].id;
        if ($(clenId + '_vek').value != "") {
          var myM = myMembers[i];
          myM.vek = $(clenId + '_vek').value;
          this.members[clenId] = myM;
          this.memberList.push(myM);
        }
      }
      this.memberList.sortBy(function(m){-1 * m.vek});
    }
  
    // Obálka nad delší akcí - ukáže progress screen
    familyElem.refresh_deffered = function() {
      // Zakryje stránku
      // alert('DEBUG: about to showWait');
      showWait();
      var that = this;
      setTimeout(function() {
        try {
          // alert('DEBUG: about to refresh');
          if (that.isValid()) {
              that.refresh_action();
          } else {
            that._invalidate();
          }
          // alert('DEBUG: refreshed');
        } finally {
          // Ukáže stránku
          // alert('DEBUG: about to hideWait');
          hideWait();
        }
      }, 40);
    }
    
    // Přepočítá údaje o rodině - hlavně životní minimum
    familyElem.refresh = function() {
    
    
      // showWait();
      var clenId = '';
      var oldFamily = Object.clone(this);
      // Vynuluje počítadla
      counters.each(function(cnt) { this[cnt] = 0; }, this);

      // Zmapuje vyplněné členy
      this.scan();

      // zobrazení/skrytí OZP podle refernčního data
      var tstRes = splitDate($('referencni_datum').value);
      if (tstRes.getTime() < ozpDate.getTime()) {
        for (i = 0, j = this.memberList.size(); i < j; ++i) {
          currClen = this.memberList[i]
          clenId = currClen.id;
          $(clenId + '_ozp_radek').style.display = 'block';
        }
      } else {
        for (i = 0, j = this.memberList.size(); i < j; ++i) {
          currClen = this.memberList[i]
          clenId = currClen.id;
          $(clenId + '_ozp_radek').style.display = 'none';
        }
      };

      // Pokud není rodina označená jako platná, volá se metoda, která zneplatní také její vlastnosti.
      if (!this._valid) {
        this._invalidate();
        return false;
      }

      trc.trace('rodina.refresh - start');

      // První průchod - celkové počty
      // var myMembers = $('rodina_seznam').select('tr.spZaklad');
      for (i = 0, j = this.memberList.size(); i < j; ++i) {
        currClen = this.memberList[i]
        clenId = currClen.id;
        // currClen.setView();                
        // Počty
        currClen.pocet = ++this.pocetCelkem;
        $(clenId + '_pocet').value = currClen.pocet;

        currClen.neza = $(clenId + '_neza').checked;
        if (currClen.neza) {
          currClen.pocet_v_kategorii = ++this.pocetDeti;
        } else {
          currClen.pocet_v_kategorii = ++this.pocetDospelych;
        };
        $(clenId + '_pocet_v_kategorii').value = currClen.pocet_v_kategorii;

        currClen.pest = $(clenId + '_pest').checked;
        if (currClen.pest) {
          this.pocetDetiPP++;
          if (currClen.vek < 18 || currClen.neza) {
            this.pocetDetiPPNez++;
          }
        }
        if ($(clenId + '_ozp_check').checked) {
          this.pocetOZP++;
          if(currClen.neza) {
            this.pocetOZPDeti++;
          }
        }

        currClen.dluh = $(clenId + '_dluh_check').getValue();
        if (currClen.dluh) { this.pocetDluh++ };


        // ozp_stup podle refernčního data - > ruší se ozp
        var tstRes = splitDate($('referencni_datum').value);
        if (tstRes.getTime() < ozpDate.getTime()) {
          currClen.ozp_stup = $(clenId + '_ozp_stup').getValue();
        } else {
          // nastavení ozp_stup jako zav_stup
          var ozp_value = $(clenId + '_zav_stup').getValue();
          if (ozp_value.substring(0, 1) != 'x' && ozp_value > 3){ozp_value = '3';} // maximální  možné ozp_stup
          currClen.ozp_stup = ozp_value;
          $(clenId + '_ozp_stup').setValue(ozp_value);
        };

        if (currClen.ozp_stup.substring(0, 1) != 'x') {
          this.pocetPostizenych++;
          if(currClen.neza) {
            this.pocetPostizenychDeti++;
          }        }

        currClen.zav_stup = $(clenId + '_zav_stup').getValue();
        if (currClen.zav_stup.substring(0, 1) != 'x') {
          this.pocetZavislych++;
          if (currClen.neza) {
            this.pocetZavislychDeti++;
          } else {
            this.pocetZavislychDosp++;
          }
        }
          
/*
        currClen.ozp_vyhod = $(clenId + '_ozp_vyhod').getValue();
        if (currClen.ozp_vyhod.substring(0, 1) != 'x') {
          this.pocetOZPVyhod++;
        }
*/
        if (currClen.ozp_stup == 3 || currClen.zav_stup >= 3/*|| currClen.ozp_vyhod == 3*/) {
          this.pocetOZPTezce++;
        }

        currClen.nevi = $(clenId + '_nevi').checked;
        if (currClen.nevi) {
          this.pocetNevidomych++;
        }

        if (currClen.vek < 1) {
          this.pocetDetiMalych++;
        }
      }
      // Druhý průchod - životní/existenční minimum, 
      /*for (i=0, j=myMembers.size(); i<j; ++i){
      clenId = myMembers[i].id;
      */
      for (i = 0, j = this.memberList.size(); i < j; ++i) {
        currClen = this.memberList[i]
        clenId = currClen.id;

        // Životní minimum
        currClen.zm = zivotniMinimum.search({
          platnost: splitDate($('referencni_datum').value),
          pocet: this.pocetCelkem,
          vek: $(clenId + '_vek').value,
          poradi: $(clenId + '_pocet_v_kategorii').value,
          neza: $(clenId + '_neza').checked
        });
        $(clenId + '_zm').updateValue(currClen.zm, FMT_KC0_TAB);
        this.zivotniMinimum += currClen.zm;

        // Existenční minimum
        currClen.em = getEM($('rodina').refDate(), $(clenId + '_neza').checked, currClen.zm);
        $(clenId + '_em').updateValue(currClen.em, FMT_KC0_TAB);
        this.existencniMinimum += currClen.em;

        // Částka živobytí - přibližně
        currClen.zivobyti = (currClen.neza) ? currClen.zm : currClen.em;
        if (!currClen.dluh) {
          currClen.zivobyti += 0.5 * (currClen.zm - currClen.em);
        };
        this.zivobyti += currClen.zivobyti;

      }

      if (oldFamily.pocetCelkem != this.pocetCelkem) {
        $('rodina_pocet').update(this.pocetCelkem);
        //this.onchange_pocetCelkem.fire()
      }
      if (oldFamily.pocetDeti != this.pocetDeti) {
        $('rodina_pocet_deti').update(this.pocetDeti);
        //this.onchange_pocetDeti.fire();
      }
      if (oldFamily.zivotniMinimum != this.zivotniMinimum) {
        $('rodina_zm').updateValue(this.zivotniMinimum, FMT_KC0_TAB);
        //this.onchange_zivotniMinimum.fire();
      }
      if (oldFamily.existencniMinimum != this.existencniMinimum) {
        $('rodina_em').updateValue(this.existencniMinimum, FMT_KC0_TAB);
        //this.onchange_zivotniMinimum.fire();
      }
      // Pokud není rodina vyplněná, nastaví všechna počítadla na undefined
      if (this.pocetCelkem <= 0) counters.each(function(cnt) { this[cnt] = undefined; }, this);

      // Vyvolá událost - rodina se změnila 
      if (oldFamily.pocetCelkem != this.pocetCelkem || this.pocetCelkem > 0) {
        // this.onchange_rodina.fire();
        this.fire('sp:onchange_rodina');
      }
      // Vyvolá událost - rodina se vyprázdnila 
      if (oldFamily.pocetCelkem > 0 && this.pocetCelkem <= 0) {
        // this.onclear_rodina.fire();
        this.fire('sp:onclear_rodina');
      }
      // Vyvolá události u změněných počítadel
      for (var i = 0, j = counters.length; i < j; ++i) {
        if (oldFamily[counters[i]] != this[counters[i]]) {
          // this['onchange_' + counters[i]].fire();
          this.fire('sp:onchange_' + counters[i]);
        }
      }

      // Pokud není rodina vyplněná správně, zase se potvrzení zruší.
      if (!this._validate()) {
        this.setValid(false);
        return false;
      }

      // Nechá přepočítat dávky
      $('zs_seznam').refresh();
      showSelected();
      // hideWait();

      trc.trace('rodina.refresh - finished');
      return true;
    }  // refresh
    
    // Ošetření událostí - zrušení a nastavení platnosti rodiny
    Event.observe(familyElem,'sp:oninvalidate', familyElem._invalidate); // Původně tam bylo refresh, ale nevím, jestli to není omyl. JS 10.2.09
      // Event.observe(familyElem,'sp:oninvalidate', familyElem.refresh); 
    Event.observe(familyElem,'sp:onfinish', familyElem.refresh);

    /** Vydá true, jen pokud je rodina naplněná
    */
    familyElem.isValid = function() {
      // return (this.pocetCelkem != undefined && this.pocetCelkem > 0) 
      return this._valid;
    }

    /** Vydá hodnotu, jen pokud je rodina naplněná
    */
    familyElem.ifValid = function(result) {
      if (this.isValid()) {
        return result
      } else {
        return unValue;
      }
    }
 
     // Vrátí Date z data zadaného v políčku 'referencni_datum'
    familyElem.refDate = function() {
      return splitDate($('referencni_datum').value);
    }

    // Nastaví datum na dnes
    familyElem.resetDate = function() {
      var d = new Date();
      $('referencni_datum').value = (d.getDate() + "." + (d.getMonth() + 1) + "." + d.getFullYear());
      $('rodina').refresh();
    } //resetDate

  // Vyčistí rodinu a nastaví X prázdných řádků (provizorní řešení)
  // var actualMembers = $('rodina_seznam').childElements().size()/2;
  for (var i=familyElem.actualLines();i<defaultMembers;i++) {addMember()}
      
  } // initFamily

    // Určí limit pro hodnotu a obecnou hash tabulku.
    // Předpokládá, že klíče tabulky jsou HORNÍ limity pro hodnoty (...do 5 let)
    // Vrátí limit (nejbližší vyšší) příslušný pro zadanou hodnotu
    function getLimitUp(value, tab) {
      var best = Infinity;
      for (limit in tab) {
        if ((+limit > +value) && (+limit < +best)) best = limit
      }
      return best
    }

    // Vydá hodnotu z obecné n-rozměrné hash tabulky organizované podle HORNÍCH limitů.
    // Předpokládá, že klíče tabulky jsou dolní limity pro hodnoty (...od 5 let)
    // Hodnoty klíčů se berou od 1. argumentu funkce
    function getTableValueUp(tab) {
      var myTab = tab;
      for (var i=1, j=arguments.length; i<j;++i) {
        var myKey = arguments[i];
        var myLimit = getLimitUp(myKey, myTab);
        if (myLimit == undefined) {return undefined};
        myTab = myTab[myLimit];
        if (myTab == undefined) {return undefined};
      }
      return myTab;
    }

    // Určí limit pro hodnotu a obecnou hash tabulku.
    // Předpokládá, že klíče tabulky jsou DOLNÍ limity pro hodnoty (...od 5 let)
    // Vrátí limit (nejbližší nižší) příslušný pro zadanou hodnotu
    function getLimitDw(value, tab) {
      var best = -Infinity;
      for (limit in tab) {
        if ((+limit <= +value) && (+limit > +best)) best = limit
      }
      return best
    }

    // Vydá hodnotu z obecné n-rozměrné hash tabulky organizované podle DOLNÍCH limitů.
    // Předpokládá, že klíče tabulky jsou dolní limity pro hodnoty (...od 5 let)
    // Hodnoty klíčů se berou od 1. argumentu funkce
    function getTableValueDw(tab) {
      var myTab = tab;
      for (var i=1, j=arguments.length; i<j;++i) {
        var myKey = arguments[i];
        var myLimit = getLimitDw(myKey, myTab);
        if (myLimit == undefined) {return undefined};
        myTab = myTab[myLimit];
        if (myTab == undefined) {return undefined};
      }
      return myTab;
    }

    // určí věkovou skupinu pro výpočet životního minima
    function vekovaSkupina(vek, neza) {
      var vS = getLimitUp(vek, zm[2008]);
      /*for (limit in zm) {
        if ((+limit > +vek) && (+limit < +vS)) vS = limit
      }*/
      // if ((+vS == 26) && (!neza)) vS = 'dospely';
      if ((+vS >= 26) && (!neza)) vS = 'dospely';
      if (+vS == Infinity) vS = 'dospely';
      return vS
    }
    // Vyčistí záznam člena rodiny, přepočítá rodinu
    function clearMember(row) {
      $('rodina').setValid(false);    
      resetMember(row);
    }
    
    // Vyčistí záznam člena rodiny, nevolá přepočítání rodimy
    function resetMember(row){
      $(row.id + '_vek').clearInput();$(row.id).vek = undefined;

      // Vyčistí všechna pole formuláře
      $(row.id).select('input', 'select').each(function(inp){inp.clearInput()});
      $(row.id + '_ozp').select('input', 'select').each(function(inp){inp.clearInput()});
      // Zakryje se vše, co se týká jen dětí nebo OZP + mazací prvek
      $(row.id + '_smazat').hide();
      $(row.id).select('.spJenDite').each(function(line){line.hide()});
      $(row.id).select('.spJenOZP').each(function(line){line.hide()});
      $(row.id + '_ozp').hide();
      // Znepřístupní, co je vidět - kromě věku a jména
      $(row.id + '_jmeno').enable();
      $(row.id + '_ozp_check').disable();
      $(row.id + '_dluh_check').disable();
      $(row.id + '_neza').disable();
      $(row.id + '_vek').enable();
        
      $(row.id + '_zm').updateValue(unValue);$(row.id).zm = undefined;
      $(row.id + '_em').updateValue(unValue);$(row.id).em = undefined;
      $(row.id + '_ozp_check').checked = false;$(row.id).ozp_check = undefined;
      $(row.id + '_ozp').hide();   
    }
      

    // Přepočítá proměnné hodnoty v dávkách
    // Už se nepoužívá. Přepočítání dávky jsem zabudoval do setVisibility
    function prepocitatDavky_deffered (){
      trc.trace('prepocitatDavky - start');
      var davky = $('dav_seznam').childElements();
       for(var i=0, j=davky.length; i<j; ++i){
         if (davky[i].visible()) {
           if (davky[i].recalculate != undefined) {davky[i].recalculate()}
         }
       }
       // Ukáže varování, pokud se něco podstatně změnilo
       showWarningGlobal();
       trc.trace('prepocitatDavky - finish');
    }

    
    // Rozloží textové datum na části
    function splitDate(strDate) {
      var re = /\b\d{1,2}[\.\/-]\s*\d{1,2}[\.\/-]\s*\d{4}\b/;
      if (! re.test(strDate)) {return undefined};
      
      var myArr = strDate.split(/[\.\/-]/);
      day = parseInt(myArr[0], 10);
      mo = parseInt(myArr[1], 10);
      yr = parseInt(myArr[2], 10);
      var myDate = new Date(yr, mo-1, day);
      
      if (myDate.getDate() != day){return undefined};
      if (myDate.getMonth() + 1 != mo){return undefined};
      if (myDate.getFullYear() != yr){return undefined};

      return myDate;
    }

    // Složí textové datum z částí
    function joinDate(objDate) 
    {
      return objDate.getDate() + ". " + (objDate.getMonth() + 1) + ". " + objDate.getFullYear();  
    }


    // Vrátí dvě textová data - začátek a konec období.
    // Poslední tři měsíce
    function lastThreeMonths(strDate) {
      var objDate = splitDate(strDate); 
      var fromDate = new Date(objDate.valueOf());
      fromDate.setMonth(objDate.getMonth() - 3,1);
      var toDate = new Date(objDate.valueOf());
      toDate.setDate(0);
      return {from: joinDate(fromDate),to: joinDate(toDate)}  
    }

    // Poslední kalendářní čtrtletí
    function lastQuarter(strDate) {
      var objDate = splitDate(strDate); 
      //var thisQuarter = Math.floor((objDate.getMonth() - 1) / 3) + 1;
      // var lastQuarter = ((thisQuarter - 1 + 3)) % 4 + 1
      var monthInQuarter = objDate.getMonth() % 3;
      // return lastQuarter;
      var fromDate = new Date(objDate.valueOf());
      fromDate.setMonth(objDate.getMonth() - 3 - monthInQuarter,1);
      var toDate = new Date(fromDate.valueOf());
      toDate.setMonth(fromDate.getMonth() + 3,0);
      return {from: joinDate(fromDate),to: joinDate(toDate)} 
    }

    // Minulý nebo předminulý rok
    // breakMonth je poslední měsíc, který vydá předminulý rok
    // Pozor! leden = 0
    function lastOrButOneYear(strDate,breakMonth) {
      var objDate = splitDate(strDate); 
      var fromDate = new Date(objDate.valueOf());
      fromDate.setMonth(0,1);
      fromDate.setFullYear (objDate.getMonth() > breakMonth ? objDate.getFullYear() - 1 : objDate.getFullYear() - 2); 
      var toDate = new Date(fromDate.valueOf());
      toDate.setMonth(11,31);
      return {from: joinDate(fromDate),to: joinDate(toDate)} 
    }

    // Vrátí poslední den v měsíci.
    function lastDayOfMonth(objDate) {
      var dd = new Date(objDate.getFullYear(), objDate.getMonth(), 0);
      return dd.getDate();
    }
    
function checkDate(fld) {
    var mo, day, yr;
    var retVal = false;
    var entry = fld.value;
    var re = /\b\d{1,2}[\.\/-]\d{1,2}[\.\/-]\d{4}\b/;
    var delimChar;
    if (re.test(entry)) {
        if (entry.indexOf("/") != -1) {
          delimChar = "/";
        } else if (entry.indexOf("-") != -1) {
          delimChar = "-";
        } else {
          delimChar = ".";
        };
        var delim1 = entry.indexOf(delimChar);
        var delim2 = entry.lastIndexOf(delimChar);
        day = parseInt(entry.substring(0, delim1), 10);
        mo = parseInt(entry.substring(delim1+1, delim2), 10);
        yr = parseInt(entry.substring(delim2+1), 10);
        var testDate = new Date(yr, mo-1, day);
        // alert(testDate)
        if ((testDate.getDate() == day)
            && (testDate.getMonth() + 1 == mo)
                && (testDate.getFullYear() == yr)) {
                    retVal = true;
        }
        /*
        if (testDate.getDate() == day) {
            if (testDate.getMonth() + 1 == mo) {
                if (testDate.getFullYear() == yr) {
                    return {ok: true; desc: 'ok'}
                } else {
                    msg = "Nesprávně zadaný rok.";
                }
            } else {
                msg = "Nesprávně zadaný měsíc.";
            }
        } else {
            msg = "Nesprávně zadaný den.";
        }
    } else {
        msg = "Nesprávný formát data. Zadejte prosím 'mm.dd.yyyy'";
        */
    }
    return retVal;
}

/**
* Pokud není datum správně vyplněné, vrátí uživatele do políčka
*/
function validateDate(fld) {
  if (splitDate(fld.value) == undefined) {
      // focus if validation fails
      alert("Nesprávný formát data. Zadejte prosím 'mm.dd.yyyy'");
      fld.focus();
      fld.select();
      return false;
  } else {return true;}
}


/**
* Pokud není datum správné a rozumné, vrátí uživatele do políčka
*/
function validateRefDate(fld) {
  var tstRes = splitDate(fld.value);
  var dateOK = true;
  if (tstRes == undefined) {
    alert("Nesprávný formát data. Zadejte prosím 'mm.dd.yyyy'");
    dateOK = false;
  };
  if (tstRes.getTime() < minDate.getTime()) {
    alert("Prosím zadejte datum nejméně " + joinDate(minDate) + ". Pro starší období poradce nefunguje.");
    dateOK = false;
  };
  if (tstRes.getTime() > maxDate.getTime()) {
    alert("Prosím zadejte datum nejvýše " + joinDate(maxDate) + ". Pro vzdálenější budoucnost jsou rady nespolehlivé.");
    dateOK = false;
  };
  if (!dateOK) {
      fld.focus();
      fld.select();
  };
  $('rodina').refresh();
  return dateOK;
}


/** Vrátí true, pokud pole obsahuje číslo
* Snaží se nahradit desetinnou , znakem .
*/
function isNumber(fld) {
  if (!isNaN(fld.value)) {
    return true;
  } else {
    var commasReplaced = fld.value.replace(/\,/g,'.');
    if (!isNaN(commasReplaced)) {
      fld.value =commasReplaced;
      return true
    }
  }
  return false;
}

/** Ošetří, jestli je v poli zadané číslo
*/
function validateNumber(fld) {
    if (!isNumber(fld)) {
        alert('Do pole je třeba zadat číslo');
        fld.focus();
        fld.select();
        return false;
    } else {return true;}
}

/** Vrátí true, pokud pole obsahuje číslo, které vypadá jako věk
*/
function isAge(fld) {
  if (isNumber(fld)) {
    if ((fld.value >= 0 ) && (fld.value <= 150 )) 
    return true;
  }
  return false;
}

/** Ošetří, jestli je v poli zadané číslo, které vypadá jako věk
*/
function validateAge(fld) {
    if (!isAge(fld)) {
        alert('Do pole je třeba zadat číslo mezi 0 a 150');
        fld.focus();
        fld.select();
        return false;
    } else {return true;}
}
  
// Zobrazí nápovědu na místě, kde uživatel kliknul
function showQuickHelp(elem, helpId) 
{
  var qH = (helpId == undefined) ? $(elem.id + "_text") : $(helpId) ;
  //qH.clonePosition(elem);
  // alert('left:' + $(elem).cumulativeOffset().left);
  var myX = $(elem).cumulativeOffset().left;
  var myOffs = document.viewport.getScrollOffsets();
  var docX = document.viewport.getScrollOffsets().left;
  var docW = document.viewport.getWidth();
  qH.style.left=myX + 'px';
  // alert('top:' + $(elem).cumulativeOffset().top);
  var myY = $(elem).cumulativeOffset().top;
  qH.style.top=myY + 'px';
  qH.style.height = qH.getHeight();
 
  makeWindowed(qH)
  qH.show();
    
}

/** Ukáže varování před přechodem na žádost
*   Doplní adresy pro pokračování z dialogu
**/
function showWarn(elem, url_details, url_form) {
  $('url_details').value = url_details;
  $('url_form').value = url_form;
  showQuickHelp(elem, 'help_varovani_zadost');
}

// Obálka nad delší akcí - ukáže progress screen
function withWait(action) {
  // Zakryje stránku
  // alert('DEBUG: about to showWait');
  // DEBUG
  // showWait();
  // action();
  // hideWait();
  // return;
  // DEUBG END
  showWait();
  var that = this;
  setTimeout(function() {
    try {
      action();
    } finally {
      // alert('DEBUG: about to hideWait');
      hideWait();
    }
  }, 40);
}

// Překryje okno výzvou: čekejte ...
function showWait() 
{
  // return false; // debug
  var qH = $('splash_screen') ;
 
  var myX = document.viewport.getScrollOffsets().left + 10;
  qH.style.left=myX + 'px';   

  var myY = document.viewport.getScrollOffsets().top;
  qH.style.top=myY + 'px';
  
  var myH = document.viewport.getHeight() - 30;
  qH.style.height=myH + 'px';

  var myW = document.viewport.getWidth() - 30;
  qH.style.width=myW + 'px';
  
  var tH = $('splash_screen_text') ;
  
  var txtX = myX + (myW - tH.getWidth())/2;
  tH.style.left = txtX + 'px';

  var txtY = myY + (myH - tH.getHeight() - 100)/2 ;
  tH.style.top = txtY + 'px';

  makeWindowed(qH);
  qH.show();
  makeWindowed(tH);
  tH.show();
  // setTimeout('', 40);
}

// Schová výzvu: čekejte ...
function hideWait() 
{
  // return false; // debug
  $('splash_screen_text').hide();
  $('splash_screen').hide();
  // setTimeout('', 40);
}




function showQuickText(elem, htmlTxt) {
  var qH = new Element('div', { 'class': 'spQiuckHelp', style: "display:none;" }).update('  <img alt="zavřít" align=right src="/images/okobr/zavrit.gif" onclick="$(this).getOffsetParent().hide()" border="0"><br>' + htmlTxt);
  $('quick_help').insert(qH);
  qH.style.left=$(elem).cumulativeOffset().left + 'px';
  qH.style.top=$(elem).cumulativeOffset().top + 'px';
  qH.style.height = qH.getHeight(); 
  makeWindowed(qH)
  qH.show();     
}

/* Pokud je stisknutá klávesa Enter, zavolá funkci.
* Jinak nic.
*/
function onEnter(e, callBack){
  if (!e) var e = window.event;
  if(e.keyCode==13) {
    callBack();   
  }
}

// Naivní konverze HTML >> Text
function stripTags(msg){
  var myMsg = msg;
    myMsg = myMsg.replace(/&nbsp;/g,String.fromCharCode(160));
    myMsg = myMsg.replace(/<br>/ig,String.fromCharCode(13,10));
    myMsg = myMsg.replace(/<\/*p>/ig,String.fromCharCode(13,10));
    myMsg = myMsg.replace(/<[^>]*>/g,'');
    return myMsg;
}

/* Zavolá alert.
* Před tím z textu odstraní HTML.
*/
function alertHTML(msg){
    alert(stripTags(msg));
}
/** Vyčistí formulář, uvede vše do výchozího stavu
*/
function resetForm() {
  $('SocPr').reset();
  $('rodina').memberList.each(function(m) { resetMember(m) });
  var d = new Date();
  $('referencni_datum').value = (d.getDate() + "." + (d.getMonth() + 1) + "." + d.getFullYear());
  if ($('rodina').isValid()) {
    $('rodina').setValid(false);
  } else {
    showSelected();
  }
}
  
/** Zaškrtne automaticky podmínku
* Pokud je vyplněná rodina, zamkne.
* Pokud není platná rodina, nechá volné a nic nenastavuje.
*/
function forceCheck(check, condition) {
  if ($('rodina').isValid()) {
    check.checked = condition;
    check.disable();
  } else {
    check.enable();
  }  
}

/** Zaškrtne automaticky podmínku podle hodnoty vybrané v selectu
* Dohoda: 
* - 'x_undefined' .. checkbox povolen
* - 'x_??cokoli??' .. checkbox vypnutý zakázaný
* - 'cokoli jiného' .. checkbox zapnutý zakázaný
*/
function checkAsPer(check, selectValue) {
  if(selectValue == 'x_undefined'){
    check.enable()
  } else {
    check.disable()
    check.checked = (selectValue.substring(0,1)!='x');
  };
} // 
/** Ukáže varování
 */
function showWarning(warningId, warningName){
  $(warningId).show();
  if (warningName == undefined) {warningName = 'Překotrolujte podmínky dávky.'}
  warnings[warningId] = warningName;
}

/** Ukáže globální seznam varování nahoře na stránce
* .. pokud je třeba.
*/
function showWarningGlobal(){
  if (! isEmpty(warnings)) {
    $('varovani_seznam').update('');
    for (w in warnings) {
      $('varovani_seznam').insert('<li><a href="#'+ w +'" class="OKdistinct2">' + warnings[w] + '</a></li>')
    }
    showQuickHelp($('referencni_datum'),'help_varovani');
    warnings = {};
  } else {
    $('help_varovani').hide()
  }
}


/** Persistence formuláře.
* Jen speciality oproti obecné persistenci EasyStore
* Uchová navíc počet členů rodiny
* Při Load doplní napřed potřebné řádky
*/
var SocPrStore = Class.create(EasyStore, {
  loadForm: function(formName){
 // alert('DEBUG: loading form');
      var savedString = this.load(formName);
      var formData;
      try {
        formData = $H(eval('(' + savedString + ')'));
      } catch (e){}
      if (formData) {      
        var dataAge = ((new Date()).getTime() - formData.get('posledniUlozeni'))/dayInMillisec; // stáří dat ve dnech
        if (dataAge > peristLimit) {
          if (!confirm('Program nalezl data vyplněná před '+ Math.round(dataAge) +' dny. Přejete si je načíst?')) {
            return
          }          
        }
        var actualMembers = $('rodina_seznam').childElements().size()/2;
        for (var i=actualMembers;i<formData.get('pocetCelkem');i++) {addMember()}
        $(formName).populate(formData)
        $(formName).posledniUlozeni = formData.get('posledniUlozeni');
        $(formName).dataJsouStara = (dataAge > peristLimit);
     };
  },
  storeForm: function($super, formName){
      // alert('SocPrStore: chystám se uložit formulář');
      var formData = $H($(formName).serialize(getHash = true));
      formData.set('pocetCelkem', $('rodina').pocetCelkem);
      formData.set('posledniUlozeni', (new Date()).getTime()); // aktuální čas v milisekundách
      var storeString = '{"' + formData.toQueryString().replace(/&/gi, '", "').replace(/=/gi, '": "').replace('"pocetCelkem", ', '') + '"}';
      // alert('SocPrStore: ukládaná data: ' + storeString);
      // alert('SocPrStore: ukládaná data: ' + formData.toJSON());
      this.store(formName, storeString);
      // alert('SocPrStore: uloženo');
  }
})


/** Formátuje číslo na zadaný počet desetinných míst s oddělením tisíců
*/
function formatNumber(nStr, dec)
{
  if (isNaN(nStr)) { return nStr};
  var decimalSep = ',';
  var thousandSep = '&nbsp;';
	nStr += '';
	x = nStr.split('.');
	x1 = x[0];
	if (dec != undefined) {x[1] = (x[1]+'00000000000').substr(0,dec)}
	if (dec <= 0) {x.length = 1}
	x2 = x.length > 1 ? decimalSep + x[1] : '';
	var rgx = /(\d+)(\d{3})/;
	while (rgx.test(x1)) {
		x1 = x1.replace(rgx, '$1' + thousandSep + '$2');
	}
	return x1 + x2;
}

/** Formátuje číslo a doplní jednotky. Implicitně Kč na 0 destinných míst.
* nmb - číselná částka
* strCur - Nepovinné. Text s jednotkou. Musí obsahovat %d tam, kam má přijít číslo. 
*   př.: "%d Kč", "$%d", "%d měsíců"...
* dec - Nepovinné. Počet destinných míst (implicitně 0)
*/
function formatUnits(nmb, strCur, dec) {
  // Pokud je nmb nečíselný string, vrátí ho neporušený
  // Pokud je nmb NaN nebo undefined, vrátí undefined
  if (isNaN(nmb)) {return Object.isString(nmb)? nmb : undefined};
  // Pokud to vypadá jako číslo, formátuje se
  if(dec == undefined) dec = 0;
  if(strCur == undefined) strCur = dec == 0 ? FMT_KC_DES : FMT_KC0;
  var formNmb = formatNumber(nmb,dec);
  var strRes = strCur.replace(/\%d/,formNmb);
  return strRes;
}

/* Po částech lineární funkce
*/
var PerPartesLinear = Class.create(Enumerable, {
  initialize: function() {
    /** Pole se zlomy funkce. Uspořádané podle x.
    */
    this._points = new Array();
    /** hash se zlomy funkce. x - argument, y - hodnota
    */
    this._map = new Hash();
    for (i = 0, j = arguments.length; i < j; ++i) {
      // alert(i);
      var p = arguments[i];
      this.set(p.x, p.y)
    };
  },
  set: function(x, y) {
    this._map.set(+x, +y);
    this._points = new Array();
    this._map.keys().sortBy(function(a) {return +a }).each(function(x) {
      this._points.push({ 'x': +x, 'y': +this._map.get(x) })
    }, this)

  },
  /** Vydá hodnotu funkce v bodě xx.
  * Undefined, pokud se netrefí do žádného intervalu
  */
  value: function(xx) {
    xx = +xx;
    var p = this._points;
    var lB = -Infinity;
    var uB = Infinity;
    for (var i = 0, j = p.length; i < j; ++i) {
      if (p[i].x <= xx) { lB = i };
      if (p[i].x >= xx) { uB = i; break };
    };
    if (p[lB] == undefined || p[uB] == undefined) {
      return undefined
    };
    if (p[lB].x == p[uB].x) {
      return p[lB].y
    } else {
      return p[lB].y + (p[uB].y - p[lB].y) * (xx - p[lB].x) / (p[uB].x - p[lB].x);
    }
  },
  /** Vydá (nejmenší) x, pro které funkce vrátí hodnotu yy.
  * Undefined, pokud se nenajde
  */
  base: function(yy) {
    yy = +yy;
    var p = this._points;
    var lB = undefined;
    var uB = undefined;
    for (var i = 0, j = p.length - 1; i < j; ++i) {
      if (p[i].y <= yy && p[i + 1].y >= yy || p[i].y >= yy && p[i + 1].y <= yy) {
        lB = i;
        uB = i + 1;
        break;
      };
    };
    if (lB == undefined) {
      return undefined
    };
    if (p[lB].y == p[uB].y) {
      return p[lB].x
    } else {
      return p[lB].x + (p[uB].x - p[lB].x) * (yy - p[lB].y) / (p[uB].y - p[lB].y);
    }
  },
  /** Kombinuje dvě po částech lineární
  * Zlomy výsledné funkce jsou tam, kde je zlom aspoň jedné vstupní.
  * Hodnoty funkce se spočítají zadaným vzorcem z hodnot vstupních funkcí
  */
  merge: function(that, formula) {
    var resFce = new PerPartesLinear();
    // var xPoints = new Array();
    this.each(function(p) {
      var x = p.x;
      var y = formula(this.value(x), that.value(x));
      // alert('Adding ' + x + ':' + y);
      resFce.set(x, y);
    }, this);
    that.each(function(p) {
      var x = p.x;
      var y = formula(this.value(x), that.value(x));
      // alert('Adding ' + x + ':' + y);
      resFce.set(x, y);
    }, this);
    /*
    xPoints.each(function(i) {
    var x = xPoints[i];
    resFce.set(x, formula(this.valueOf(x), that.valueOf(x)));
    }, this);
    */
    return resFce;
  },
  _each: function(iterator) {
    this._points.each(iterator)
  },
  inspect: function() {
    var str = '';
    this._points.each(function(p) {
      str += $H(p).inspect();
    });
    return str;
  }

}) //PerPartesLinear


/** Je objekt prázdný?
 */
function isEmpty(ob){
   for(var i in ob){ return false;}
  return true;
}

// Finta, která obejde chybu v MSIE, kvůli kteé nelze překrýt select elementem div.
// Viz www.actionscript.org/forums/showthread.php3?t=132324
     // make the specified div a windowed control in IE6
     // this masks an iframe (which is a windowed control) onto the div,
     // turning the div into a windowed control itself
     function makeWindowed(p_div)
     {
        var is_ie6 =
           document.all && 
           (navigator.userAgent.toLowerCase().indexOf("msie 6.") != -1);
        if (is_ie6)
        {
           var html =
              "<iframe src=\"javascript:false\" style=\"position: absolute; display: block; " +
              "z-index: -1; width: 100%; height: 100%; top: 0; left: 0;" +
              "filter: mask(); background-color: #ffffff; \"></iframe>";
          
           if (p_div) p_div.innerHTML += html;
           // force refresh of div
           var olddisplay = p_div.style.display;
           p_div.style.display = 'none';
           p_div.style.display = olddisplay;
        };
     }

/** Paramter z URL
* Source: http://www.11tmr.com/11tmr.nsf/D6Plinks/MWHE-695L9Z
*/

function getURLParam(strParamName){
  var strReturn = "";
  var strHref = window.location.href;
  if ( strHref.indexOf("?") > -1 ){
    var strQueryString = strHref.substr(strHref.indexOf("?")).toLowerCase();
    var aQueryString = strQueryString.split("&");
    for ( var iParam = 0; iParam < aQueryString.length; iParam++ ){
      if ( 
aQueryString[iParam].indexOf(strParamName.toLowerCase() + "=") > -1 ){
        var aParam = aQueryString[iParam].split("=");
        strReturn = aParam[1];
        break;
      }
    }
  }
  return unescape(strReturn);
} 

// ******** Trasování ***************
function Tracer() {
    this.log = [];
    this.flag = 0;
    // Zapíše hlášku + čas do logu
    this.trace = function(msg, level) {
      if (level == undefined) level = 1;
      if(this.flag < level){return}
      var d = new Date();
      // this.log += '<tr><td>' +msg + '</td><td>' + d.getTime() + '</td></tr>';
      this.log.push({'level':level,'msg':msg,tm:d.getTime()})
    };

    // Vypíše log
    this.show = function() {
      if (this.log.size() <= 0) return false;
      var rep = '<table><tr><th>level</th><th>msg</th><th>time</th><th>period</th><th>total</th></tr>';
      var firstTime = this.log[0].tm
      for (var l = 0, len = this.log.length; l < len; ++l) {
        var myTime = this.log[l].tm;
        var myPeriod = l >= len-1 ? 0 : this.log[l+1].tm - myTime;
        var myTotal = myTime - firstTime;
        rep += '<tr><td>' + this.log[l].level + '</td><td>' + this.log[l].msg + '</td><td>' + myTime + '</td><td>' + myPeriod + '</td><td>' + myTotal + '</td></tr>';
      }
      rep += '</table>';
      document.getElementById('traceOut').innerHTML = rep;
    };

    // Vymaže log
    this.reset = function() {
      this.log = [];
    };

    // Zapnout
    this. setOn = function(level) {
      this.flag = level==undefined ? Infinity : level;
    };

    // Vypnout
    this.setOff = function() {
      this.flag = 0;
    }

} 

// ******** Konstanty ***************

// Zobrazí se tam, kde hodnota nelze spočítat
var unValue = '???';//'<img alt="Program hodnotu spočítá, pokud zadáte vstupní údaje." style="margin: 3px" src="/soc/poradce/images/help_16x16.gif" border="0">'; //'---';
// Fragment pro splněné podmínky
var okStr = '<img alt="zkuste podat žádost" title="zkuste podat žádost" style="margin: 3px" src="/soc/poradce/images/good.gif" border="0">';
var okStrTxt = '<span class="spAno">Zkuste to</span>';
var okStrLink = '<span class="spAno spLink" onclick="$(\'###\').onclick()">Zkuste to</span>';
// Fragment pro nesplněné podmínky
var noStr = '<img alt="nemá cenu žádost podávat" title="nemá cenu žádost podávat" style="margin: 3px" src="/soc/poradce/images/bad.gif" border="0">';
var noStrTxt = '<span class="spNe">Ne</span>';
// Implicitní počet řádků pro rodinu
var defaultMembers = 4;
var defaultMember = 
'<tr id="clenX" class="spPruh spPruhNormal spZaklad">' + '\n' +
'    <td><img id="clenX_smazat" alt="smazat" src="/soc/poradce/images/red_delete.gif" style="display:none" onclick="clearMember(this.parentNode.parentNode)" border="0"></td>' + '\n' +
'     <td style="white-space:nowrap;"><input type="text" id="clenX_vek" name="clenX_vek" onkeypress="onEnter(event,this.onchange);" onchange="if($(\'clenX_vek\').value==\'\'){clearMember($(\'clenX\'))} else if(validateAge($(\'clenX_vek\'))){$(\'clenX\').refresh()};" size="3" style="width: 25pt; text-align: right" value="">&nbsp;<span title="Položka je povinná"><b>!</b></span></td>' + '\n' +
'     <td><input type="text" id="clenX_jmeno" name="clenX_jmeno" size="10" value=""></td>' + '\n' +
'     <td style="text-align:left;white-space:nowrap;">' + '\n' +
'      <input type="checkbox" onclick="if(!this.checked){$(\'clenX_stud\').checked=false;};$(\'clenX\').refresh();" id="clenX_neza" name="clenX_neza" disabled>&nbsp;nezaopatřené<br>' + '\n' +
'        <span id="clenX_pest_text" class="spJenDite" style="display:none"><input type="checkbox" class="spJenDite"  onclick="$(\'clenX\').refresh();" id="clenX_pest" name="clenX_pest">&nbsp;v pěstounské péči</span><br>' + '\n' +
'        <span id="clenX_stud_text" class="spJenDite" style="display:none"><input type="checkbox" class="spJenDite"  onclick="if(this.checked){$(\'clenX_neza\').checked=\'on\';};$(\'clenX\').refresh();" id="clenX_stud" name="clenX_stud">&nbsp;student</span><br>' + '\n' +
'     </td>' + '\n' +
'     <td style="text-align:center"><input type="checkbox" onclick="$(\'clenX\').refresh();" id="clenX_ozp_check" disabled name="clenX_ozp_check" size="4"><br>' + '\n' +
'      </td>' + '\n' +
'     <td class="spDluh" style="text-align:center;display:none"><input type="checkbox" onclick="$(\'clenX\').refresh();" id="clenX_dluh_check" disabled name="clenX_dluh_check" size="4"><br>' + '\n' +
'      </td>' + '\n' +
'     <td><span id="clenX_zm" class="spDopocitanePole">---</span></td>' + '\n' +
'     <td class="spHidden"><span id="clenX_em" class="spDopocitanePole">---</span></td>' + '\n' +
'     <td class="spHidden"><input type="text" id="clenX_pocet" name="clenX_pocet" size="1" value=""></td> ' + '\n' +
'     <td class="spHidden"><input type="text" id="clenX_pocet_v_kategorii" name="clenX_pocet_v_kategorii" size="1" value=""></td>' + '\n' +
'' + '\n' +
'  </tr>' + '\n' +
'  <tr id="clenX_ozp" class="spPruh spPruhNormal spJenOZP" style="display:none">' + '\n' +
'    <td colspan="6">' + '\n' +
'      <table border="0" class="spOZPpanel">' + '\n' +
'        <tr><td colspan="2"><div id="clenX_ozp_radek" style="display:none">       ' + '\n' +
'          Stupeň postižení: ' + '\n' +
'          ' + '\n' +
'            <select id="clenX_ozp_stup" name="clenX_ozp_stup" title="Stupeň zdravotního postižení" onchange="$(\'clenX\').refresh();" size="1">' + '\n' +
'              <option selected value="x_undefined">--zadejte stupeň postižení--</option>' + '\n' +
'              <option value="1">dlouhodobě nemocný</option>' + '\n' +
'              <option value="2">dlouhodobě zdravotně postižený</option>' + '\n' +
'              <option value="3">dlouhodobě těžce zdravotně postižený</option>' + '\n' +
'            </select>' + '\n' +
'            <img id="clenX_ozp_stup_show" alt="Stručná nápověda" onclick="showQuickHelp(this,\'help_ozp_stup\')" src="/images/okobr/otaznik.gif" border="0">' + '\n' +
'          </div></td>' + '\n' +
'        </tr>' + '\n' +
/*
'        <tr>       ' + '\n' +
'          <td>Přiznané výhody: </td>' + '\n' +
'          <td>' + '\n' +
'            <select id="clenX_ozp_vyhod" name="clenX_ozp_vyhod" title="Stupeň zdravotního postižení" onchange="$(\'clenX\').refresh();" size="1">' + '\n' +
'              <option selected value="x_undefined">--zadejte stupeň výhod--</option>' + '\n' +
'              <option value="1">I. stupeň (průkaz TP)</option>' + '\n' +
'              <option value="2">II. stupeň (průkaz ZTP)</option>' + '\n' +
'              <option value="3">III. stupeň (průkaz ZTP/P)</option>' + '\n' +
'            </select>' + '\n' +
'            <img id="clenX_ozp_vyhod_show" alt="Stručná nápověda" onclick="showQuickHelp(this,\'help_ozp_vyhod_text\')" src="/images/okobr/otaznik.gif" border="0">' + '\n' +
'          </td>' + '\n' +
'        </tr>' + '\n' +
*/
'        <tr>' + '\n' +
'          <td>Stupeň závislosti<br> na péči jiné osoby:</td>' + '\n' +
'          <td>' + '\n' +
'            <select id="clenX_zav_stup" name="clenX_zav_stup" title="Stupeň závislosti na péči jiné osoby" onchange="$(\'clenX\').refresh();" size="1">' + '\n' +
'              <option selected value="x_undefined">--zadejte stupeň závislosti--</option>' + '\n' +
'              <option value="1">stupeň I (lehká závislost)</option>' + '\n' +
'              <option value="2">stupeň II (středně těžká závislost)</option>' + '\n' +
'              <option value="3">stupeň III (těžká závislost)</option>' + '\n' +
'              <option value="4">stupeň IV (úplná závislost)</option>' + '\n' +
'            </select>' + '\n' +
'             <img id="clenX_zavislost_show" alt="Stručná nápověda" onclick="showQuickHelp(this,\'help_zavislost_text\' )" src="/images/okobr/otaznik.gif" border="0">' + '\n' +
'          </td> ' + '\n' +
'        </tr> ' + '\n' +
'        <tr>' + '\n' +
'          <td>Nevidomý:</td>' + '\n' +
'          <td>' + '\n' +
'            <input type="checkbox" onclick="$(\'clenX\').refresh();" id="clenX_nevi" name="clenX_nevi">' + '\n' +
'          </td>' + '\n' +
'        </tr>         ' + '\n' +
'      </table> ' + '\n' +
'    </td>' + '\n' +
'  </tr>';
// milisekund za den
var dayInMillisec = 1000*60*60*24;
// limit na stáří uložených dat - ve dnech
var peristLimit = 30; // debug: 100/dayInMillisec;
// Minimální datum, pro které poradce pracuje - 1.1.2008
var minDate = new Date(2010,1 - 1,1);
// Maximální datum, pro které poradce pracuje - Rok dopředu.
var maxDate = new Date();
maxDate.setFullYear(maxDate.getFullYear() + 1);
// Vysvětlující hint, pokud položku nelze spočítat
var txtCannotCount ="Pokud zadáte vstupní údaje, program částku spočítá."
// formát finanční částky
var FMT_KC0 = "<span class=\"spCastka\">%d&nbsp;Kč</span>";
var FMT_KC0_TAB = "<span class=\"spCastkaTab\">%d&nbsp;Kč</span>";
var FMT_KC_DES = "<span class=\"spCastka\">%d&nbsp;Kč</span>";

// Protokol o čase
var trc = new Tracer();

