// validatore.js
// autore: Kiko
// copyright 2006 Metaware S.p.A.
// creato il 15/02/2006

/* Il validatore si occupa della validazione degli input di un form
 *
 * Gli attributi riconosciuti nei tag INPUT, SELECT e TEXTAREA  sono:
 *  - mw-required:  se vale true viene testato che il valore non sia stringa vuota
 *  - mw-type: puo' valere:  
 *        - date 
 *        - orario 
 *        - piva
 *        - cf-pfisica
 *        - cf
 *        - cap
 *        - email
 *        - string
 *        - digit
 *        - currency
 *        - phone
 *  - NO!! mw-force-message: se vale true i messaggi di errori vengono emessi sempre,
 *                      altrimenti quelli di tipo 'Campo obbligatorio' non vengono mostrati
 *  - mw-to-uppercase: prima di effettuare la validazione converte in maiuscolo il contenuto del controllo
 *  - mw-to-lowercase: prima di effettuare la validazione converte in minuscolo il contenuto del controllo
 *  - mw-non-blocking: valida regolarmente ma non produce errore globale (cioè con la checkAll)
 *  - mw-pattern: valida in base al pattern inserito
 *  - mw-size: lunghezza (reale, contando due volte gli "a capo")
 *
 *  Esempio:  <label>Data di macellazione<br/>
 *              <input type="text" size="10" maxlength="10"
 *                     mw-required="true" mw-type="date"
 *                     name="{data/@__id}"
 *                     onblur="Validatore.coloredValidate(this)"/>
 *            </label>
 *
 * E' possibile dichiarare un contenitore per l'errore di validazione, tipicamente uno SPAN
 * che può stare ovunque nel documento ma deve avere le seguenti caratteristiche:
 * - deve avere un id = 'err_<name o id del controllo da validare>'         (NB: name ha la priorità)
 * - mw-add-label: specifica se nel testo dell'errore deve essre aggiunto il messaggio di testo 
 *                 contenuto nella label contenitore del controllo 
 * - mw-handle-parent: specifica se è necessario nascondere/visualizzare anche il contenitore dell'errore (nell'esempio, il TD)
 *                 puo' valere true o un numero che specifica quanti padri nascondere/visualizzare 
 * - mw-insert-br-before e mw-insert-br-after: aggiunge un <br/> prima o dopo il messaggio di errore
 * - mw-keep-message: non crea alcun messaggio: si limita a rendere visibile quello presente nel contenitore
 *
 *  Esempio:  <td colspan="6" style="display: none;">
 *                <span id="err_{data/@__id}" mw-add-label="true" mw-handle-parent="true" class="error" style="display: none;">&nbsp;</span>
 *            </td>
 * 
 *
 *
 *-----> FUNZIONI PUBBLICHE <-----
 *
 * Validatore.checkAll(idNodoRoot) :
 *   - esegue il check di tutti i nodi a partire da quello con id idNodoRoot
 *   - ritorna un booleano
 *
 * Validatore.coloredCheckAll(idNodoRoot) :
 *   - esegue il check di tutti i nodi a partire da quello con id idNodoRoot
 *   - colora li background dei nodi non validi
 *   - setta il codice di errore nel contenitore con id associato al nome del
 *        nodo non valido (es: se il nome del nodo e' cippaLippa, cerca di 
 *        piazzare l'errore nel nodo con id='err_cippaLippa')
 *   - ritorna null se è andato tutto bene, oppure l'md5 dell'errore globale (compresi i vcalori)
 *
 * Validatore.booleanValidate(nodo) :
 *   - esegue il check del singolo nodo
 *   - ritorna un booleano
 *
 * Validatore.coloredValidate(nodo) :
 *   - esegue il check del singolo nodo
 *   - colora li background dei nodi non validi
 *   - setta il codice di errore nel contenitore con id associato al nome del
 *        nodo non valido (es: se il nome del nodo e' cippaLippa, cerca di 
 *        piazzare l'errore nel nodo con id='err_cippaLippa')
 *   - ritorna il messaggio d'errore o null
 *
 * Validatore.alertValidate(nodo) :
 *   - esegue il check del singolo nodo
 *   - apre un alert (modale) con il codice di errore
 *   - ritorna un booleano
 *
 */

