var digits = "0123456789";
var lowercaseLetters = "abcdefghijklmnopqrstuvwxyz"
var uppercaseLetters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var validLetters = "èéòàùìöäüëß '\t\n\r"

var validWithNumbers =  " ., '-\|/_--\t\n\r"


// caratteri whitespace
var whitespace = " \t\n\r";

// giorni nei mesi
var daysInMonth = makeArray(12);
daysInMonth[1] = 31;
daysInMonth[2] = 29;   // da verificare con funzione specifica
daysInMonth[3] = 31;
daysInMonth[4] = 30;
daysInMonth[5] = 31;
daysInMonth[6] = 30;
daysInMonth[7] = 31;
daysInMonth[8] = 31;
daysInMonth[9] = 30;
daysInMonth[10] = 31;
daysInMonth[11] = 30;
daysInMonth[12] = 31;

// non-digit separatori di data
var dateDelimiter = "/";

// numero digits per CAP
var digitsInCAP = 5
// max numero digits per Postal Code 20
var digitsInPostalCode = 20;

// numero digits per Codice fiscale
var digitsInCodfis = 16


// Definisce il valore di ritorno per le funzioni che ricevono
// stringhe vuote
// se defaultEmptyOK è false ( default ) la funzione ritornerà
// false se chiamata con stringa vuota;
// se defaultEmptyOK è è true  la funzione consente di accettare
// chiamate con stringa vuota e  ritornerà true
//

var defaultEmptyOK = false


// crea un array
function makeArray(n) {
   for (var i = 1; i <= n; i++) {
      this[i] = 0
   }
   return this
}

 
// Controlla se la stringa s è vuota
function isEmpty(s)
{   return ((s == null) || (s.length == 0))
}



// Ritorna true se la stringa è vuota o è
// composta solo da caratteri 'whitespace'
function isWhitespace (s)
{   var i;

    // stringa vuota
    if (isEmpty(s)) return true;

    // arriva al primo carattere non-whitespace
    // quando lo trova, ritorna false ;
    // altrimenti, ritorna true

    for (i = 0; i < s.length; i++)
    {
        // controlla se il carattere corrente sia whitespace
        var c = s.charAt(i);

        if (whitespace.indexOf(c) == -1) return false;
    }

    // tutti i caratteri sono whitespace.
    return true;
}



// Ritorna true se il carattere c è un digit
// (0 .. 9).
function isDigit (c)
{   return ((c >= "0") && (c <= "9"))
}



// isInteger (STRING s [, BOOLEAN emptyOK])
//
// Ritorna true se tutti i caratteri nella stringa s sono numbers
//
// Accetta solo  non-signed integers .
//
function isInteger (s)

{   var i;

    if (isEmpty(s))
       if (isInteger.arguments.length == 1) return defaultEmptyOK;
       else return (isInteger.arguments[1] == true);

    // arriva al primo carattere non-numerico
    // quando lo trova, ritorna false ;
    // altrimenti, ritorna true

    for (i = 0; i < s.length; i++)
    {
        // controlla che il carattere corrente sia  number.
        var c = s.charAt(i);

        if (!isDigit(c)) return false;
    }

    // tutti i caratteri sono  numbers.
    return true;
}



// isAlphabetic (STRING s [, BOOLEAN emptyOK])
//
// Ritorna true se s è una lettera
// (A .. Z, a..z)
//
function isAlphabetic (s)

{   var i;

    if (isEmpty(s))
       if (isAlphabetic.arguments.length == 1) return defaultEmptyOK;
       else return (isAlphabetic.arguments[1] == true);


    for (i = 0; i < s.length; i++)
    {
        // controlla che c sia una lettera
        var c = s.charAt(i);

        if (!isLetter(c))
        return false;
    }

    // tutti i caratteri sono lettere.
    return true;
}




// isAlphanumeric (STRING s [, BOOLEAN emptyOK])
//
// Ritorna true se s è una lettera
// (A .. Z, a..z) o un  numero.

