/*
Tento kód smí upravovat puze Ondřej Tišler nebo jím pověřená osoba, pokud potřebujete svou speciální
funkci a je obecná, tak přiďte za mnou, pokud obecná není, tak nepatří do tohoto souboru.

Změnu textů chybových hlášek proveďte předefinováním pole message PO includnutí tohoto souboru, pole message
se v tomto souboru NEUPRAVUJE
*/
/*use:
<form name="aaa" onSubmit="return(testAll(this))">
  <input type="text" name="bbb">
  <input type="text" name="ccc">
  <script language="JavaScript">
    document.aaa.bbb.tests=new Array(testDate, testEmpty);
    document.aaa.bbb.format="dd.mm.yyyy hh.mi";
    document.aaa.ccc.tests=new Array(testNumber, minLength);
    document.aaa.ccc.minLength=5;
  </script>
</form>
*/
/* seznam testů a jejich požadavky:
  testValue - test na nepovolený textový obsah (instrukce na vyplnění v polích)
    text - zakázaný text
  testEmpty  - otestuje prázdnost pole, u vyšších verzí lze testovat i pole typu select
    [attach] - pole (Array), odkazů na jiná pole, pokud je jeden z odkazů vyplněn, pak pole
               může být prázdné
    [condition] - pole (Array), odkazů na jiná pole, pokud není ani jeden z odkazů vyplněn, pak pole
               může být prázdné
  testEmptySelect - test na prázdné pole option v prvku select, kontroluje se přítomnost libovolné volby,
                    žádná volba nemusí být vybrána (pro test vybrání volby použijte testEmpty)
  testNumber - v poli mohou být vyplněny jen číslice bez znaménka a desetiné čárky
    [minValue] - minimální hodnota pole, akceptuje objekt s definovanou toString vracející číslo
    [maxValue] - maximální hodnota pole, akceptuje objekt s definovanou toString vracející číslo
  testPhoneFragment - test na telefonní číslo (čísla + mezery)
  testReal   - v poli může být kladné reálné číslo, desetiná tečka se konvertuje na des. čárku, mezery jsou vyhozeny
    [maxNumsAfter] - povolený počet desetinných míst za des. tečkou
    [minValue] - minimální hodnota pole, akceptuje objekt s definovanou toString vracející číslo
    [maxValue] - maximální hodnota pole, akceptuje objekt s definovanou toString vracející číslo
  minLength  - v poli musí být vyplněno alespoň x znaků
    minLength - požadovaný minimální počet znaků
  maxLength  - v poli může být maximálně x znaků, určeno pro textarea
    maxLength - maximální počet znaků v poli
  testPassword - otestuje shodnost vyplněných hesel, pokud jsou různé, pak jsou obě pole vymazána
    confirmField - odkaz na potvrzovací pole
  testDate   - test datumového pole, jako oddělovač lze použit libovolný nečíselný znak
    format - libovolná kombinace dd, mm, yy(yyyy), mi, hh, nezávisí na velikosti písmen
           - jako oddělovač lze moužít jakýkoli znak mimo předchozích + ff, tyto oddělovače jsou pak odeslány
  testBirthNumber - test na rodné číslo (kompletní)
  testEmails - otestuje, zda jsou správně zadány emailové adresy. Implicitně je minCount=0, maxCount se nebere
               vůbec v úvahu
    [minCount] - minimální počet zadaných emailů
    [maxCount] - maximální počet zadaných emailů

*/

/* 	jscripty potřebují pro svou práci nadefinované příslušné resourcy
	v proměnné message (asociativní pole, klíčem řetězce, obsahem vypisovaná hláška)*/