//brutale inclusione del javascript che calcola l'md5
document.write('<script language="javascript" type="text/javascript" src="javascript-lib/md5.js"> </script>');
//brutale inclusione del javascript di validazione di Dunia
document.write('<script language="javascript" type="text/javascript" src="javascript-lib/mw_validateUtilities.js"> </script>');
 
//var Validatore = new Object();

function Validatore(nodeId, mandatoryElementsId)
{
	this.radioArray = new Array();    //cache dei controlli radio
	this.checkboxArray = new Array();    //cache dei controlli checkbox
	this.mandatoryElementsId = mandatoryElementsId;
    this.oldErrore = null;
	
	if (nodeId != null && nodeId != '')
        this.rootEl =  document.getElementById(nodeId);
    else
        this.rootEl =  document;
}

new Validatore(null, null);

Validatore.prototype.coloredCheckAll = function (testaSoloIlTipo)
{
	if (this.mandatoryElementsId != null)
	{
		this.nascondiErrore(document.getElementById(this.mandatoryElementsId), true);
	}

   // try
    {
        var risultato = true;
        var stringona = "";
        // booleano che dice se almeno un elemento obbligatorio manca
        var missingMandatory = false;

        if (this.rootEl != null)
        {
            var dummy;
            var elemento;
            var tipo;
 
            //analizzo gli input
            var elementi = this.rootEl.getElementsByTagName('input');
            for (var i=0; i < elementi.length; i++)
            {    
                elemento = elementi[i];
                tipo = elemento.type.toUpperCase();
                
                if (!elemento.disabled && (tipo == "TEXT" || tipo == "RADIO" || tipo == "CHECKBOX" || tipo == "PASSWORD" ))
                {
                    dummy = this.coloredValidate(elemento, testaSoloIlTipo);

                    if (this.extractBlocking(elemento))
                    {
                        if (dummy != null)
                            risultato = false;
                        stringona += elemento.name + elemento.value;
                    }

					if (tipo == "RADIO" && elemento.checked)
					{
						stringona += "*";
					}

                }
            }
            
            //analizzo le select
            elementi = this.rootEl.getElementsByTagName('select');
            for (var i=0; i < elementi.length; i++)
            {
                elemento = elementi[i];

                if (!elemento.disabled)
                {
                    dummy = this.coloredValidate(elemento, testaSoloIlTipo);
    
                    if (this.extractBlocking(elemento))
                    {
                        if (dummy != null)
                            risultato = false;
        
                        stringona += elemento.name + elemento.value;
                    }
                }
            }
            
            //analizzo le textarea
            var elementi = this.rootEl.getElementsByTagName('textarea');
            for (var i=0; i < elementi.length; i++)
            {
                elemento = elementi[i];
                dummy = this.coloredValidate(elemento, testaSoloIlTipo);

                if (this.extractBlocking(elemento))
                {
                    if (dummy != null)
                        risultato = false;
    
                    stringona += elemento.name + elemento.value;
                }
            }
        }
        
        this.setError(
                this.rootEl,
                (risultato) ? '' : mw_validator_errore_form, mw_validator_show_all_errors
        );
        
        if (risultato)
            return null;
        else
            return b64_md5(stringona);    //tanto per ruzzare
    //  return risultato;
    }
/*    catch (e)
    {
        alert('Impossibile validare: ' + e);
        return false;
    }*/
}

Validatore.prototype.getRoot = function (nodeId)
{
    if (nodeId != null && nodeId != '')
        return document.getElementById(nodeId);
    else
        return document;
}

Validatore.prototype.booleanValidate = function (node, testaSoloIlTipo)
{
    this.performToUpperCase(node);
    this.performToLowerCase(node);
            
    return  (this.validate2(node, testaSoloIlTipo) == '');
}

