// ----------------------------------------------------
//
// formChecker: oggetto per gestione controlli su form
//
// V 0.5
// ----------------------------------------------------

// definizioni

/**
 * Funzione generica per trovare un oggetto in pagina HTML
 * @does Nothing
 * @return Un oggetto
 * @param n Nome dell'oggetto
 * @param d Nome del documento (opzionale)
 */
function MM_findObj(n, d) { //v4.01
  var p,i,x;  if(!d) d=document; if((p=n.indexOf("?"))>0&&parent.frames.length) {
    d=parent.frames[n.substring(p+1)].document; n=n.substring(0,p);}
  if(!(x=d[n])&&d.all) x=d.all[n]; for (i=0;!x&&i<d.forms.length;i++) x=d.forms[i][n];
  for(i=0;!x&&d.layers&&i<d.layers.length;i++) x=MM_findObj(n,d.layers[i].document);
  if(!x && d.getElementById) x=d.getElementById(n); return x;
}

/**
 * Abbozzo di funzione di evidenziazione componente
 */
function componentHighlight(obj) {
		obj.style.borderStyle = "dashed";
		obj.style.borderColor = "#FF0000";
}
 
var fc_messages_it = new Array();
fc_messages_it["isnull"] = "il campo %1 non può essere vuoto";
fc_messages_it["isdate"] = "il campo %1 non contiene una data valida (GG/MM/AAAA)";
fc_messages_it["isemail"] = "il campo \"%1\" non contiene una E-mail valida";
fc_messages_it["ischecked"] = "Si deve scegliere un valore per il campo %1";
fc_messages_it["isnumeric"] = "Il campo %1 può contenere solo cifre";
fc_messages_it["isofsize"] = "Il campo %1 deve essere almeno %2 caratteri";
fc_messages_it["isequal"] = "I campi %1 devono essere uguali";
fc_messages_it["isequalnotnull"] = "I campi %1 devono essere uguali e non vuoti";
fc_messages_it["matchregexp"] = "Il valore del campo %1 non è esatto"; 

var fc_messages_uk = new Array();
fc_messages_uk["isnull"] = "Field %1 can't be empty";
fc_messages_uk["isdate"] = "Field %1 is not a valid date (DD/MM/YYYY)";
fc_messages_uk["isemail"] = "Field %1 is not a valid E-mail";
fc_messages_uk["ischecked"] = "You must choose a value for field %1";
fc_messages_uk["isnumeric"] = "Field %1 must be a number";
fc_messages_uk["isofsize"] = "Field %1 must be at least %2 char";
fc_messages_uk["isequal"] = "Fields %1 must be equal";
fc_messages_uk["isequalnotnull"] = "Fields %1 must be equal and not empty";
fc_messages_it["matchregexp"] = "Il valore del campo %1 non è esatto";

/**
 * Classe formChecker  -
 * <A href="../formChecker.txt">Release notes</A> 
 * @constructor
 * @param formname	Nome della form
 * @param lang		lingua (it,uk per ora i soli valori disponibili)
 * @param setfocus	indica se va fatto il posizionamento sul primo errore (true/false)
 */
function formChecker (formname,lang,setfocus) {
	var c;
	// inizializzazione array interni all'oggetto
	this.checks = new Array();
	this.errors = new Array();
	this.formname = formname;
	this.highlight = false; // highligh disabilitato
	// impostazione array dei messaggi in base alla lingua	
	if (lang =="it") {
		this.messages = fc_messages_it;
	} else {
		this.messages = fc_messages_uk;
	}
	
	// indica se si deve fare il posizionamento dopo visualizzazione
	// errori
	
	this.setfocus = setfocus;
}

/**
 * Array di messaggi in Italiano
 */
formChecker.prototype.fc_messages_it = fc_messages_it;
/**
 * Array di messaggi in Inglese
 */
formChecker.prototype.fc_messages_uk = fc_messages_uk;

/**
 * Funzione che imposta il focus
 * @param c Nome (nomi) del componente su cui puntare il focus, se sono più di uno
 * 			usa il primo (fa anche un check di esistenza componente)
 */