var message = new Array();
    message["hasValue"] = "Nevyplnil jste položku.";
    message["empty"]="Pole nesmí být prázdné.";
    message["notANumber"]="Řetězec '{0}' není číslo.";
    message["minValue"] = "Minimalni hodnota čísla v tomto poli je {0}.";
    message["maxValue"] = "Maximalni hodnota čísla v tomto poli je {0}.";
    message["notAPhone"] = "Řetězec '{0}' není telefonní číslo.";
    message["notAReal"]="Řetězec '{0}' není reálné číslo";
    message["toManyNumbersAfterFloatingPoint"]="Maximální počet des. míst je {0}.";
    message["minLength"]="Minimální délka řetězce je {0}.";
    message["maxLength"]="V poli je {0} znaků. Maximální délka řetězce je {1} znaků.";
    message["passwordsDifferent"]="Zadaná hesla nejsou shodná.";
    message["invalidDate"]="Datum byl rozeznán jako {0} a není platný. Formát data je {1}.";
    message["birthNumberInvalidDate"] = "Datum uvedené v rodném čísle '{0}.{1}.{2}' není platné.";
    message["birthNumberInvalidCRC"] = "Kontrolní součet rodného čísla {0} nesouhlasí.";
    message["birthNumberMinLength"] = "U ročníku {0} je počet čísel rodného čísla {1} číslic.";
    message["email"] = "Zadaná emailová adresa \"{0}\" není správná";
    message["emailMax"] = "Bylo zadáno více emailových adres než je povoleno ({0}). Maximální počet je {1}.";
    message["emailMin"] = "Bylo zadáno méně emailových adres než je povoleno ({0}). Minimální počet je {1}.";

/**********************************************************************************
*************od tohoto bodu je vlastni kod scriptu
***********************************************************************************/


var maxdays = new Array(12);       // definice maximálních počtů dnů v jednotlivých
    maxdays[0] = 31;               // měsících
    maxdays[1] = 31;
    maxdays[2] = 28;
    maxdays[3] = 31;
    maxdays[4] = 30;
    maxdays[5] = 31;
    maxdays[6] = 30;
    maxdays[7] = 31;
    maxdays[8] = 31;
    maxdays[9] = 30;
    maxdays[10] = 31;
    maxdays[11] = 30;
    maxdays[12] = 31;

/** třída poskytuje rozhraní pro includy do stringů */
function MessageFormat(){};
/** metoda provede includy do stringu
 * @param input string, do kterého se aplikují includy
 * @param includes pole objektů (volá se toString), s includy, toto pole musí pokrýt všechny includy v input
 *        pokud se v includu vyskytne {x}, kde:
 *          x < index includu - pak se v nezměněné podobě zapíše do výstupního řetězce
 *          x = index includu - ZAKÁZANÁ kombinace, metoda se zacyklí
 *          x > index includu - na {x} se aplikuje další include
 */
MessageFormat.format = function (input, includes){
  var index = 0;
  var output = input;
  while (output.indexOf("{"+index+"}")>-1) {
    output = output.substring(0, output.indexOf("{"+index+"}"))+includes[index]
      +output.substring(output.indexOf("{"+index+"}")+2+(index+"").length);
    if (output.indexOf("{"+index+"}")==-1) index++;
  }
  return output;
}
/*################ vlastní testy #################*/

// test na nepovolený textový obsah
function testValue(what) {
  if (what.text==what.value) {
    alert(message["hasValue"]);
    return false;
  }
  else
    return true;
}

// test na prázdnost pole
function testEmpty(what) {
  var re = /^\s[ \t]*$/;
  var attachEmpty = true;
  if (what.attach!=null&&what.attach.length>0) {
    for (var i = 0; i<what.attach.length; i++)
      if (what.attach[i].value.replace(re,'')!='')
        attachEmpty = false
  }
  var condition = false;
  if (what.condition!=null&&what.condition.length>0) {
    attachEmpty = false;
    for (var i = 0; i<what.condition.length; i++)
      if (what.condition[i].value.replace(re,'')!='')
        condition = true;
  }
  if ((condition || attachEmpty) && what.value.replace(re,'')=='') {
    alert(message["empty"]);
    return false;
  }
  else {
    return true;
  }
}

// test na prázdné pole option prvku select
function testEmptySelect(what) {
  if (what.options.length==0) {
    alert(message["empty"]);
    return false;
  }
  else
    return true;
}