Validatore.prototype.coloredValidate = function (node, testaSoloIlTipo)
{
    this.performToUpperCase(node);
    this.performToLowerCase(node);
            
    var msg = this.validate2(node, testaSoloIlTipo);
    
    this.setColor(node, msg);
   
    this.setError(node, msg, mw_validator_show_all_errors);
     
    if (this.mandatoryElementsId != null)
	{
        var formName = node.form.name;
        var formId = node.form.id;
   
        //this.hideMandatoryErrors(formName, formId);
        this.hideMandatoryErrors();
    }
 
    return (msg == '') ? null : msg;
  
}

Validatore.prototype.alertValidate = function (node)
{
    this.performToUpperCase(node);
    this.performToLowerCase(node);
            
    var messaggio = this.validate2(node);

    if (messaggio != '')
        alert(messaggio);
        
    return  (messaggio == '');
}

Validatore.prototype.setColor = function (node, message)
{
    var tipo = node.type.toUpperCase();
    var nome = node.name;
    
    if (message != '')
        node.style.backgroundColor = mw_validator_background_color_error;
	else
	{
	    if (tipo == 'RADIO')
    	{
			var radios = node.form.elements;
		
			if (radios != null && radios != undefined)
			{
				for (var i=0; i < radios.length; i++)
				{
					if (radios[i].name == nome)
				        radios[i].style.backgroundColor = '';//mw_validator_background_color_ok;
				}
			}
		}
		else
	        node.style.backgroundColor = '';//mw_validator_background_color_ok;
	}    
}

Validatore.prototype.setError = function (node, message, showAllErrors)
{
    if(node == null) return;
    //provo a cercare lo span usando il nome del controllo
    var errore = document.getElementById('err_' + node.name);

	if (message != mw_validator_campo_obbligatorio)
	{
	    if (errore == null && node.id != null && node.id != undefined && node.id != '')
	    {
	        //provo a cercare usando l'id
	        errore = document.getElementById('err_' + node.id);	        
	    }
    }
    else
    {
    	errore = document.getElementById(this.mandatoryElementsId);
    }

	if (errore == null) // se il campo 'errore' non c'è, non lo segnalo
		return;
	
    //var forza = (node.getAttribute('mw-force-message') == 'true') || showAllErrors;

    if (message != '') // c'é errore
    { 
    	if (message != mw_validator_campo_obbligatorio) // errore generico
	    {
	    	// se ho stabilito che per il campo non venga creata un'etichetta, mi limito a mostrare il contenuto dello span
	    	if (errore.getAttribute('mw-keep-message') != 'true')
			{
		        if (errore.getAttribute('mw-add-label') == 'true')
		        {
		            var lab = node.parentNode;
		            if (lab.nodeName.toUpperCase() == 'LABEL')
		                message = estraiTestoDaNodo(lab) + ': ' + message;
		        }
		
		        var msg = '';
		        if (errore.getAttribute('mw-insert-br-before') == 'true')
		            msg += '<br/>';
		        msg = msg + message;
		        if (errore.getAttribute('mw-insert-br-after') == 'true')
		            msg = msg + '<br/>';
		
		        errore.innerHTML = msg;
	        }
	    }

	    this.nascondiErrore(errore, false);
    }
    else
    {
	    if (errore.getAttribute('mw-keep-message') != 'true')
		{
		   errore.innerHTML='';
		}

        this.nascondiErrore(errore, true);
    }
        
}

/**
 * Nasconde il messaggio di errore per i campi obbligatori nel caso in cui tutti 
 * siano stati compilati (indipendentemente dal fatto che siano stati compilati correttamente o meno)
 */