function formChecker_setFocus(c) {
	//alert(c.name);
	if (c.name.indexOf(',') > 0) {
		var oa = c.name.split(',');
		obj = MM_findObj(oa[0]);
		obj.focus();
	} else {
		obj = MM_findObj(c.name);
		if (obj) { 
				obj.focus();
				//componentHighlight(obj);
		}
	}
}
	
/**
 * Funzione base di aggiunta controllo
 * @param name	Nome (nomi) del componente su cui fare il controllo
 * @param label	Label da usare come riferimento nel messaggio di errore
 * @param type	parametro base che stabilisce il tipo di controllo
 * @param args	argomenti aggiuntivi (possono essere di vario tipo a seconda del
 * 				parametro type
 * @param required	indica se il controllo è facoltativo o obbligatorio (true/false)
 */
function formChecker_add(name,label,type,args,required) {
	this.checks.push(new formCheck(this,name,label,type,args,required))
	return;
	}

/**
 * Esegue il check effettivo della form
  */
function formChecker_validate() {
	//alert("validate");
	var i;
	this.errors = new Array();
	//alert(this.checks.length);
	for (i = 0; i < this.checks.length; i ++) {
		this.checks[i].validate(this);
	}
	//alert(this.errors.length);
	if (this.errors.length > 0) {
		this.displayErrors(this.errors);
		if (this.setfocus) {
			this.setFocus(this.errors[0]);
		}
		i = false;
	} else {
		i = true;
	}
	//alert(i);
	return(i);
}

/**
 * Crea il singolo messaggio di errore
 * @param e	oggetto formError
 */
function formChecker_createMessage(e) {
	var c,m,t,re;
	c = e.component;
	m = e.message;
	//t = sprintf(message,);
	re = /%1/;
	m = m.replace(re, c.label);
	return(m);
}


/**
 * Mostra il messaggio di errore (per ora in un alert)
 */
function formChecker_displayErrors() {
	var i,msg = "";
	for (i = 0; i < this.errors.length; i++) {
		msg = msg + this.createMessage(this.errors[i]) + "\n";
	}
	
	alert(msg);
}

//----------------------------------------------------------------------------
// assegnazione metodi oggetto formChecker
//----------------------------------------------------------------------------

formChecker.prototype.setFocus = formChecker_setFocus;
formChecker.prototype.add = formChecker_add;
formChecker.prototype.validate = formChecker_validate;
formChecker.prototype.createMessage = formChecker_createMessage;
formChecker.prototype.displayErrors = formChecker_displayErrors;


//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------


/**
 * Classe formCheck - rappresenta il singolo controllo da effettuare sulla 
 * form  
 * <pre>
 * </pre>
 * @constructor
 * @param args	argomenti aggiuntivi che possono essere di varia natura
 * @param f 	nome del form su cui va effettuato il check
 * @param name	nome dell'elemento o elementi separati da "," coinvolti nel controllo
 * @param label	etichetta che viene mostrata nel messaggio di errore come riferimento al campo
 * @param type	il tipo fondamentale di controllo
 * @with What is that
 */
function formCheck (f,name,label,type,args,required) {
	this.name = name;
	this.label = label;
	this.type = type;
	this.args = args;
	this.fc = f;
	this.required = required;
	//alert(parent.formname);
	}

/**
 * Metodo base dell'oggetto, chiede di effettuare il controllo
 * @return true/false
 * @param f indica l'istanza di classe formChecker da utilizzare
 */