// test číslic
function testNumber(what) {
	  val = what.value;
    var re = /[\d]*/;
    if (val.charAt(0).replace( /[+-]/ , '') == "") {
	    val = val.substring(1);
  	}
    if ( val.replace(re,'') != "" ) {
  	alert(MessageFormat.format(message["notANumber"], new Array(what.value)));
    return false;
		} else {
  	if (what.maxValue != null) {
  		if (what.value > parseInt(what.maxValue.toString())) {
				alert(MessageFormat.format(message["maxValue"], new Array(what.maxValue.toString()+"")));
				return false;
			}
		}
		if (what.minValue != null) {
			if (what.value < parseInt(what.minValue.toString())) {
				alert(MessageFormat.format(message["minValue"], new Array(what.minValue.toString()+"")));
				return false;
			}
		}
    return true;
  }
}

// test telefonního čísla
function testPhoneFragment(what) {
  var re = /\+?(\d*[ ]*)*/;
  if (what.value.replace(re,'')!='') {
      alert(MessageFormat.format(message["notAPhone"], new Array(what.value)));
    return false;
  }
  else {
    return true;
  }
}

// test realnych cisel
/* ve vlastnosti maxNumsAfter může uložit maximální počet des.míst*/
function testReal(what){
  var re = /[.]/g; // zmena . na ,
  var ret = what.value.replace(re,',');
  re = /[\s\xA0]/g; // akceptace mezer
  ret = ret.replace(re, '');
  re = /\d*[,]?\d*/;
  if (ret.replace(re,'')!="") {
      alert(MessageFormat.format(message["notAReal"], new Array(what.value)));
    return false;
  }
  else {
    if (what.maxNumsAfter!=null) {
      re = new RegExp("[0123456789]*[,]?[1234567890]{0,"+what.maxNumsAfter+"}");
      if (ret.replace(re,'')!="") {
        alert(MessageFormat.format(message["toManyNumbersAfterFloatingPoint"], new Array (what.maxNumsAfter+"")));
        return false;
      }
    }
    if (what.maxValue != null) {
  		if (what.value > parseFloat(what.maxValue.toString())) {
				alert(MessageFormat.format(message["maxValue"], new Array(what.maxValue.toString()+"")));
				return false;
			}
		}
		if (what.minValue != null) {
			if (what.value < parseFloat(what.minValue.toString())) {
				alert(MessageFormat.format(message["minValue"], new Array(what.minValue.toString()+"")));
				return false;
			}
		}
    what.value=ret;
    return true;
  }
}

// test na minimalní délku
function minLength(what) {
  if(what.value!=null && what.value.length < what.minLength && what.value!="") {
    alert(MessageFormat.format(message["minLength"], new Array(what.minLength+"")));
    return false;
  }
  else {
    return true;
  }
}

// test na maximální délku (pro textarea, text se ošetří příslušným atributem)
/* ve vlastnosti maxLength nastavte max. počet znaků*/
function maxLength(what) {
  if(what.value!=null && what.value.length > what.maxLength && what.value!="") {
    alert(MessageFormat.format(message["maxLength"], new Array(what.value.length, what.maxLength+"")));
    return false;
  }
  else {
    return true;
  }
}

// test dvou hesel (polí), je nutno nastavit odkaz confirmField na druhé pole
function testPassword (what) {
  if ((what.value==null || what.value=="") && (what.confirmField.value==null || what.confirmField.value=="")) {
    return true;
  }
  else {
    if (what.value!=what.confirmField.value) {
      alert(message["passwordsDifferent"]);
      what.value="";
      what.confirmField.value="";
      return false;
    }
    else return true;
  }
}