Validatore.prototype.hideMandatoryErrors = function (formName, formId)
{
        var form = this.rootEl;

        /*
        var form = null;

        //prima vedo se c'e' un form con quell'id, se non lo trovo cerco tra i nomi dei form
        if (formId != null && formId != '')        
            form = document.getElementById(formId);

        if (form == null || form == undefined)
            if (formName != null && formName != '')        
                form = document.forms[formName];

        if (form == null || form == undefined)
        {
            alert("Specificare almeno il nome o l'id del form"); 
            return;
        }*/
	    var inputEls = form.getElementsByTagName('input');
	    var selectEls = form.getElementsByTagName('select');
	    var textAreaEls = form.getElementsByTagName('textarea');
	    var hide = 'true';
	    
	    // FIXME: Becca anche campi che non sono visibili graficamente. 
	    // Quest'ultimo caso e' difficile da gestire
	    if((inputEls != undefined) && (inputEls != null))
    	    for(var i = 0;i < inputEls.length; i++)
    	    {
    	    	var inp = inputEls[i];
    	    
    	    	if((inp.getAttribute("mw-required") == 'true') && mw_isEmpty(inp.value) && (!inp.disabled) && (inp.name != '^ignore'))
    	    	{
    	    		hide = 'false';
    	    		break;
    	    	}
    	    }
    	    
	    if((selectEls != undefined) && (selectEls != null))
    	    for(var i = 0;i < selectEls.length; i++)
    	    {
    	    	var sel = selectEls[i];
    	    
    	    	if((sel.getAttribute("mw-required") == 'true') && mw_isEmpty(sel.value) && (!sel.disabled) && (sel.name != '^ignore'))
    	    	{
    	    		hide = 'false';
    	    		break;
    	    	}
    	    }
    	  
	    if((textAreaEls != undefined) && (textAreaEls != null))
    	    for(var i = 0;i < textAreaEls.length; i++)
    	    {
    	    	var tex = textAreaEls[i];
    	    
    	    	if((tex.getAttribute("mw-required") == 'true') && mw_isEmpty(tex.value) && (!tex.disabled) && (tex.name != '^ignore'))
    	    	{
    	    		hide = 'false';
    	    		break;
    	    	}
    	    }
	  
	    if(hide == 'true')
	    {
	    	this.nascondiErrore(document.getElementById(this.mandatoryElementsId), true);
	    }
}

Validatore.prototype.nascondiErrore = function (nodo, nascondi)
{
    if (nascondi)
        nodo.style.display = 'none';
    else        
        nodo.style.display = '';

    var cheFare = nodo.getAttribute('mw-handle-parent');
   
    if (cheFare != null && cheFare != undefined && cheFare != '')
    {
        var nu = parseInt(cheFare, 10);
        if (isNaN(nu))
            nu = 1;

        var parente = nodo;
        for (var i=0; i<nu; i++)
        {
            parente = parente.parentNode; 
        }
            
        if (nascondi)
            parente.style.display = 'none';
        else        
            parente.style.display = '';
    }
}


/* Esegue il test vero e proprio, ritorna stringa vuota se e' andato tutto bene
 * oppure il messaggio di errore.
 */