function isAlphanumeric (s)
{   var i;

	if (isEmpty(s))
       if (isAlphanumeric.arguments.length == 1) return defaultEmptyOK;
       else return (isAlphanumeric.arguments[1] == true);

    for (i = 0; i < s.length; i++)
    {
        // controlla che il carattere corrente sia un numero o una lettera
        var c = s.charAt(i);
        if (! (isLetter(c) || isDigit(c) ) )
        return false;
    }

    // tutti i caratteri sono numeri o lettere
    return true;
}


//	For username and password fields check.
// 
function isValidUid(str){
	
	 // controllo che ci sia almeno una lettera o un numero 
	 var flag = 0;
	 for (i = 0; i < str.length && flag==0; i++) {
	          var c = str.charAt(i);
	          if ( isLetter(c) || isDigit(c) ) {  flag=1; }
	 }
	 if (flag == 0) {	return false; }	
	
	// controllo range caratteri validi
	var res="";
	var a = new Array();
	a[1] = "_";
	a[2] = ".";
	
	for (i=0; i < a.length; i++){
		res = res + a[i];	
	}
	
	var re = new RegExp("^[a-zA-Z0-9\-"+ res +"]*$", "");
	
	if (re.test(str)){
		return true;
	}else{
		return false;
	}
	
}


// isEmail (STRING s [, BOOLEAN emptyOK])
//
// Email deve essere del tipo  a@b.c :
//  - deve esserci almeno un carattere prima di  @
//  - deve esserci almeno un carattere prima e dopo il .
//  - i caratteri @ e . sono entrambi richiesti
//

function isEmail (s)
{   var i;
    if (isEmpty(s))
       if (isEmail.arguments.length == 1) return defaultEmptyOK;
       else return (isEmail.arguments[1] == true);

    // se la stringa è composta solo da whitespace  ritorna false
    if ( isWhitespace(s) ) return false;

       			
    // deve esserci almeno un carattere prima di  @
    // quindi il controllo parte dal secondo
    i = 1;
    var sLength = s.length;
	
    // cerca  @
    while ((i < sLength) && (s.charAt(i) != "@"))
    {   if ( s.charAt(i) == " ") return false ;
    	i++ ;
    }

    if ((i >= sLength) || (s.charAt(i) != "@")) return false;
    i++ ;
    if ( (s.charAt(i) == "@") || (s.charAt(i) == ".") || (s.charAt(i) == " ") ) return false ;
    i++ ;


    // cerca  .
    while ((i < sLength) && (s.charAt(i) != "."))
    {   if ( s.charAt(i) == " ") return false ;
    	i++ ;
    }

    if (    (s.charAt(sLength-1) == ".")  ||  (s.charAt(sLength-1) == "@")  ) return false ;

    // ci deve essere almeno un carattere dopo  .
    if ((i >= sLength - 1) || (s.charAt(i) != ".")) return false;
    else return true;
}


// isSignedInteger (STRING s [, BOOLEAN emptyOK])
//
// Ritorna true se tutti i caratteri sono numeri
// il primo carattere può rappresentare il segno ( + o - ).

function isSignedInteger (s)

{   if (isEmpty(s))
       if (isSignedInteger.arguments.length == 1) return defaultEmptyOK;
       else return (isSignedInteger.arguments[1] == true);

    else {
        var startPos = 0;
        var secondArg = defaultEmptyOK;

        if (isSignedInteger.arguments.length > 1)
            secondArg = isSignedInteger.arguments[1];

        // skip leading + or -
        if ( (s.charAt(0) == "-") || (s.charAt(0) == "+") )
           startPos = 1;
        return (isInteger(s.substring(startPos, s.length), secondArg))
    }
}


// isNonnegativeInteger (STRING s [, BOOLEAN emptyOK])
//
// Ritorna true se la stringa è un integer >= 0.
    // - s deve essere un signed integer e
    // - una delle seguenti condizioni deve essere vera
    //    -  s è vuota ed il parametro defaultEmpty è true
    //    -  s è un number >= 0

function isNonnegativeInteger (s)
{   var secondArg = defaultEmptyOK;

    if (isNonnegativeInteger.arguments.length > 1)
        secondArg = isNonnegativeInteger.arguments[1];

    return (isSignedInteger(s, secondArg)
         && ( (isEmpty(s) && secondArg)  || (   (killBugParse(s)) >= 0) ) );
}