function formCheck_validate (f) {
	//alert(this.type);
	var n = f.errors.length;
	//alert(n);
	switch (this.type) {
		case "isnull": 
			if(this.isNull()) 	f.errors.push(new formError(this,f.messages["isnull"],null));
			break;
		case "isdate": 
			if(this.isDate()) 	f.errors.push(new formError(this,f.messages["isdate"],null));
			break;
		case "isemail":
			if (this.required) {
				if(this.isEmail()) 	f.errors.push(new formError(this,f.messages["isemail"],null));
			} else {
				if(!this.isNull() && (this.isEmail())) 	f.errors.push(new formError(this,f.messages["isemail"],null));
			}
			break;
		case "ischecked": 
			if(!this.isChecked()) 	f.errors.push(new formError(this,f.messages["ischecked"],null));
			break;
		case "isnumeric": 
			if (this.required) {
				if(!this.isNumeric()) 	f.errors.push(new formError(this,f.messages["isnumeric"],null));
			} else {
				if(!this.isNull() && !this.isNumeric()) 	f.errors.push(new formError(this,f.messages["isnumeric"],null));
			}
			break;
		case "isequal": 
			if(!this.isEqual(false)) 	f.errors.push(new formError(this,f.messages["isequal"],null));
			break;
		case "isequalnotnull": 
			if(!this.isEqual(true)) 	f.errors.push(new formError(this,f.messages["isequalnotnull"],null));
			break;
		case "isboxchecked": 
			if(!this.isBoxChecked()) 	f.errors.push(new formError(this,f.messages["ischecked"],null));
			break;
		case "matchregexp": 
			if(!this.matchRegExp()) 	f.errors.push(new formError(this,f.messages["matchregexp"],null));
			break;
		default:
			break;
	}
	if (f.errors.length == n && f.highlight) {
			obj = MM_findObj(this.name);
			obj.style.borderStyle = "solid";
			obj.style.borderColor = "#444444";
	}
	return(true);	
}

function formCheck_isNull() {
	var obj = MM_findObj(this.name);
	if (obj.value == "" || obj.value == undefined) {
		return(true);
	} else {
		return(false);
	}
}

function formCheck_isString() {
	return;
}

function formCheck_isDate() {
	var obj = MM_findObj(this.name);
	if (isValidDate(obj.value)) {
		return(false);
	} else {
		return(true);
	}
}

function formCheck_isEmail() {
	var obj = MM_findObj(this.name);
	if (isValidEmail(obj.value)) {
		return(false);
	} else {
		return(true);
	}
}

function formCheck_isChecked() {
	var obj = MM_findObj(this.name);
	var ct = 0;
	var retval = false;
	while (obj[ct]) { 		// cicla tra tutti i sottocomponenti
		if (obj[ct].checked) {
			retval = true;
		}
		//alert(obj[ct].checked);
		ct++;
	}
	return(retval);
}

function formCheck_isBoxChecked() {
	//alert(this.fc.formname + " " +this.name);
	var obj = MM_findObj(this.fc.formname);
	
	var ct = 0;
	var retval = false;
	while (obj.elements[ct]) { 		// cicla tra tutti i sottocomponenti
			if (obj.elements[ct].type == "checkbox") {
				//alert(obj.elements[ct].name);
				if (obj.elements[ct].name.toString().indexOf(this.name) == 0) {
					//alert("checked starts");
					if (obj.elements[ct].checked) {
						retval = true;
					}
				}
			}
		
		//alert(obj[ct].checked);
		ct++;
	}
	return(retval);
}

/**
 * Funzione di test per vedere se un campo è numerico
 * @return true/false
 */
function formCheck_isNumeric() {
	var obj = MM_findObj(this.name);
	if (isNumeric(obj.value)) {
		return(true);
	} else {
		return(false);
	}
}

/**
 * Funzione di test per vedere se un campo è uguale ad un valore
 * o se due campi sono uguali
  * @return true/false
 * @param flag indica se l'uguaglianza tra due valori comprende anche valore nullo
 */
function formCheck_isEqual(flag) {
	if (this.name.indexOf(',') > 0) {
		var oa = this.name.split(",");
		if (oa.length == 2) {
			var obj1 = MM_findObj(oa[0]);
			var obj2 = MM_findObj(oa[1]);
			//alert(obj1.name.value + " " + obj2.name.value);
			if (flag) {
				condition =  (obj1.value) && (obj2.value);
			} else {
				condition = true;
			}
			return(obj1.value == obj2.value && condition);
		} else {
			alert("non implementato");
			return(true);
		}
	} else {
		var obj = MM_findObj(this.name);
		return(obj.value == this.args);
		}
}

/**
 * Funzione di test per vedere se un campo soddisfa una Regular Expression
  * @return true/false
 * @has Not a single thing
 */
function formCheck_matchRegExp() {
	var obj = MM_findObj(this.name);
	if (this.args.test(obj.value)) {
		return(true);
	} else {
		return(false);
	}
}
	
/**
 * Funzione di test per vedere se un campo se un campo è un Codice Fiscale
 * <B>DA IMPLEMENTARE</B>
 * @return true/false
 */
function formCheck_isCF() {	// da implementare
	return(true);
	}