Validatore.prototype.validate2 = function (node, testaSoloIlTipo)
{
    //sembra stupido ma devo farlo, per sicurezza
    if (testaSoloIlTipo == null || testaSoloIlTipo == undefined || testaSoloIlTipo != true)
        testaSoloIlTipo = false;

    var tipoNodo = node.type.toUpperCase();
    var nomeNodo = node.tagName.toUpperCase();
    var nodename = node.name;
    
    if (!((nomeNodo == 'INPUT' && 
            (tipoNodo == "TEXT" || 
             tipoNodo == "RADIO" ||
             tipoNodo == "CHECKBOX" ||
             tipoNodo == "PASSWORD" )) 
        || nomeNodo == 'SELECT'
        || nomeNodo == 'TEXTAREA'))
         return '';

    if (/*nodename == '^ignore' ||*/ node.style.display == 'none' || node.disabled)
         return '';
    
    //scorro verso il nodo radice per vedere se il nodo in questione è contenuto in qualcosa di disabilitato
    //Di un'inefficienza triviale. Non e' vero, ho fatto un po' di prove e il ritardo e' impercettibile.
    for (var precNode = node.parentNode; precNode != null && precNode != document; precNode = precNode.parentNode)
    {
        if (precNode.style.display == 'none' || precNode.style.visibility == 'hidden')
            return '';
    }
    
    var valore = node.value;

    //test di esistenza
    var required = this.extractRequired(node);
    if (required)
        if (nomeNodo == 'SELECT' || 
                nomeNodo == 'TEXTAREA' || 
                tipoNodo == 'TEXT' || 
                tipoNodo == 'PASSWORD')
            if (mw_isEmpty(valore))
                return mw_validator_campo_obbligatorio;
            else
                ; //nop
        else 
        {   //Siamo in un radio o in un checkbox. 
            // Assumo che i radio dello stesso pannello abbiano lo stesso name.
            var elementi = this.getByType(tipoNodo);
            var hasChecked = false;
            
            for (var i=elementi.length; i-->0;)
                 if (elementi[i].name == nodename && elementi[i].checked)
                 {
                     hasChecked = true;
                     i=0; //smetto di testare    
                 }
            
            if (!hasChecked)
                return 'Scelta obbligatoria';
         }

    if (valore == '')
        return '';
    
    //test di tipo
    var tipo = this.extractType(node);
    if (tipo != null && tipo != '')
        switch (tipo)
        {
            case 'string':
                if (!mw_isValidString(valore))
                    return mw_validator_caratteri_non_validi;
            break;
            case 'date':
            	var data = this.normalizzaData(valore); 
//                if (mw_isValidDate(valore) == null)
				if (data == null)
                    return mw_validator_data_non_corretta;
                node.value = data;
            break;
            case 'orario':
            	var orario = this.normalizzaOrario(valore); 
				if (orario == null)
                    return mw_validator_orario_non_corretto;
                node.value = orario;
            break;
            case 'piva':
                var dummy = mw_validatePIVA(valore);
                
                if (dummy == ERR_IVA_LEN)
                    return mw_validator_partita_iva_corta;
                else if (dummy == ERR_IVA_CHAR)
                    return mw_validator_partita_iva_caratteri_invalidi;
                else if (dummy == ERR_IVA_CHECKSUM)
                    return mw_validator_partita_iva_invalida;
            break;
            case 'cf-pfisica':
                var dummy = mw_validateCF(valore);
                
                if (dummy == ERR_CF_LEN)
                    return mw_validator_cfpf_corto;
                else if (dummy == ERR_CF_CHAR)
                    return mw_validator_cfpf_caratteri_invalidi;
                else if (dummy == ERR_CF_CHECKSUM)
                    return mw_validator_cfpf_invalido;
            break;
            case 'cf':
                var dummy = mw_validatePIVA(valore) * mw_validateCF(valore);
                
                if (dummy != 0)
                    return mw_validator_cf_invalido;
            break;
            case 'cap':
                if (!mw_isValidCAP(valore))
                    return mw_validator_cap_invalido;
            break;
            case 'email':
                if (!mw_isValidEmail(valore))
                    return mw_validator_email_invalida;
            break;
            case 'digit':
                if (!mw_isValidDigitString(valore))
                    return mw_validator_digit_invalido;

                if (testaSoloIlTipo == false)
                {
                    var min = this.extractMinValue(node);
                    if (min != null)
                        if (parseInt(valore) < parseInt(min, 10))
                            return mw_validator_numero_piccolo;
                    
                    var max = this.extractMaxValue(node);
                    if (max != null)
                        if (parseInt(valore) > parseInt(max, 10))
                            return mw_validator_numero_grande;
                }
            break;
            case 'currency':
                if (!mw_isValidEuroCurrency(valore))
                    return mw_validator_currency_invalido;

                if (testaSoloIlTipo == false)
                {
                    var min = this.extractMinValue(node);
                    if (min != null)
                        if (parseFloat(valore) < parseFloat(min))
                            return mw_validator_numero_piccolo;
                    
                    var max = this.extractMaxValue(node);
                    if (max != null)
                        if (parseFloat(valore) > parseFloat(max))
                            return mw_validator_numero_grande;
                }
            break;
            case 'phone':
                if (!mw_isValidTelNumber(valore))
                    return mw_validator_telefono_invalido;
            break;
        }
    
    if (testaSoloIlTipo == true)
        return '';
    
    //test sul pattern
    var patt = this.extractPattern(node);
    if (patt != null)
    {
        var cippa = valore.match(new RegExp(patt));
        if (!(cippa != null && valore == cippa[0]))
            return mw_validator_pattern_invalido;
    }
    
    //test sulla lunghezza
    var siz = this.extractSize(node);
    if (siz != null && getRealLength(valore) > siz)
            return mw_validator_lunghezza_invalida;

    return '';
}

