jQuery.validator.addMethod("maxWords", function(value, element, params) { 
    return this.optional(element) || value.match(/\b\w+\b/g).length < params; 
}, "Please enter {0} words or less."); 
 
jQuery.validator.addMethod("minWords", function(value, element, params) { 
    return this.optional(element) || value.match(/\b\w+\b/g).length >= params; 
}, "Please enter at least {0} words."); 
 
jQuery.validator.addMethod("rangeWords", function(value, element, params) { 
    return this.optional(element) || value.match(/\b\w+\b/g).length >= params[0] && value.match(/bw+b/g).length < params[1]; 
}, "Please enter between {0} and {1} words.");


jQuery.validator.addMethod("letterswithbasicpunc", function(value, element) {
	return this.optional(element) || /^[a-z-.,()'\"\s]+$/i.test(value);
}, "Letters or punctuation only please");  

jQuery.validator.addMethod("alphanumeric", function(value, element) {
	return this.optional(element) || /^\w+$/i.test(value);
}, "Letters, numbers, spaces or underscores only please");  

jQuery.validator.addMethod("lettersonly", function(value, element) {
	return this.optional(element) || /^[a-z]+$/i.test(value);
}, "Letters only please"); 

jQuery.validator.addMethod("nowhitespace", function(value, element) {
	return this.optional(element) || /^\S+$/i.test(value);
}, "No white space please"); 

jQuery.validator.addMethod("ziprange", function(value, element) {
	return this.optional(element) || /^90[2-5]\d\{2}-\d{4}$/.test(value);
}, "Your ZIP-code must be in the range 902xx-xxxx to 905-xx-xxxx");

/**
* Return true, if the value is a valid vehicle identification number (VIN).
*
* Works with all kind of text inputs.
*
* @example <input type="text" size="20" name="VehicleID" class="{required:true,vinUS:true}" />
* @desc Declares a required input element whose value must be a valid vehicle identification number.
*
* @name jQuery.validator.methods.vinUS
* @type Boolean
* @cat Plugins/Validate/Methods
*/ 
jQuery.validator.addMethod(
	"vinUS",
	function(v){
		if (v.length != 17)
			return false;
		var i, n, d, f, cd, cdv;
		var LL    = ["A","B","C","D","E","F","G","H","J","K","L","M","N","P","R","S","T","U","V","W","X","Y","Z"];
		var VL    = [1,2,3,4,5,6,7,8,1,2,3,4,5,7,9,2,3,4,5,6,7,8,9];
		var FL    = [8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2];
		var rs    = 0;
		for(i = 0; i < 17; i++){
		    f = FL[i];
		    d = v.slice(i,i+1);
		    if(i == 8){
		        cdv = d;
		    }
		    if(!isNaN(d)){
		        d *= f;
		    }
		    else{
		        for(n = 0; n < LL.length; n++){
		            if(d.toUpperCase() === LL[n]){
		                d = VL[n];
		                d *= f;
		                if(isNaN(cdv) && n == 8){
		                    cdv = LL[n];
		                }
		                break;
		            }
		        }
		    }
		    rs += d;
		}
		cd = rs % 11;
		if(cd == 10){cd = "X";}
		if(cd == cdv){return true;}
		return false; 
	},
	"The specified vehicle identification number (VIN) is invalid."
);

/**
  * Return true, if the value is a valid date, also making this formal check dd/mm/yyyy.
  *
  * @example jQuery.validator.methods.date("01/01/1900")
  * @result true
  *
  * @example jQuery.validator.methods.date("01/13/1990")
  * @result false
  *
  * @example jQuery.validator.methods.date("01.01.1900")
  * @result false
  *
  * @example <input name="pippo" class="{dateITA:true}" />
  * @desc Declares an optional input element whose value must be a valid date.
  *
  * @name jQuery.validator.methods.dateITA
  * @type Boolean
  * @cat Plugins/Validate/Methods
  */
jQuery.validator.addMethod(
	"dateITA",
	function(value, element) {
		var check = false;
		var re = /^\d{1,2}\/\d{1,2}\/\d{4}$/
		if( re.test(value)){
			var adata = value.split('/');
			var gg = parseInt(adata[0],10);
			var mm = parseInt(adata[1],10);
			var aaaa = parseInt(adata[2],10);
			var xdata = new Date(aaaa,mm-1,gg);
			if ( ( xdata.getFullYear() == aaaa ) && ( xdata.getMonth () == mm - 1 ) && ( xdata.getDate() == gg ) )
				check = true;
			else
				check = false;
		} else
			check = false;
		return this.optional(element) || check;
	}, 
	"Inserisci una data corretta"
);

jQuery.validator.addMethod(
	"dateOld",
	function(value, element) {
		var check = false;
		var re = /^\d{1,2}\/\d{1,2}\/\d{4}$/
		if( re.test(value)){
			var adata = value.split('/');
			var gg = parseInt(adata[0],10);
			var mm = parseInt(adata[1],10);
			var aaaa = parseInt(adata[2],10);
			var xdata = new Date(aaaa,mm-1,gg);
			var today = new Date();
			if(today.getFullYear()-xdata.getFullYear()>16){
			    check = true;
			   }else if((today.getFullYear())-(xdata.getFullYear())==16){
			        //controllo il mese
			        if(today.getMonth()-xdata.getMonth() < 0){
			            check=false;
			        }else if (today.getMonth()-xdata.getMonth() > 0){
			            check=true;
			        }else{
    			        //controllo il giorno
    			        if(today.getDate()-xdata.getDate()>=0){
    			            check=true;
    			        }else{
    			            check=false;
    			        }
			        }
			   }else{
				check = false;
			   }
		} else
			check = false;
		return this.optional(element) || check;
	}, 
	"Inserisci una data superiore a 16 anni"
);

jQuery.validator.addMethod(
	"codiceFiscale",
	function(value, element){
        var validi, i, s, set1, set2, setpari, setdisp;
        if( value == '' )  return true;
        value = value.toUpperCase();
        if( value.length != 16 )
            return false;
        validi = "ABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789";
        for( i = 0; i < 16; i++ ){
            if( validi.indexOf( value.charAt(i) ) == -1 )
                return false;
        }
        set1 = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        set2 = "ABCDEFGHIJABCDEFGHIJKLMNOPQRSTUVWXYZ";
        setpari = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
        setdisp = "BAKPLCQDREVOSFTGUHMINJWZYX";
        s = 0;
        for( i = 1; i <= 13; i += 2 )
            s += setpari.indexOf( set2.charAt( set1.indexOf( value.charAt(i) )));
        for( i = 0; i <= 14; i += 2 )
            s += setdisp.indexOf( set2.charAt( set1.indexOf( value.charAt(i) )));
        if( s%26 != value.charCodeAt(15)-'A'.charCodeAt(0) )
            return false;
        return true;
    }
	, 
	"Codice Fiscale non valido"
);


jQuery.validator.addMethod(
	"after4days",
	function(value, element){
	    var re = /^\d{1,2}\/\d{1,2}\/\d{4}$/
	    if( re.test(value)){
            var adata = value.split('/');
	        var gg = parseInt(adata[0],10);
	        var mm = parseInt(adata[1],10);
	        var aaaa = parseInt(adata[2],10);
	        var xdata = new Date(aaaa,mm-1,gg);
	        var minimumDate = new Date();
	        var dayAdded=0;
	        while(dayAdded<4){
	            minimumDate.setDate(minimumDate.getDate()+1);
	            var day= minimumDate.getDay();
	            var monthday=minimumDate.getDate();
	            var month=minimumDate.getMonth();
	            var year=minimumDate.getFullYear();
	            
	            if(!(day==0 || day==6 ||  
	                (monthday == 1 && month == 0) ||
	                (monthday == 6 && month == 0) ||
                    (monthday == 25 && month == 3) ||
                    (monthday == 1 && month == 4) ||
                    (monthday == 2 && month == 5) ||                  
                    (monthday == 15 && month == 7) ||
                    (monthday == 1 && month == 10) ||
                    (monthday == 8 && month == 11) ||
                    (monthday == 25 && month == 11) ||
                    (monthday == 26 && month == 11) ||
                    (year == 2011 && month == 3 && monthday == 25) ||(year == 2012 && month == 3 && monthday == 9) ||(year == 2013 && month == 3 && monthday == 1) ||(year == 2014 && month == 3 && monthday == 21) ||(year == 2015 && month == 3 && monthday == 6) ||
                    (year == 2016 && month == 2 && monthday == 28) ||(year == 2017 && month == 3 && monthday == 17) ||(year == 2018 && month == 3 && monthday == 2) ||(year == 2019 && month == 3 && monthday == 22) ||(year == 2020 && month == 3 && monthday == 13) ||
                    (year == 2021 && month == 3 && monthday == 5) ||(year == 2022 && month == 3 && monthday == 18) ||(year == 2023 && month == 3 && monthday == 10) ||(year == 2024 && month == 3 && monthday == 1) ||(year == 2025 && month == 3 && monthday == 21) ||
                    (year == 2026 && month == 3 && monthday == 6) ||(year == 2027 && month == 2 && monthday == 29) ||(year == 2028 && month == 3 && monthday == 17) ||(year == 2029 && month == 3 && monthday == 2) ||(year == 2030 && month == 3 && monthday == 22) ||
                    (year == 2031 && month == 3 && monthday == 14) ||(year == 2032 && month == 2 && monthday == 29) ||(year == 2033 && month == 3 && monthday == 18) ||(year == 2034 && month == 3 && monthday == 10) ||(year == 2035 && month == 2 && monthday == 26) ||
                    (year == 2036 && month == 3 && monthday == 14) ||(year == 2037 && month == 3 && monthday == 6) ||(year == 2038 && month == 3 && monthday == 26) ||(year == 2039 && month == 3 && monthday == 11) ||(year == 2040 && month == 3 && monthday == 2) ||
                    (year == 2041 && month == 3 && monthday == 22) ||(year == 2042 && month == 3 && monthday == 7) ||(year == 2043 && month == 2 && monthday == 30) ||(year == 2044 && month == 3 && monthday == 18) ||(year == 2045 && month == 3 && monthday == 10) ||
                    (year == 2046 && month == 2 && monthday == 26) ||(year == 2047 && month == 3 && monthday == 15) ||(year == 2048 && month == 3 && monthday == 6) ||(year == 2049 && month == 3 && monthday == 19) ||(year == 2050 && month == 3 && monthday == 11)
	              ))
	                dayAdded+=1;	            
	        }	        
	        
	        var oneDay = 1000*60*60*24;
            var difference = Math.ceil((xdata.getTime() - minimumDate.getTime()) / oneDay);
            if(difference>=0)
                return true;
            else return false;
                    
	    } else 
	        return false;
    }
	, 
	"La data deve essere di almeno 4 giorni lavorativi dopo oggi"
);

jQuery.validator.addMethod(
	"textareaMaxlength4000",
	function(value, element){
	    if (value.length <=4000)
	        return true;
	    else
	        return false;
    }
	, 
	"Inserire al massimo 4000 caratteri"
);
jQuery.validator.addMethod(
	"textareaMaxlength100",
	function(value, element){
	    if (value.length <=100)
	        return true;
	    else
	        return false;
    }
	, 
	"Inserire al massimo 100 caratteri"
);

jQuery.validator.addMethod(
	"textareaMinlength100",
	function(value, element){
	    if (value.length >=100)
	        return true;
	    else
	        return false;
    }
	, 
	"Inserire almeno 100 caratteri"
);

jQuery.validator.addMethod(
	"durataMesiTirocinio",
	function(value, element){
	        var minMesiObject=document.getElementById('durata_min_tirocinio_mesi');
	        var minMesi=minMesiObject.innerHTML;
	        var selectObject=document.getElementById('durata_tirocinio_mesi');
	        var mesi=selectObject.innerHTML;
	        var inizio=document.getElementById('data_inizio_tir').value;
	        var fine=document.getElementById('data_fine_tir').value;
	        if(inizio=="")
	            return false;
	        var dataInizioSplit = inizio.split('/');
	        var ggi = parseInt(dataInizioSplit[0],10);
	        var mmi = parseInt(dataInizioSplit[1],10);
	        var aaaai = parseInt(dataInizioSplit[2],10);
	        var dataInizio = new Date(aaaai,mmi-1,ggi);
	        
	        var dataFineSplit = fine.split('/');
	        var ggf = parseInt(dataFineSplit[0],10);
	        var mmf = parseInt(dataFineSplit[1],10);
	        var aaaaf = parseInt(dataFineSplit[2],10);
	        var dataFine = new Date(aaaaf,mmf-1,ggf);
	        
	        if(dataFine<=dataInizio)
	            return false;
	        
	        var meseInizio=dataInizio.getMonth();
	        var meseFine=dataFine.getMonth();
	        var annoInizio=dataInizio.getFullYear();
	        var annoFine=dataFine.getFullYear();
	        
	        var diffAnni = annoFine - annoInizio;
		    var diffMesi = 0;
		    if (meseInizio <= meseFine) {
			    diffMesi = meseFine - meseInizio;
		    } 
		    else{
			    // se il mese di arrivo è precedente a quello di inizio allora calcolo la differenza in mesi come il mese di arrivo + 12 (mesi in un'anno) - mese di inizio
			    var tempDiff = 12 - meseInizio;
			    diffMesi = tempDiff + meseFine;
			    if (diffAnni != 0) {
				    // se gli anni sono diversi devo sottrarre 1 alla loro differenza perchè un anno lo uso per il calcolo dei mesi di differenza
				    diffAnni -= 1;
			    }
		    }
    		
		    var numeroMesiFinale = 0;
		    if (diffMesi != 0) {
			    numeroMesiFinale = diffAnni * 12 + diffMesi;
		    }
		    else{
			    if (diffAnni != 0) {
				    numeroMesiFinale = diffAnni * 12;
			    }
		    }
		    
		    if(numeroMesiFinale<minMesi)
			return false;
		    else if(numeroMesiFinale==minMesi){
			if(ggf>=ggi)
			    return true;
			else return false;
		    }else if(numeroMesiFinale>mesi)
			return false;
		    else if(numeroMesiFinale==mesi){
			if(ggi>=ggf)
			    return true
			else return false;
		    }else
		        return true;
    }
	, 
	"Inserire un periodo valido entro il numero di mesi previsti"
);

jQuery.validator.addMethod(
	"durataMesiTirocinioAdmin",
	function(value, element){
		var minMesiObject=document.getElementById('durata_min_tirocinio_mesi');
	        var minMesi=minMesiObject.innerHTML;
	        var selectObject=document.getElementById('durata_tirocinio_mesi');
	        var mesi=selectObject.innerHTML;
	        var inizio=document.getElementById('data_inizio_tir').value;
	        var fine=document.getElementById('data_fine_tir').value;
	        if(inizio=="")
	            return false;
	        var dataInizioSplit = inizio.split('-');
	        var ggi = parseInt(dataInizioSplit[0],10);
	        var mmi = dataInizioSplit[1];
	        var aaaai = "20"+parseInt(dataInizioSplit[2],10);
	        var dataInizio = new Date(aaaai,getMonthNumber(mmi),ggi);
	        
	        var dataFineSplit = fine.split('-');
	        var ggf = parseInt(dataFineSplit[0],10);
	        var mmf = dataFineSplit[1];
	        var aaaaf = "20"+parseInt(dataFineSplit[2],10);
	        var dataFine = new Date(aaaaf,getMonthNumber(mmf),ggf);
	        
	        if(dataFine<=dataInizio)
	            return false;
	        
	        var meseInizio=dataInizio.getMonth();
	        var meseFine=dataFine.getMonth();
	        var annoInizio=dataInizio.getFullYear();
	        var annoFine=dataFine.getFullYear();
	        
	        var diffAnni = annoFine - annoInizio;
		    var diffMesi = 0;
		    if (meseInizio <= meseFine) {
			    diffMesi = meseFine - meseInizio;
		    } 
		    else{
			    // se il mese di arrivo è precedente a quello di inizio allora calcolo la differenza in mesi come il mese di arrivo + 12 (mesi in un'anno) - mese di inizio
			    var tempDiff = 12 - meseInizio;
			    diffMesi = tempDiff + meseFine;
			    if (diffAnni != 0) {
				    // se gli anni sono diversi devo sottrarre 1 alla loro differenza perchè un anno lo uso per il calcolo dei mesi di differenza
				    diffAnni -= 1;
			    }
		    }
    		
		    var numeroMesiFinale = 0;
		    if (diffMesi != 0) {
			    numeroMesiFinale = diffAnni * 12 + diffMesi;
		    }
		    else{
			    if (diffAnni != 0) {
				    numeroMesiFinale = diffAnni * 12;
			    }
		    }
		    
		    if(numeroMesiFinale<minMesi)
			return false;
		    else if(numeroMesiFinale==minMesi){
			if(ggf>=ggi)
			    return true;
			else return false;
		    }else if(numeroMesiFinale>mesi)
			return false;
		    else if(numeroMesiFinale==mesi){
			if(ggi>=ggf)
			    return true
			else return false;
		    }else
		        return true;
    }
	, 
	"Inserire un periodo valido entro il numero di mesi previsti"
);

function getMonthNumber(month){
    if(month=="GEN" || month=="gen" || month=="JAN" || month=="jan"){
        return 0;
    }else if(month=="FEB" || month=="feb"){
        return 1;
    }else if(month=="MAR" || month=="mar"){
        return 2;
    }else if(month=="APR" || month=="apr"){
        return 3;
    }else if(month=="MAG" || month=="mag" || month=="MAY" || month=="may"){
        return 4;
    }else if(month=="GIU" || month=="giu" || month=="JUN" || month=="jun"){
        return 5;
    }else if(month=="LUG" || month=="lug" || month=="JUL" || month=="jul"){
        return 6;
    }else if(month=="AGO" || month=="ago" || month=="AUG" || month=="aug"){
        return 7;
    }else if(month=="SET" || month=="set" || month=="SEP" || month=="sep"){
        return 8;
    }else if(month=="OTT" || month=="ott" || month=="OCT" || month=="oct"){
        return 9;
    }else if(month=="NOV" || month=="nov"){
        return 10;
    }else if(month=="DIC" || month=="dic" || month=="DEC" || month=="dec"){
        return 11;
    }
}

jQuery.validator.addMethod(
	"orariTirocinante",
	function(value, element){
	
	        var inizioMattinaElement=document.getElementById('ora_inizio_attivita_mattina');
	        var fineMattinaElement=document.getElementById('ora_fine_attivita_mattina');
	        var inizioPomeriggioElement=document.getElementById('ora_inizio_attivita_pomeriggio');
	        var finePomeriggioElement=document.getElementById('ora_fine_attivita_pomeriggio');
	
	        var inizioMattina=inizioMattinaElement.value;
	        var fineMattina=fineMattinaElement.value;
	        var inizioPomeriggio=inizioPomeriggioElement.value;
	        var finePomeriggio=finePomeriggioElement.value;
	        
	        var inizioMattinaSplit=inizioMattina.split(':');
	        var oraInizioMattina=inizioMattinaSplit[0];
	        var minutiInizioMattina=inizioMattinaSplit[1];
	        
	        var fineMattinaSplit=fineMattina.split(':');
	        var oraFineMattina=fineMattinaSplit[0];
	        var minutiFineMattina=fineMattinaSplit[1];
	        
	        var inizioPomeriggioSplit=inizioPomeriggio.split(':');
	        var oraInizioPomeriggio=inizioPomeriggioSplit[0];
	        var minutiInizioPomeriggio=inizioPomeriggioSplit[1];
	        
	        var finePomeriggioSplit=finePomeriggio.split(':');
	        var oraFinePomeriggio=finePomeriggioSplit[0];
	        var minutiFinePomeriggio=finePomeriggioSplit[1];
	        
	        if((oraInizioMattina == "--" && oraFineMattina != "--") ||
	           (oraInizioMattina != "--" && oraFineMattina == "--") ||
	           (oraInizioPomeriggio == "--" && oraFinePomeriggio != "--") ||
	           (oraInizioPomeriggio != "--" && oraFinePomeriggio == "--") ||	           
	           (oraInizioMattina == "--" && oraFineMattina == "--" && oraInizioPomeriggio == "--" && oraFinePomeriggio == "--")
	        ){  
	            return false;
	        }
	            
	            
	        var mattinaIndefinita = oraInizioMattina == "--";
	        var pomeriggioIndefinito = oraInizioPomeriggio == "--";
	        
	        var dateInizioMattina=new Date();
	        var dateFineMattina=new Date();
	        var dateInizioPomeriggio=new Date();
	        var dateFinePomeriggio=new Date();
	        if(!mattinaIndefinita){	            
	            dateInizioMattina.setHours(oraInizioMattina);
	            dateInizioMattina.setMinutes(minutiInizioMattina);	            
	            dateFineMattina.setHours(oraFineMattina);
	            dateFineMattina.setMinutes(minutiFineMattina);
	        }
	        if(!pomeriggioIndefinito){	            
	            dateInizioPomeriggio.setHours(oraInizioPomeriggio);
	            dateInizioPomeriggio.setMinutes(minutiInizioPomeriggio);	            
	            dateFinePomeriggio.setHours(oraFinePomeriggio);
	            dateFinePomeriggio.setMinutes(minutiFinePomeriggio);
	        }
	        
	        if(mattinaIndefinita){
	            return dateInizioPomeriggio < dateFinePomeriggio;
	        }else if(pomeriggioIndefinito){
	            return dateInizioMattina < dateFineMattina;
	        }else{
	            return dateInizioMattina < dateFineMattina &&
	                dateFineMattina < dateInizioPomeriggio &&
	                dateInizioPomeriggio < dateFinePomeriggio;
	        }
	        
	    
    }
	, 
	"Orari tirocinante non validi<br>(non inserire orari sovrapposti, oppure orario fine mattina <br>uguale a orario inizio pomeriggio)"
);




/**
 * matches US phone number format 
 * 
 * where the area code may not start with 1 and the prefix may not start with 1 
 * allows '-' or ' ' as a separator and allows parens around area code 
 * some people may want to put a '1' in front of their number 
 * 
 * 1(212)-999-2345
 * or
 * 212 999 2344
 * or
 * 212-999-0983
 * 
 * but not
 * 111-123-5434
 * and not
 * 212 123 4567
 */
jQuery.validator.addMethod("phone", function(phone_number, element) {
    phone_number = phone_number.replace(/\s+/g, ""); 
	return this.optional(element) || phone_number.length > 9 &&
		phone_number.match(/^(1-?)?(\([2-9]\d{2}\)|[2-9]\d{2})-?[2-9]\d{2}-?\d{4}$/);
}, "Please specify a valid phone number");

// TODO check if value starts with <, otherwise don't try stripping anything
jQuery.validator.addMethod("strippedminlength", function(value, element, param) {
	return jQuery(value).text().length >= param;
}, jQuery.format("Please enter at least {0} characters"));

// same as email, but TLD is optional
jQuery.validator.addMethod("email2", function(value, element, param) {
	return this.optional(element) || /^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i.test(value); 
}, jQuery.validator.messages.email);

// same as url, but TLD is optional
jQuery.validator.addMethod("url2", function(value, element, param) {
	return this.optional(element) || /^(https?|ftp):\/\/(((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:)*@)?(((\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5])\.(\d|[1-9]\d|1\d\d|2[0-4]\d|25[0-5]))|((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)*(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?)(:\d*)?)(\/((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)+(\/(([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)*)*)?)?(\?((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|[\uE000-\uF8FF]|\/|\?)*)?(\#((([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(%[\da-f]{2})|[!\$&'\(\)\*\+,;=]|:|@)|\/|\?)*)?$/i.test(value); 
}, jQuery.validator.messages.url);

// same as url, but TLD is optional
jQuery.validator.addMethod("numberITA", function(value, element, param) {
	return this.optional(element) || /^-?\d+(?:(\.|,)\d{1,2})?$/.test(value);
}, jQuery.validator.messages.number);