/**
 * Funzione di test per vedere se un campo è in un intervallo di date
 * <B>DA IMPLEMENTARE</B>
 * @return true/false
 */
function formCheck_isDateInRange() {
	var dates = new Array();
	dates = this.args.split("|");		
	return;
	}

//----------------------------------------------------------------------------
// assegnazione dei metodi di formCheck
//----------------------------------------------------------------------------

formCheck.prototype.isNull = formCheck_isNull;
formCheck.prototype.isDate = formCheck_isDate;
formCheck.prototype.isDateInRange = formCheck_isDateInRange;
formCheck.prototype.isString = formCheck_isString;
formCheck.prototype.isEmail = formCheck_isEmail;
formCheck.prototype.isChecked = formCheck_isChecked;
formCheck.prototype.isBoxChecked = formCheck_isBoxChecked;
formCheck.prototype.isNumeric = formCheck_isNumeric;
formCheck.prototype.isEqual = formCheck_isEqual;
formCheck.prototype.matchRegExp = formCheck_matchRegExp;
formCheck.prototype.validate = formCheck_validate;
formCheck.prototype.isCF = formCheck_isCF;


/**
 * Classe formError  
 * classe di descrizione di singolo errore - tiene un riferimento al controllo
 * che lo ha generato
 * @constructor
 * @with What is that
 */
function formError(c,message,formatMethod) {
	this.component = c;
	this.name = c.name;
	this.message = message;
	this.formatMethod = formatMethod;
	//alert(c.name);
	obj = MM_findObj(c.name);
	//alert(c.fc.highlight);
	if (obj && (obj.type == "text" || obj.type == "password") && c.fc.highlight) {
		componentHighlight(obj);
	}
}

function formError_setMessage(m) {
	this.message = message;
}

formError.prototype.setMessage = formError_setMessage;

//----------------------------------------------------------------------------
// funzioni varie di supporto 
//----------------------------------------------------------------------------

function isValidEmail(email) {
	//alert(email);
	var str = email;
	if(email == "") return (false);
	if (window.RegExp) {
		var reg1str = "(@.*@)|(\\.\\.)|(@\\.)|(\\.@)|(^\\.)";
		var reg2str = "^.+\\@(\\[?)[a-zA-Z0-9\\-\\.]+\\.([a-zA-Z]{2,3}|[0-9]{1,3})(\\]?)$";
		var reg1 = new RegExp(reg1str);
		var reg2 = new RegExp(reg2str);
		if (!reg1.test(str) && reg2.test(str))  return true;
		return false;
	} else {
		//alert("no RegExp");
		if(str.indexOf("@") >= 0) return true;
		return false;
	}
}

function isValidDate( strValue ) {
	var objRegExp = /^\d{1,2}(\-|\/|\.)\d{1,2}\1(\d{4}|\d{2})$/
	
	if(!objRegExp.test(strValue))
		return false;
	else {
		var t = strValue;
		var tre = /\d/g;
		t = strValue.replace(tre,"");
		
		var strSeparator = t.substring(1,2)
		var arrayDate = strValue.split(strSeparator);
		var arrayLookup = { '01' : 31,'1' : 31,'03' : 31,'3' : 31, '4' : 30,'04' : 30,'05' : 31,'5' : 31,'06' : 30,'6' : 30,'07' : 31,'7' : 31, '08' : 31,'8' : 31,'09' : 30,'9' : 30,'10' : 31,'11' : 30,'12' : 31}
		var intDay = parseInt(arrayDate[0]);
		
		if(arrayDate[1] < 12 && arrayLookup[arrayDate[1]] != null) {
			if(intDay <= arrayLookup[arrayDate[1]] && intDay != 0)
				return true;
		}
		
		var intYear = parseInt(arrayDate[2]);
		var intMonth = parseInt(arrayDate[1]);
		if( ((intYear % 4 == 0 && intDay <= 29) || (intYear % 4 != 0 && intDay <=28)) && intDay !=0)
			return true;
	}
	return false;
}

function  isNumeric( strValue ) { // USA
	
	if (strValue == undefined) return false;
	var objRegExp  =  /(^-?\d\d*\.\d*$)|(^-?\d\d*$)|(^-?\.\d\d*$)/;
	return objRegExp.test(strValue);
}