Validatore.prototype.extractType = function (node)
{
    return node.getAttribute('mw-type');
}

Validatore.prototype.extractBlocking = function (node)
{
    return (node.getAttribute('mw-non-blocking') != 'true');
}

Validatore.prototype.extractRequired = function (node)
{
    return (node.getAttribute('mw-required') == 'true');
}

Validatore.prototype.performToUpperCase = function (node)
{
    if (node.getAttribute('mw-to-uppercase') == 'true')
        node.value = node.value.toUpperCase();
}

Validatore.prototype.performToLowerCase = function (node)
{
    if (node.getAttribute('mw-to-lowercase') == 'true')
        node.value = node.value.toLowerCase();
}

Validatore.prototype.extractMinValue = function (node)
{
    return node.getAttribute('mw-min-value');
}

Validatore.prototype.extractMaxValue = function (node)
{
    return node.getAttribute('mw-max-value');
}

Validatore.prototype.extractPattern = function (node)
{
    return node.getAttribute('mw-pattern');
}

Validatore.prototype.extractSize = function (node)
{
    return node.getAttribute('mw-size');
}

Validatore.prototype.getByType = function (tipoMultiplo)
{
    switch (tipoMultiplo)
    
    {
        case 'RADIO':
            if (this.radioArray.length > 0)
                return this.radioArray;
            break;
        case 'CHECKBOX':
            if (this.checkboxArray.length > 0)
                return this.checkboxArray;
            break;
        default:
            alert ('Validatore.getByType. Tipo invalido: ' + tipoMultiplo);
    }

    var inputs = document.getElementsByTagName('input');
    
    for (var i=inputs.length; i-->0;)
        switch (inputs[i].type.toUpperCase())
        {
            case 'RADIO':
                this.radioArray.push(inputs[i]);
                break;
            case 'CHECKBOX':
                this.checkboxArray.push(inputs[i]);
                break;
        }
    
    switch (tipoMultiplo)
    {
        case 'RADIO':
            return this.radioArray;
        case 'CHECKBOX':
            return this.checkboxArray;
    }
}

/**
 * Prende una data (stringa formattata gg/mm/aaaa ) e la trasforma in oggetto contenente giorno, mese e anno, tre interi
 * Ritorna null se il formato e' non corretto. Puo' tornare date non valide (p.e. 32 gennaio).
 *
 * @deprecated Usare la funzione mw_analizzaData() presente
 * in mw_validateUtilities 
 */
Validatore.prototype.analizzaData = function(dataStr)
{
	var datePattern =/^\d{1,2}\/\d{1,2}\/((\d{2}){1,2})$/;
	var sogliaAnno = 20; // mettere un valore relativamentre all'anno corrente

   	if(!datePattern.test(dataStr))
   	{
   		return null;
   	}

	var sottostringhe = dataStr.split("/");

	var data = new Object();

	data.giorno = parseInt(sottostringhe[0], 10);
	data.mese = parseInt(sottostringhe[1], 10);
	data.anno = parseInt(sottostringhe[2], 10);

	if (data.anno < 100)
	{
		if (data.anno > sogliaAnno)
			data.anno = data.anno + 1900;
		else
			data.anno = data.anno + 2000;
	}

	return data;
}