// test správnosti formátu data
function testDate(what) {
  format=what.format;
  value=what.value;
  var isOk=true;
  var output="";
  if (value!=null && value!="") {                    // pokud je vyplněný datum, tak ho zanalyzuj
    // normalizace datumu
    var re = /\W/g;
    iformat=format.replace(re," ");
    iformat=iformat.toLowerCase();
    iformat=iformat.replace("mi","ff");
    re = /\D/g;
    value=value.replace(re," ");
    for (var i=0; i<format.length; i++) {
      if (iformat.charAt(i)!=" " && value.charAt(i)==" ") {
        value=value.substring(0,i)+' '+value.substring(i);
      }
      if (iformat.charAt(i)==" " && value.charAt(i)!=" " && value.charAt(i)!="") {        
        value=value.substring(0,i-1)+value.substring(i+1);
        isOk=false;
      }
    }
    value=value.substring(0,iformat.length);
    // day - dd DD
    var day=new Number(value.substring(iformat.indexOf('d'),iformat.lastIndexOf('d')+1));
    // month - mm MM
    var month=new Number(value.substring(iformat.indexOf('m'),iformat.lastIndexOf('m')+1));
    // year - yyyy YYYY, yy YY
    var year=new Number(value.substring(iformat.indexOf('y'),iformat.lastIndexOf('y')+1));
    // hour - hh HH
    var hour=new Number(value.substring(iformat.indexOf('h'),iformat.lastIndexOf('h')+1));
    // min - ff, FF
    var min=new Number(value.substring(iformat.indexOf('f'),iformat.lastIndexOf('f')+1));
    if (year<50) {year=2000+year;}
    if ((year>=50)&&(year<100)) {year=1900+year;}
    if ((month==2)&&((year % 4) == 0)&&(((year % 100) != 0)||((year % 400) == 0))) {
      maxdays[2]=29;}
    if ((iformat.indexOf('d')<0?false:day<1)||day>maxdays[month]) {isOk=false;}
    if ((iformat.indexOf('m')<0?false:month<1)||month>12) {isOk=false;}
    if (hour<0 || hour>23) {isOk=false}
    if (min<0 || min>59) {isOk=false}
    // složeni opraveneho datumu
    var length,i=0;
    while (i<iformat.length) {
      co=iformat.charAt(i);
      if (co==" ") {
        output=output+format.charAt(i);
        i++
      }
      else {
        re = new RegExp("[^"+co+"+]","g");
        length=iformat.replace(re,"").length;
        switch (co) {
          case 'd' :
            output+=day
            break;
          case 'm' :
            output+=month
            break;
          case 'y' :
            output+=year % Math.pow(10, length);
            break;
          case 'h' :
            output+=hour;
            break;
          case 'f' :
            output+=min==0?'00':min;
            break;
        }
        i+=length;
      }
    }
  }
  if (!isOk)
    alert(MessageFormat.format(message["invalidDate"], new Array (output, what.format)));
  else
    what.value=output;
  return isOk;
}

/** otestuje kompletně rodné číslo */
function testBirthNumber(what) {
  // vyjímky: 0 - ok, 1 - špatné datum, 2 - špatný kontrolní součet, 3 - není číslem, 4 - min délka 9/10 znaků
  if (what.value!=null && what.value!="") {
    var day=-1;
    var month=-1;
    var year=-1;
    var value=what.value;
    try {
    // číslo
      var re = /[^+-]\D/g;
      if (what.value != what.value.replace(re,''))
      	throw 3;
    // datum
      var day=-1;
      var month=-1;
      var year=-1;
      day=new Number(value.substring(4, 6));
      month=new Number(value.substring(2, 4));
      year=new Number(value.substring(0, 2));
      if (value.length==10 && year<54) year=year+2000;
        else year=year+1900;
    // minimální délka
      if ((year>=1954 && value.length<10) || (year<1954 && value.length<9))
        throw 4;
      if ((month==2)&&((year % 4) == 0)&&(((year % 100) != 0)||((year % 400) == 0))) {
        maxdays[2]=29;}
      if (month>50) month=month-50;
      if (month<1||month>12)         throw 1;
      if (day<1||day>maxdays[month]) throw 1;
    // kontrolní součet
      if (value.length==10) {
        base = new Number(value.substring(0, 9));
        if ((base % 11) % 10 != new Number(value.substring(9, 10))) throw 2;
      }
    }
    catch (e) {
      if (e instanceof Error)
        throw e;
      else
        switch (e) {
          case 1 :
            alert(MessageFormat.format(message["birthNumberInvalidDate"], new Array(day, month, year)));
            return false;
          case 2 :
            alert(MessageFormat.format(message["birthNumberInvalidCRC"], new Array(value)));
            return false;
          case 3 :
            alert(MessageFormat.format(message["notANumber"], new Array(value)));
            return false;
          case 4 :
            alert(MessageFormat.format(message["birthNumberMinLength"], new Array(year, year>1954?"10":"9")));
            return false;
          case 0 :
            return true;
            break;
          default :
            return false;
        }
    }
  }
  return true;
}