// isIntegerInRange (STRING s, INTEGER a, INTEGER b [, BOOLEAN emptyOK])
//
// ritorna true se s è un numero compreso tra a e b (inclusi)
//

function isIntegerInRange (s, a, b)
{   if (isEmpty(s))
       if (isIntegerInRange.arguments.length == 1) return defaultEmptyOK;
       else return (isIntegerInRange.arguments[1] == true);

    if (!isInteger(s, false)) return false;


    var num = parseInt ( killBugParse(s) );
    return ((num >= a) && (num <= b));
}



// Restituisce la stringa che sarà passata a ParseInt senza "0" davanti
// previene il bug di parseInt che non converte una stringa che ha
// "0" come primo carattere
//

function killBugParse (s) {

  if ( s.charAt(0) == "0" ) {
      return  ( s.substring(1, s.length ) )   ;
   }

  return s ;
}



// Ritorna true se la data è composta solo dai delimitatori 
// 
// 

function isEmptyDate(s)
{   
	
	if ( isEmpty(s) || s==dateDelimiter+dateDelimiter)
		return true;

}


// isYear (STRING s [, BOOLEAN emptyOK])
// isYear ritorna true se la  stringa s è un anno valido
// a 4 cifre tra 1900 e 2100

function isYear (s)
{   if (isEmpty(s))
       if (isYear.arguments.length == 1) return defaultEmptyOK;
       else return (isYear.arguments[1] == true);
    if (!isNonnegativeInteger(s)) return false;

    return ( (s.length == 4) && (isIntegerInRange(s, 1900, 2100) ) );
}

// isMonth (STRING s [, BOOLEAN emptyOK])
// ritorna true se s è un mese valido compreso tra 1 e 12

function isMonth (s)
{   if (isEmpty(s))
       if (isMonth.arguments.length == 1) return defaultEmptyOK;
       else return (isMonth.arguments[1] == true);

    return isIntegerInRange (s, 1, 12);
}



// isDay (STRING s [, BOOLEAN emptyOK])
// ritorna true se s è un giorno valido compreso tra 1 e 31

function isDay (s)
{

    if (isEmpty(s))
       if (isDay.arguments.length == 1) return defaultEmptyOK;
       else return (isDay.arguments[1] == true);


    return  isIntegerInRange (s, 1, 31) ;

}



// daysInFebruary (INTEGER year)
//
// ritorna i giorni di febbraio per l'anno specificato nel parametro
// febbraio ha 29 giorni negli anni divisibili per 4,
// eccetto per gli anni divisibili per 100 che non sono divisibili anche per
// 400

function daysInFebruary (year)
{
    return (  ((year % 4 == 0) && ( (!(year % 100 == 0)) || (year % 400 == 0) ) ) ? 29 : 28 );
}


// isDate ( STRING day, month, year )
//
// isDate ritorna true se i parametri formano una data corretta
//



function isDate ( day, month, year )
{


// controlla la validità di year , month e day

if  (  (!isYear(year, false))  ||  (!isMonth(month, false))  ||
       (!isDay(day , false)) )
    return false;


    var intYear  = killBugParse(year);
    var intMonth = killBugParse(month);
    var intDay   = killBugParse(day);

    if ( intDay > daysInMonth[intMonth] ) return false ;

    // controlla i giorni per febbraio
    if ( (intMonth == 2) && (intDay > daysInFebruary(intYear))  )
      return false  ;

    return true;
}


// isCAP (STRING s)
// controlla la correttezza del Codice di Avviamento Postale (5 digits)

function isCAP (s)
{  if (isEmpty(s))
       if (isCAP.arguments.length == 1) return defaultEmptyOK;
       else return (isCAP.arguments[1] == true);
   return ( isInteger(s) &&  (s.length == digitsInCAP) )
}


// isPostalCode (STRING s)
// controlla la correttezza del Codice di Avviamento Postale per stati esteri (Postal Code)