/**
 * Prende un orario (stringa formattata hh.mm) e lo trasforma in oggetto contenente ora e minuti, due interi.
 * Ritorna null se il formato e' non corretto. Puo' tornare ore non valide (p.e. 25.97).
 */
Validatore.prototype.analizzaOrario = function(orarioStr)
{
	var orarioPattern =/^\d{1,2}\.\d{1,2}$/;

   	if(!orarioPattern.test(orarioStr))
   	{
   		return null;
   	}

	var sottostringhe = orarioStr.split(".");

	var orario = new Object();

	orario.ora = parseInt(sottostringhe[0], 10);
	orario.minuti = parseInt(sottostringhe[1], 10);

	return orario;
}

/**
 * Verifica che un oggetto data (giorno, mese, anno) contenga valori corretti per il giorno e il mese 
 * ritorna true se la data va bene, false se e' sbagliata (p.e. 30/2/2006)
 *
 * @deprecated Usare la funzione mw_verificaData() presente
 * in mw_validateUtilities 
 */ 
Validatore.prototype.verificaData = function(data)
{
	var giorniMesi = new Array(31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31);
	// anno bisesto anno funesto
	if (   ((data.anno % 4 == 0) && (data.anno % 100 != 0))    // sono bisestili gli anni divisibili per 4 ma non per 100 ...  
		|| ((data.anno % 400 == 0) && (data.anno % 1000 != 0)) // oppure se divisibili per 400 ma non per 1000 ...
		|| ((data.anno % 1000 == 0) && (data.anno % 4000 != 0))// ... infine se divisibile per 1000 ma non 4000 ( http://it.wikipedia.org/wiki/Anno_bisestile )
	   )
	{
		giorniMesi[1] = 29;
	}

	if ((data.mese < 1 || data.mese > 12) ||  							// se il mese non va bene
		(data.giorno == 0 || data.giorno > giorniMesi[data.mese - 1]))	// se il giorno non va bene
		return false;
	else
		return true;
}

/**
 * Verifica che un oggetto orario (ora, minuti) contenga valori corretti per l'ora e i minuti; 
 * ritorna true se l'orario va bene, false se e' sbagliato (p.e. 24.01 o 15.60)  
 */ 
Validatore.prototype.verificaOrario = function(orario)
{
	// Controlla i minuti: fuori dall'intervallo 0-59 sono
	// certamente sballati
    if ((orario.minuti < 0 || orario.minuti > 59))
    	return false;

	// L'ora compresa tra 0 e 23 va sempre bene
    if ((orario.ora >= 0 && orario.ora <= 23))
    	return true;
	
	// Le 24.00 sono accettabili
	if ((orario.ora == 24) && (orario.minuti == 0))
		return true;

	return false;
}

/**
 * Prende due date (stringhe fromattate gg/mm/aaaa ) e le confronta
 * Ritorna intero: < 0 se data1 < data2; > 0 se data1 > data2; 0 se uguali, null se una delle due non è valida
 */
Validatore.prototype.confrontaDate = function (dataStr1, dataStr2)
{
	var data1 = this.analizzaData(dataStr1);
	var data2 = this.analizzaData(dataStr2);

	if (data1 == null || data2 == null)
		return null;

	var compare = data1.anno - data2.anno;

	if (compare != 0)
		return compare;
	compare = data1.mese - data2.mese;

	if (compare != 0)
		return compare;

	compare = data1.giorno - data2.giorno;
	return compare;
}

/**
 * @deprecated Usare la funzione mw_normalizzaData() presente
 * in mw_validateUtilities
 */
Validatore.prototype.normalizzaData = function (dataStr)
{

	var data = this.analizzaData(dataStr);

	if (data == null || this.verificaData(data) == false)
		return null;

	var ret = data.giorno.toString();
	ret += 	"/";
	ret += data.mese.toString();
	ret += 	"/";
	ret += data.anno.toString();
	return ret;
}