/* Funkce otestuje, zda byl zadán seznam emailů, oddělený středníky nebo čárkami. Je povoleno zadat i 0 emailů.
 * Minimální počet emailů udává parameter minValue, max počet emailů: maxValue*/
function testEmails(what) {
  /* Funkce otestuje, zda byl zadán email (žádný nebo jeden) parameter je String */
  function testEmailText(email) {
    email = trim(email);
    if (email == "") return true;
    var filter  = /^([a-zA-Z0-9%_\.\-])+\@(([a-zA-Z0-9\-])+\.)+([a-zA-Z0-9]{2,4})+$/;
    if (filter.test(email)) {
      return true;
    }
    else {
      alert(MessageFormat.format(message["email"], new Array(email)));
      return false;
    }
  }
  var minValue = what.minValue;
  var maxValue = what.maxValue;
  // rozdělení mezi středníky

  var re = /[;,]/g;
 	var emails = what.value.split(re);
 	var isOK = true;
 	var countOK = 0;
 	// kontrola jednotlivých emailů
 	for(var i=0; i < emails.length; i++) {
 	  if (trim(emails[i]) == "") continue;
 	  if (testEmailText(emails[i])) {
 	    countOK++;
 	  }
 	  else {
 	    isOK = false;
 	  }
 	}
  if (isOK) {
    if (minValue != null) if (countOK < minValue) {
      isOK = false;
      alert(MessageFormat.format(message["emailMin"], new Array(countOK, minValue)));
    }
    if (maxValue != null) if (countOK > maxValue) {
      isOK = false;
      alert(MessageFormat.format(message["emailMax"], new Array(countOK, maxValue)));
    }
  }
  if (isOK) what.value = what.value.replace(re, ";"); // přepíše všechny "," na ";"
  return isOK;
}

/* funkce otestuje všechny políčka předaného formuláře dle pole tests daného prvku
   a vrátí případné chybné políčko*/
function returnCorruptField (where) {
  if (where!=null) {
    for (var i=0; i<where.elements.length; i++) {
      var test = false;
      if (where.elements[i].tests!=null) {
        test=true;
        for (var el=where.elements[i];test==true&&el.tagName!="BODY";el=el.parentNode)
          if (el.disabled==true) test=false;
      }
      if (test) {
        var tests = where.elements[i].tests;
        if (tests.constructor != Array)
          tests = eval("new Array ("+tests+")");
        //alert(where.elements[i].tagName+":"+where.elements[i].id+":"+tests);
        for (var j=0; j<tests.length; j++) {
          if (tests[j](where.elements[i])==false) {
            return where.elements[i];
          }
        }
      }
    }
  }
  return;
}

/* funkce otestuje všechny políčka předaného formuláře dle pole tests daného prvku
  a vrátí true, pokud je o.k. jinak false */
function testAll(where) {
  var corrupt = returnCorruptField(where)
  if (corrupt!=null) {
    corrupt.focus();
    return false;
  }
  return true;
}

/** Pomocná funkce trim() - oseká mezery ze začátku a konce zadané hodnoty **/
function trim(what) {
  return what.replace(/^[\s]*/,'').replace(/[\s]*$/,'');
}