function isPostalCode (s)
{  if (isEmpty(s))
       if (isPostalCode.arguments.length == 1) return defaultEmptyOK;
       else return (isPostalCode.arguments[1] == true);
   return ( isAlphanumeric(s) &&  (s.length <= digitsInPostalCode) )
}



// controlla la coerenza del codice fiscale
//
// Le posizioni occupate da caratteri alfabetici sono :
// 1,2,3 (cognome)  4,5,6 (nome)
// 9,12  (mese e comune/stato di nascita )
// 16    (controllo)
//

function isCodfis (s)

{   var i;

    if (isEmpty(s))
       if (isCodfis.arguments.length == 1) return defaultEmptyOK;
       else return (isCodfis.arguments[1] == true);
	
    if (s.length != digitsInCodfis) return false ;
		
    for (i = 0; i <= 5 ; i++)
    {
        // tre caratteri per il cognome, tre per il nome
        var c = s.charAt(i);
        if ( !(isLetter(c)) )  return false;
    }

    // carattere per mese di nascita
	
    var c = s.charAt(8);
    if (! (isLetter(c)) ) return false;
	
    // carattere per comune o stato di nascita
    var c = s.charAt(11);
    if (! (isLetter(c)) ) return false;
    // carattere di controllo
    var c = s.charAt(15);
    if (! (isLetter(c)) ) return false;

    // le seguenti posizioni sono normalmente occupate da caratteri
	// numerici,ma possono venire sostituite da lettere in caso di codice fiscale
	// identico ad uno già assegnato
	
    for (i = 6 ; i <= 14 ; i++) {
	    if ( ( i != 8 ) && (i != 11 ) )  {
          var c = s.charAt(i);
	      if (! (isLetter(c) || isDigit(c) ) ) return false ;
	    }
	}

    return true;
}


function isLetter (c)
{   return ( ((c >= "a") && (c <= "z")) || ((c >= "A") && (c <= "Z")) )
}



//  isValidWithNumbers(s)
//  Ritorna true se la stringa contiene una sequenza di lettere
//  o caratteri ammessi nella variabile validWithNumbers
//  Da usare per il controllo di campi del tipo città, ente, telefono, fax
//  che possono essere composti da più parole intervallate da
//  spazi, apostrofi , slash, punti e composti anche da numeri
//
function isValidWithNumbers(s)
{   var i;

      for (i = 0; i < s.length; i++)
     {
          // controlla che il carattere corrente sia una lettera, numero  o un carattere ammesso
          var c = s.charAt(i);
          if ( !(  isLetter(c) || isDigit(c) ||  validWithNumbers.indexOf(c) != -1  ) ) return false;
     }

     // tutti i caratteri sono numeri o lettere o caratteri ammessi da validWithNumbers
     return true;
}

//  isValidAlphabetic(s)
//  Ritorna true se la stringa contiene una sequenza di lettere
//  o caratteri ammessi nella variabile validLetters
//  Da usare per il controllo di campi del tipo Nome o Cognome
//  che possono essere composti da più parole intervallate da
//  spazi o apostrofi
//
function isValidAlphabetic(s)
{   var i;

       if (isEmpty(s))
       if (isValidAlphabetic.arguments.length == 1) return defaultEmptyOK;
       else return (isValidAlphabetic.arguments[1] == true);

    for (i = 0; i < s.length; i++)
    {
        // controlla che il carattere corrente sia una lettera o un carattere ammesso
        var c = s.charAt(i);
        if (!( isLetter(c) || validLetters.indexOf(c) != -1  ) ) return false;
	}

    // tutti i caratteri sono numeri o lettere o caratteri ammessi da validLetter
    return true;
}



//  isValidPhone(s)
function isValidPhone(s)
{
       var i;

      for (i = 0; i < s.length; i++)
     {
          // controlla che il carattere corrente sia una lettera, numero  o un carattere ammesso
          var c = s.charAt(i);
          if ( !(  isDigit(c) ||  validWithNumbers.indexOf(c) != -1  ) ) return false;
     }

     // tutti i caratteri sono numeri o caratteri ammessi da validWithNumbers
     return true;
}


// Funzioni di controllo e validazione dei campi richiamate dalla form //
// checkString (TEXTFIELD theField, STRING s, [, BOOLEAN emptyOK==false])
// Ritorna true se la stringa  theField.value non è composta solo da whitespace.