Validatore.prototype.normalizzaOrario = function (orarioStr)
{
	var orario = this.analizzaOrario(orarioStr);

	if (orario == null || this.verificaOrario(orario) == false)
		return null;

	var ret = orario.ora.toString();
	ret += 	".";
	
	var minutiStr = orario.minuti.toString();
	
	// Piu' bellino cosi'
	if (minutiStr.length == 1)
		minutiStr = "0" + minutiStr;
	
	ret += minutiStr;
	return ret;
}

Validatore.prototype.controllaInputOrfani = function()
{
	var lista = "";
	//analizzo gli input
	if (this.rootEl != null)
	{
		var elementi = this.rootEl.getElementsByTagName('input');
		for (var i=0; i < elementi.length; i++)
		{    
		    elemento = elementi[i];
	
			if (document.getElementById("err_" + elemento.name) == undefined)
			{
			   var lab = elemento.parentNode;
			   if (lab.nodeName.toUpperCase() == 'LABEL')
			        lista += estraiTestoDaNodo(lab);
			   else
			   		lista += elemento.name;
			   lista +="\n";
			}
		}
		
		//analizzo le select
		elementi = this.rootEl.getElementsByTagName('select');
		for (var i=0; i < elementi.length; i++)
		{
		    elemento = elementi[i];
	
			if (document.getElementById("err_" + elemento.name) == undefined)
			{
			   var lab = elemento.parentNode;
			   if (lab.nodeName.toUpperCase() == 'LABEL')
			        lista += estraiTestoDaNodo(lab);
			   else
			   		lista += elemento.name;
			}
		   lista +="\n";
	
		}
		
		//analizzo le textarea
		elementi = this.rootEl.getElementsByTagName('textarea');
		for (var i=0; i < elementi.length; i++)
		{
		   	elemento = elementi[i];
	
			if (document.getElementById("err_" + elemento.name) == undefined)
			{
			   var lab = elemento.parentNode;
			   if (lab.nodeName.toUpperCase() == 'LABEL')
			        lista += estraiTestoDaNodo(lab);
			   else
			   		lista += elemento.name;
			}
		   lista +="\n";
	
		}
	}

	if (lista != "")
		alert ("Elementi senza etichetta di errore:\n" + lista);
}

/**
 * Funzione 'overloadabile' dalle istanze per controlli specifici dei vari form
 */
Validatore.prototype.extraCheckings = function()
{
	return null;
} 



// TODO spostare
function trim(inputString) {
   // Removes leading and trailing spaces from the passed string. Also removes
   // consecutive spaces and replaces it with one space. If something besides
   // a string is passed in (null, custom object, etc.) then return the input.
   if (typeof inputString != "string") { return inputString; }
   var retValue = inputString;
   var ch = retValue.substring(0, 1);
   while (ch == " " || ch=="\n") { // Check for spaces at the beginning of the string
      retValue = retValue.substring(1, retValue.length);
      ch = retValue.substring(0, 1);
   }
   ch = retValue.substring(retValue.length-1, retValue.length);
   while (ch == " " || ch=="\n") { // Check for spaces at the end of the string
      retValue = retValue.substring(0, retValue.length-1);
      ch = retValue.substring(retValue.length-1, retValue.length);
   }
   if (retValue == "&nbsp;")
       retValue = '';

   return retValue; // Return the trimmed string back to the user
}    

// TODO spostare
function estraiTestoDaNodo(nodo) {
    var testo = "";
    var labellini = nodo.childNodes;
    for (var i=0; i < labellini.length; i++)
        if (labellini[i].nodeType == 3)
            testo += labellini[i].nodeValue;
        else
            testo += ' ';
    
    return trim(testo);
}

function getRealLength (testo)
{
	var dummy = testo.length;
	var found = testo.indexOf('\n');
	
	while (found != -1)
	{
		dummy++;
		found = testo.indexOf('\n', found +1);
	}

    return dummy;
}