function checkString (theField, emptyOK)
{
    if (checkString.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    if (isWhitespace(theField.value)) return false
       else return true;
}



function checkValidAlphabetic (theField, emptyOK)
{
    if ( checkValidAlphabetic.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    if ( !isValidAlphabetic (theField.value)) return false
       else return true;
}




function checkValidWithNumbers (theField, emptyOK)
{
    if ( checkValidWithNumbers.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    if ( !isValidWithNumbers (theField.value)) return false
       else return true;
}





// checkEmail (TEXTFIELD theField [, BOOLEAN emptyOK==false])
//
// Controlla che la stringa  theField.value rappresenti un
// indirizzo  Email.
//

function checkEmail (theField, emptyOK)
{   if (checkEmail.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    else if (!isEmail(theField.value, false))
       return false ;
    else return true;
}


// controlla che la stringa  theField.value sia un anno valido
//

function checkYear (theField, emptyOK)
{   if (checkYear.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    if (!isYear(theField.value, false))
       return false ;
    else return true;
}

// checkDate (  STRING theField [, OKtoOmitDay==false] )
// Controlla che la stringa theField rappresenti una data valida
//
// - accetta anche day e month ad una cifra
// - non accetta year.length != 4
// - accetta separatori di data specificati in dateDelimiter

function checkDate (theField, emptyOK)
{
    if (checkDate.arguments.length == 1) emptyOK  = defaultEmptyOK;
    if ((emptyOK == true) && (isEmptyDate(theField.value))) return true;
	
    var dateString = theField.value ;
	
    var day   = dateString.substring
	                       ( 0, dateString.indexOf(dateDelimiter) ) ;
    var month = dateString.substring
	                       ( dateString.indexOf(dateDelimiter) + 1 ,
						               dateString.lastIndexOf(dateDelimiter) ) ;
    var year  = dateString.substring
	                       ( dateString.lastIndexOf(dateDelimiter) + 1 ) ;

      	
    if (isDate (day, month, year) )   return true;
	
    return false ;
}


// Controlla che la stringa theField rappresenti una CAP valido
// - accetta numeri interi a 5 cifre
function checkCAP (theField, emptyOK)
{   if (checkCAP.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    else
    {
      if (!isCAP(theField.value) ) return false ;
      else
         return true;
    }
}

// Controlla che la stringa theField rappresenti un Postl Code  valido
function checkPostalCode (theField, emptyOK)
{   if (checkPostalCode.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    else
    {
      if (!isPostalCode(theField.value) ) return false ;
      else
         return true;
    }
}

// Controlla che la stringa theField rappresenti un
// numero di telefono
function checkPhone (theField, emptyOK)
{  
	if (checkPhone.arguments.length == 1) emptyOK = defaultEmptyOK;
 	if ((emptyOK == true) && (isEmpty(theField.value))) return true;
	else {
  		if (  !isValidPhone(theField.value)  || isEmpty(theField.value) ) return false
     	else  return true;
	}
}



// Controlla che la stringa theField rappresenti un Codice fiscale valido
// - accetta stringhe a 16 cifre
function checkCodfis (theField, emptyOK)
{   if ( checkCodfis.arguments.length == 1) emptyOK = defaultEmptyOK;
    if ((emptyOK == true) && (isEmpty(theField.value))) return true;
    else
    {
      if (!isCodfis(theField.value) ) return false ;
      else
         return true;

    }
}


// funzioni di verifica selezione da combo box e radio button //


// Ritorna false se nessun elemento di un radio button  è checked .

function isRadioChecked (radio)
{   for (var i = 0; i < radio.length; i++)
    {   if (radio[i].checked) { return true } ;
    }
	
    return false ;
}

// Ritorna false se nessun elemento di una combo box  è checked
// oppure se è selezionato un campo blank

function isComboSelected (select)
{
    for (var i = 0; i < select.length; i++)
    {
	   if   ( (select.options[i].selected)  &&
	             (!isWhitespace(select.options[i].text))  )
	                { return true } ;
    }
	
    return false ;
}