/**
 * $ jQuery Form Validation
 * Version 1.4.20 (2008-09-05)
 *
 * Copyright (c) 2008 Flink BV - www.flink.nl
 */


/************************************************************************************************

ENABLE VALIDATION:

		Enable validation by using:

			$.validatorEnable(object Options, object ErrorMessages)


		Examples:

			All forms on load : 		$('form').validatorEnable();
			One specific form :			$('form#frm_reg').validatorEnable();
			Specific options :			$('form#frm_reg').validatorEnable({hdlCallback: setPage, showTooltip: true});
			Custom error messages :		$('form#frm_reg').validatorEnable({}, {required: 'Field is required'});



ADD VALIDATORS:

		Add each validator to the class attribute of an input, select or textarea by prefixing it with 'validator-'.
			<input type="text" class="validator-required validator-date">

		An argument to a validator can be added as suffix with '-' as seperator.
		Eg. a minimum length validation:
			<input type="text" class="validator-required validator-minlength-4">



EXAMPLE HTML FORM SETUP:

		<form action="post" id="frm_test" action="">

			<div class="formRow">
				<div class="formLabel"><label for="SFRM_Test">Test</label></div>
				<div class="formCtrl>
					<input class="validator-required" type="text" name="SFRM_Test" id="SFRM_Test" value="">
					<div id="errMsg-SFRM_Test" class="errMsg">
						<div class="errMsg-required">Require error message specific for this field</div>
						<div class="errMsg-unique">Unique error message specific for this field</div>
						<div class="errMsg-dynamic">Overwrite all other error messages in here</div>
					</div>
				</div>
			</div>

		</form>
		<script language="text/javascript">
			$('#frm_test').validatorEnable();
		</script>


************************************************************************************************/

(function($) {


$.fn.extend({

	/**
	 * Returns a value of a field as a string.
	 * Will return checkbox lists etc as a comma separated string
	 * @return string 
	 */ 
	fieldStringVal: function() {
		var retval = new String();
		if (this.length > 0){
			var elm = this[0];
			var name = new String(elm.name);
			var t = elm.type;
			if (t == "checkbox" || t == "radio"){

				if (name == ""){
					if (elm.checked) retval = elm.id;
				}
				else{
					$(":input[name='" + name + "']").each(function(){
						if (this.checked){
							if (retval != "") retval += ",";
							retval += this.id;
						}
					});
				}
			}
			else if (t == "select-one" || t == "select-multiple"){
				for (var i=0; i<elm.length; i++){
					if (elm.options[i].selected){
						if (retval != "") retval += ",";
						retval += elm.options[i].value;
					}
				}
			}
			else{
				retval = elm.value;
			}
		}

		return $.trim(retval);
	},
	
	validatorTokenEnable:function(options){
	
		if (typeof $.validator == 'object') {
			jQuery.each(options, function(frm, key) {
		      $('#'+frm).validatorEnable();
		    });
		}
	},

	/**
	 * Enable validator
	 * @param object options		Validator options
	 * @param object errorMessages	Error messages
	 * @return jQuery
	 */
	validatorEnable: function(options, errorMessages){
		return $.each(this, function()
		{
			var form = this;
			if (typeof(form.id) == 'undefined' || typeof form.validator == 'object' || !$(form).is('form')) return;
			
			
			// set form specific settings
			form.validator = {
				options : $.extend({}, $.validator.defaultOptions, options),
				errorMessages : $.extend({}, $.validator.defaultErrorMessages, errorMessages),
				groups : []
			};

			// set focus handler
			if (form.validator.options.fieldFocusCssClass) {
				$('input[type=password], input[type=text], select, textarea', form)
					.focus(function()
					{
						if ($.browser.msie && (this.type=='select-one' || this.type=='select-multiple')) return;
						$(this).addClass($(this).parents('form')[0].validator.options.fieldFocusCssClass);
						return true;
					})
					.blur(function()
					{
						if ($.browser.msie && (this.type=='select-one' || this.type=='select-multiple')) return;
						$(this).removeClass($(this).parents('form')[0].validator.options.fieldFocusCssClass);
						return true;
					});
			}

			// set maxlength trigger for textarea's
			if (form.validator.options.fieldMaxlengthTrigger) $('textarea[class*=validator-maxlength]', form).setFieldLengthTrigger();

			// set focus to first field
			if (form.validator.options.autoFocus)
				$(':input:visible:enabled:first', form).focus();
				
			// add hidden field
			if (form.validator.options.validatorKey)
				$(form).append('<input type="hidden" name="SFRM_validator_key" value="'+form.validator.options.validatorKey+'">');
			
			// add unload handler
			if (form.validator.options.unloadWarning) {
				$(':input', form).change(function(){ $.validator.formChangeCnt++; });
				window.onbeforeunload = function() {
			    	if ($.validator.formChangeCnt > 0 && $.validator.onUnloadEnabled) {
						return form.validator.errorMessages.unload;
					}
			    };
			    $.validator.onUnloadEnabled = true;
			}
			
			// set submit handler
			$(form).bind("submit", function(){
				//var start_time = new Date();
				var result = $.validator.validateForm(this);
				//var end_time = new Date();
				//alert('Validated in '+((end_time-start_time)/1000)+' seconds');
				return result; 
			});
			
		});
	},


	/**
	 * Set length trigger on a field
	 * @return jQuery
	 */
	setFieldLengthTrigger: function(){
		$(this).each(function(){
			var m = 0;
			var cssClassesStr = new String($(this).attr("class"));
			var cssClasses = cssClassesStr.split(" ");
			for (var i=0; i<cssClasses.length; i++){
				if (cssClasses[i].substr(0,20) == 'validator-maxlength-'){
					m = parseInt(cssClasses[i].substr(20));
					break;
				}
			}
			this.maxlength = m;
			$('#'+this.id+'_size').text(this.value.length);

			$(this).keyup(function(){
				if (this.value.length > this.maxlength && this.maxlength > 0) this.value = this.value.substr(0,this.maxlength);
				$('#'+this.id+'_size').text(this.value.length);
			});
		});
		return this;
	},
	
	/**
	 * Set unfocus value
	 * @param value
	 * @return jQuery
	 */
	setUnfocusValue: function(value){
		$(this).each(function(){
			if (typeof(this.unfocusValue)!='undefined') return;
			this.unfocusValue = value;
			this.origType = this.type;
			
			if (this.type=='password') {
				$(this).after('<input type="text" style="display:none" class="formUnfocus" id="'+this.id+'-overlay" value="'+this.unfocusValue+'">');
				$('#'+this.id+'-overlay').focus(function(){
					$(this).hide().siblings('#'+this.id.substring(0,this.id.length-8)).show().focus();
				});
				$(this).blur(function(){
					if (this.value=='' && this.value!=this.unfocusValue) {
						$('#'+this.id+'-overlay').removeClass('formFocus').show();
						$(this).hide();
					}
				}).blur();
			} else {
				$(this).focus(function(){ 
					if (this.value==this.unfocusValue){
						$(this).val('').removeClass('formUnfocus');
					}
				}).blur(function(){
					if (this.value=='' || this.value==this.unfocusValue) {
						$(this).val(this.unfocusValue).addClass('formUnfocus');
					} else { //incase event is called manually
						$(this).removeClass('formUnfocus');
					}
				}).blur();
			}
			
			$.validator.unfocusValueFields.push(this);
		});
		return this;
	}
});


//
// indexOf on an array for IE
//
if(!Array.indexOf){
    Array.prototype.indexOf = function(obj){
        for(var i=0; i<this.length; i++){
            if(this[i]==obj){
                return i;
            }
        }
        return -1;
    }
}

//
// Static methods
//
$.validator = {
	
	/**
	 * Array of fields with unfocus handler
	 * @var object
	 */
	unfocusValueFields: [],

	/**
	 * Array of custom validators
	 * @var object
	 */
	customValidators : {},
	
	/**
	 * Current change form elements (used by onUnload handler)
	 * @var int
	 */
	formChangeCnt: 0,
	
	/**
	 * onUnload handler state
	 * @var bool
	 */
	onUnloadEnabled: false,
	
	/**
	 * Default validator options
	 * @var object
	 */
	defaultOptions : {
		showInlineMessages 			: true,
		inlineMessageElementIdPrefix: "errMsg-",
		headElementCssClass 		: "sfrm_errors",
		fieldErrorCssClass 			: "errHilite",
		fieldFocusCssClass 			: 'formFocus',
		formRowCssClass				: 'formRow',
		showTooltip 				: false,
		tooltipElementClass 		: 'formInfo',
		hdlCallback					: false,
		fieldMaxlengthTrigger		: true,
		autoFocus					: false,
		formOverlay					: true,
		validatorKey				: false,
		unloadWarning				: false
	},

	/**
	 * Default error messages
	 * @var object
	 */
	defaultErrorMessages : {
		required: 	'Vul aub bovenstaand veld in',
		requiredby: 'Vul aub bovenstaand veld in',
		postcode: 	'Onjuiste postcode',
		email: 		'Onjuist e-mailadres',
		emailunique:'E-mailadres is al geregistreerd',
		loginunique:'Gebruikersnaam is al geregistreerd',
		select: 	'Selecteer aub een optie',
		time:		'Onjuiste tijd',
		date: 		'Onjuiste datum',
		mindate:	'Datum ligt te ver in het verleden',
		maxdate:	'Datum ligt te ver in de toekomst',
		phone:		'Vul aub een geldig telefoonnummer in',
		phonenl:	'Vul aub een geldig telefoonnummer in',
		minlength: 	'Ingevulde tekst is te kort',
		maxlength:	'Ingevulde tekst is te lang',
		minvalue:	'Grotere waarde verwacht',
		maxvalue:	'Kleinere waarde verwacht',
		pattern:	'Onjuiste invoer',
		equalto:	'Velden komen niet overeen',
		notequalto:	'Velden mogen niet gelijk zijn',
		user:		'Gebruikersnaam is onjuist',
		website:	'Website adres is onjuist. Een adres moet altijd beginnen met http://',
		name:		'Ongeldige tekens in naam',
		initials:	'Onjuiste voorletters. Vul aub voorletters in gescheiden met een punt',
		unique:		'Dubbele waarde',
		chars:		'Alleen letters worden toegestaan',
		numeric:	'Alleen nummers worden toegestaan',
		bank:		'Onjuist giro- of bankrekeningnummer',
		greater:	'Waarde is groter dan de gekoppelde waarde',
		less:		'Waarde is kleiner dan de gekoppelde waarde',
		file: {
			image:	'Bestand is geen geldig afbeelding (ondersteunde formaten: jpg/png/gif)',
			doc:	'Bestand is geen geldig document (ondersteunde formaten: doc/docx/xls/xlsx/ppt/pptx/pdf)',
			video:	'Bestand is geen geldig video bestand (ondersteunde formaten: mov/avi/wmv/mpg)'
		},
		ajax:		'Er is een fout ontstaan bij het valideren van dit veld. Probeer het aub nogmaals. Wanneer u het probleem blijft houden, raden wij u aan contact op te nemen met de website beheerder.',
		unload:		'Bij het verlaten van deze pagina zullen alle wijzigingen verloren gaan.'
	},

	/**
	 * Reset form state
	 * @param object form		Form object
	 * @param object options	Validator options
	 */
	resetForm : function (form, options){
		
		$('.'+options.headElementCssClass, form).hide();

		// reset validator groups
		form.validator.groups = [];

		$("div[id^='"+options.inlineMessageElementIdPrefix+"'], div[class*='"+options.inlineMessageElementIdPrefix+"']", form).hide();
		$('div.'+options.fieldErrorCssClass+', :input.'+options.fieldErrorCssClass, form).removeClass(options.fieldErrorCssClass);
	},
	
	disableUnfocusValueFields: function(form)
	{
		$.each($.validator.unfocusValueFields, function(){
			if ($(this).val()==this.unfocusValue && this.type!='password') $(this).val('');
		});
	},
	
	enableUnfocusValueFields: function(form)
	{
		$.each($.validator.unfocusValueFields, function(){
			if ($(this).val()=='' && this.type!='password') $(this).val(this.unfocusValue);
		});
	},

	/**
	 * Perform validation on all form elements
	 * @param object form	Form object
	 * @return bool			Validation state
	 */
	validateForm : function(form){
			
		var options = (form.validator ? form.validator.options : $.validator.defaultOptions)
			,validatedOK = true
			,idx = new Object, dateIdx = [], timeIdx = []
			,data = [], e=0
			,focusField;

		//set tinyMCE values to textarea's:
		if (typeof tinyMCE == 'object') {
			tinyMCE.triggerSave();
		}		
		// reset errors
		$.validator.resetForm(form, options);
		
		// disable form
		if (options.formOverlay) $.validator.setOverlay(form);
		
		// disable unfocus value fields
		$.validator.disableUnfocusValueFields();
		
		// check functions
		function isDateObject(id) {
	    	var ob = document.getElementById(id);
	    	return (ob&&ob.className.indexOf('validator-date') > -1);
	    }
	    function isTimeObject(id) {
	    	var ob = document.getElementById(id);
	    	return (ob&&ob.className.indexOf('validator-time') > -1);
	    }
		
		// Loop through each input and validate
		$(':input', form).each(function(i)
		{
			var fieldElm, value, type, name = this.name;
			if (name == "" || typeof(name) == 'undefined') return;
			
			// set type for special input fields
			var spos = name.lastIndexOf('_'), suffix = name.substring(spos+1), prefix = name.substring(0, spos);
			if (isDateObject(this.id.substring(0,this.id.lastIndexOf('_'))) && (suffix=='day' || suffix=='month' || suffix=='year')) {
				if(typeof(idx[prefix])=='undefined') idx[prefix] = new Object;
				idx[prefix].type = 'date';
				idx[prefix][suffix] = this;
				return;
			} else if (isTimeObject(this.id.substring(0,this.id.lastIndexOf('_'))) && (suffix=='hour' || suffix=='min')) {
				if(typeof(idx[prefix])=='undefined') idx[prefix] = new Object;
				idx[prefix].type = 'time';
				idx[prefix][suffix] = this;
				return;
			}
			
			// convert to jQuery element
			fieldElm = $(this);
			
			// already validated
			if(typeof(idx[name])!='undefined') {
				if (idx[name].type=='date' && idx[name].year && idx[name].month && idx[name].day) {
					// date object
					value = idx[name].year.value+'-'+idx[name].month.value+'-'+idx[name].day.value;
					if (value.length!=10) value = '';
				} else if (idx[name].type=='time' && idx[name].hour && idx[name].min) {
					// time object
					value = idx[name].hour.value+':'+idx[name].min.value;
					if (value.length!=5) value = '';
				} else {
					// object already set
					return;
				}
				fieldElm.val(value);
			} else {
				idx[name] = new Object;
				idx[name].type = this.type;
			}
						
			// log validation
			idx[name].elm = this;
			
			// set type
			type = idx[name].type;
			value = fieldElm.fieldStringVal();

			// get validators
			var validators = [];
			var cssClasses = (new String(fieldElm.attr("class"))).split(" ");
			for (var i=0; i<cssClasses.length; i++){
				if (cssClasses[i].indexOf('validator-') == 0)
					validators.push(cssClasses[i].substring(10));
			}

			
			// default resultset
			var result = {name: name, result: true, msg: null, validator: null, value: null};

			// attributes
			var attr = {
				validators: validators,
				minvalue: fieldElm.attr('minvalue')||'',
				maxvalue: fieldElm.attr('maxvalue')||''
			};

			// go through each validator methods
			for (var i=0; i<validators.length; i++)
			{
				result = $.validator.validateField(name, value, validators[i], form, attr);
				if (!result.result) break;
			}

			// validation succeed
			if (result.result)
			{
				if (result.value!=null && (type=='text'||type=='hidden'||type=='textarea')) {
					fieldElm.val(result.value);
				}
			}
			else 
			{
				validatedOK = false;

				// Set focus and scroll to the first errored element
				if (!focusField) {
					focusField = $(
					type=='date' ? ":input[name='"+name+"_day']:visible, :input[name='"+name+"_month']:visible, :input[name='"+name+"_year']:visible" : (
							type=='time' ? ":input[name='"+name+"_hour']:visible,:input[name='"+name+"_min']:visible" :
							":input[name='"+name+"']:visible")
					, form);
				}

				$.validator.setErrorField(idx[name], result.msg, result.validator, form, options);
			}

			// remember results
			data[e]=result;
			e++;
		});
		
		// show head error message
		if (!validatedOK) $('.' + options.headElementCssClass, form).filter(':first').show();
		
		// set focus to first error field
		if (focusField && focusField.length) focusField.filter(':first').focus();

		// post through an hdlCallback instead of a normal post
		if (typeof options.hdlCallback == 'function')
			validatedOK = options.hdlCallback(validatedOK,form,data);
			
		// enable form again
		if (!validatedOK) {
			if (options.formOverlay) $.validator.unsetOverlay(form);
			
			// enable unfocus value fields
			$.validator.enableUnfocusValueFields();
		}
		
		// set validator key
		// TODO: generate a dynamic key
		if (validatedOK && options.validatorKey)
			$(":input[name='SFRM_validator_key']", form).val(options.validatorKey);
			
		// disable onunload handler
		if (validatedOK) $.validator.onUnloadEnabled = false;
		
		// return state
		return validatedOK;
	},

	/**
	 * Validate a field with a validator method
	 * @param string name 		Name of field
	 * @param string value 		Value of field
	 * @param string validator 	Name of validator with arguments
	 * @param object form 		Form object
	 * @param object attr		Field attributes
	 * @return object {name, result, msg, validator, value}
	 */
	validateField: function(name, value, validator, form, attr)
	{
		var msg, arg, required, method, external = false, result = true;
		var msgs = (form.validator ? form.validator.errorMessages : $.validator.defaultErrorMessages);

		var div = validator.indexOf('-');
		if (div > 0)
		{
			method = validator.substring(0,div);
			arg = validator.substring(div+1);
		}
		else
		{
			method = validator;
			switch (method) {
				case 'telefoon' : method='phone'; break;
				case 'number' : method='numeric'; break;
			}
		}
		
		/**
		 * helper function: string repeat
		 * @param string str 	String
		 * @param int i			Increment
		 * @return string
		 */
		function strRepeat(str, i) {
	        var newstr = ''; 
	        for (var j=0; j < i; j++) newstr += str; 
	        return newstr;
	    } 
		
		/**
		 * Helper function: string compare
		 * @param string str1	String 1
		 * @param string str2	String 2
		 * @param string op		Operator
		 * @return bool
		 */
		function strCompare(str1, str2, op) 
		{
			var ml = (str1.length > str2.length ? str1.length : str2.length);
			str1 = strRepeat('0',ml-str1.length)+str1;
			str2 = strRepeat('0',ml-str2.length)+str2;
			var rs = false;
			switch(op)
			{
				case 'le' : // less-equal
					rs = str1 <= str2;
					break;
				case 'ge' : // greater-equal
					rs = str1 >= str2;
					break;
				case 'e' : // equal
					rs = str1 == str2;
					break;
			}
			return rs;
		}

		// execute current validator method
		switch (method)
		{
			case 'required' :
				result = (value!='');
				msg = msgs.required;

				if (!attr.validators.indexOf('date'))
				{
					if (result && attr.minvalue!='')
					{
						method = 'minvalue';
						result = value >= attr.minvalue;
					}

					if (result && attr.maxvalue!='')
					{
						method = 'maxvalue';
						result = value <= attr.maxvalue;
					}
				}
				break;
			case 'requiredby':
				if(arg && $('#'+$.validator.filterName(arg)).fieldStringVal())
				{
					result = (value!='');
				}
				break;
			case 'postcode':
				if (value!='')
				{
					var regex = /^(\d{4})\s*([A-Za-z]{2})$/;
					result = regex.test(value);
					if (result) value = value.replace(regex, '$1 $2');
				}
				break;
			case 'email':
				if (value!='')
				{
					result = /^([\w\-]+[.])*[\w\-]+[@]([\w\-]+[.])*[\w\-]{2,}[.]\w{2,6}$/.test(value);
				}
				break;
			case 'emailunique':
				if (value!='') external = true;
				break;
			case 'loginunique':
				if (value!='') external = true;
				break;
			case 'select':
				result = (value!='');
				break;
			case 'phone':
				if (value!='')
				{
					result = /^[\d\+\-\s.,]{6,}$/.test(value);
				}
				break;
			case 'phonenl':
				//default true
				result = true;
				if (value!='')
				{
					//if value default false
					result = false;
					
					//regular check
					validFormat = /^[\d\+\-\s.,]{6,}$/.test(value);
					if(validFormat) {
						
						var bMobile = false;
						var iStart	= 3;
					  	
					  	//strip spaces
					  	value = value.replace(/(\s)/g, '');
					  	sCleanVal = value.replace(/(-)/g, '');
					  	
					  	//replace countrycode
					  	sCleanVal = sCleanVal.replace(/(0031)/g, '0');
					  	sCleanVal = sCleanVal.replace(/(\+31)/g, '0');
					  						  	
					  	//check for 10 digits
					  	if(sCleanVal.length == 10) {
						  	//determine if mobile number
						  	if(sCleanVal.substr(0,2) == '06') {
						  		bMobile = true;
						  		iStart = 2;
						  	}
						  	//check for 0 at start
							if(sCleanVal.substr(iStart,1)!= '0') {
								
								//check for number trick
								if((bMobile && sCleanVal.substr(iStart) != '12345678') || (!bMobile && sCleanVal.substr(iStart) != '1234567')) {
									result = true;
									//$(':input#'+name).val();
								}		
							}
					  	}
					  	//set clean phonenumber
					  	if (result) value = sCleanVal.substr(0,iStart)+'-'+sCleanVal.substr(iStart);
					}
				}
				break;
			case 'date':
				if (value!='')
				{
					var regex = /^(\d{4})-(\d{2})-(\d{2})$/;
					if(regex.test(value))
					{
						var d = new Date(value.replace(regex, '$2/$3/$1'));
						result = ( parseInt(RegExp.$2, 10) == (1+d.getMonth()) ) &&
										(parseInt(RegExp.$3, 10) == d.getDate()) &&
										(parseInt(RegExp.$1, 10) == d.getFullYear() );
						msg = msgs.date;
					}
					else
					{
						result = false;
						msg = msgs.required;
					}

					if (result && attr.minvalue!='')
					{
						method = 'minvalue';
						result = value >= attr.minvalue;
						msg = msgs.mindate;
					}

					if (result && attr.maxvalue!='')
					{
						method = 'maxvalue';
						result = value <= attr.maxvalue;
						msg = msgs.maxdate;
					}
					
				}
				break;
			case 'time' :
				if (value.length==5)
				{
					var regex = /^(\d{2}):(\d{2})$/;
					if (regex.test(value))
					{
						var h = parseInt(value.replace(regex, '$1')), m = parseInt(value.replace(regex, '$2'));
						if (h<0 || h>23 || m<0 || m>59)
						{
							result = false;
						}
					}
					else
					{
						result = false;
					}
				}
				break;
			case 'equalto' :
				if (arg)
				{
					var revalue = $('#'+$.validator.filterName(arg)).fieldStringVal();
					if ((revalue!='' || value!='') && revalue!=value)
					{
						result = false;
					}
				}
				break;
			case 'notequalto' :
				if (arg)
				{
					var revalue = $('#'+$.validator.filterName(arg)).fieldStringVal();
					if ((revalue!='' || value!='') && revalue==value)
					{
						result = false;
					}
				}
				break;
			case 'user':
				if (value!='')
				{
					result = /^[a-zA-Z0-9_\-]{3,64}$/.test(value);
				}
				break;
			case 'maxlength' :
				arg = parseInt(arg);
				if (arg > 0)
				{
					result = (value.length <= arg);
				}
				break;
			case 'minlength' :
				arg = parseInt(arg);
				if (value!='' && arg > 0)
				{
					result = (value.length >= arg);
				}
				break;
			case 'website' :
				if (value!='')
				{
					if (!/^(ftp|http|https):\/\//.test(value)) value = 'http://'+value;
					result = /^(([\w]+:)?\/\/)?(([\d\w]|%[a-fA-f\d]{2,2})+(:([\d\w]|%[a-fA-f\d]{2,2})+)?@)?([\d\w][-\d\w]{0,253}[\d\w]\.)+[\w]{2,4}(:[\d]+)?(\/([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)*(\?(&?([-+_~.\d\w]|%[a-fA-f\d]{2,2})=?)*)?(#([-+_~.\d\w]|%[a-fA-f\d]{2,2})*)?$/.test(value);
				}
			case 'name' :
				if (value!='')
				{
					result = /^[^0-9~!@#$%^&*+={}\[\]|\\<>_]+$/.test(value);
				}
				break;
			case 'pattern' :
				if (value!='')
				{
					var pattern,regExp;
					pattern = $('#'+$.validator.filterName(name)).attr('pattern');
					patternoptions = $('#'+$.validator.filterName(name)).attr('patternoptions');
					regExp = new RegExp(pattern,patternoptions);				
					result = regExp.test(value);
				}
				break;
			case 'initials' :
				if (value!='')
				{
					value = value.replace(/([a-z]{1}|th)([\s,\.]+|$)/gi, '$1.').toUpperCase();
					result = /^(([a-z]{1}|th)\.)+$/i.test(value);
				}
				break;
			case 'unique' :
				if (value!='')
				{
					if (!arg) arg = 0;
					if (form.validator && form.validator.groups && form.validator.groups[arg])
					{
						if (form.validator.groups[arg].indexOf(value) > -1)
						{
							result = false;
						}
						else
						{
							form.validator.groups[arg].push(value);
						}

					}
					else
					{
						form.validator.groups[arg] = [];
						form.validator.groups[arg].push(value);
					}
				}
				break;
			case 'chars' :
				if (value!='')
				{
					result = /^([a-zA-Z])$/.test(value);
				}
				break;
			case 'numeric' :
				if (value!='')
				{
					result = /\d+$/.test(value);
					if (result && attr.minvalue!='')
					{
						method = 'minvalue';
						result = value >= attr.minvalue;
					}

					if (result && attr.maxvalue!='')
					{
						method = 'maxvalue';
						result = value <= attr.maxvalue;
					}
				}
				break;
			case 'bank' :
				result = true;
				var len = value.length;
				if (len == 9 ) {
					var berekening = 0;
					while (len > 0) {
						berekening += len*value.substr((9-len),1);
						len--;
					}
					result = (berekening % 11 == 0);
				} 
				else if (len < 7 || len > 9) 
				{
					result = false;
				}
				else if (value.substr(0,1) == '0') {
					result = false;
				}
				break;
			case 'greater' :
				if (value!='' && arg && !strCompare(value, $('#'+$.validator.filterName(arg)).fieldStringVal(), 'ge'))
				{
					result = false;
				} 
				break;
			case 'less' :
				if (value!='' && arg && !strCompare(value, $('#'+$.validator.filterName(arg)).fieldStringVal(), 'le'))
				{
					result = false;
				} 
				break;
			case 'file' :
				if (value != '') 
				{
					switch (arg)
					{
						case 'image' :
							result = /\.(jpg|gif|jpeg|png)$/i.test(value);
							msg = msgs.file.image;
							break;
						case 'doc' :
							result = /\.(doc|xls|pdf|ppt|pps|docx|xlsx|pptx)$/i.test(value);
							msg = msgs.file.doc;
							break;
						case 'video' :
							result = /\.(mov|avi|wmv|mpg|mpeg)$/i.test(value);
							msg = msgs.file.video;
							break;
					}
				}
				break;
			default :
				if (typeof($.validator.customValidators[method]) == 'function')
				{
					return $.validator.customValidators[method](name, value, method, form, attr, arg);
				}
				break;
		}
		
		// specific external validation?
		if (external)
		{
			$.ajax({
				url: '/dynamics/validator.php',
				async:false,
				dataType:'json',
				data: {
					validator:validator,
					value:value,
					argument: arg
				},
				success: function(dr){
					result=dr.result;
				},
				error: function(){
					result=false;
					msg=msgs.ajax;
				}
			});
		}
		
		if (!result && !msg) {
			msg = msgs[method];
		}

		return {name: name, result: result, msg: msg, validator: method, value: value};
	},

	/**
	 * Set error for a specific field
	 * @param object field			Field properties
	 * @param string fieldMessage 	Error message
	 * @param string validator		Validator method
	 * @param object form			Form object
	 * @param object options		Validator options
	 */
	setErrorField: function(field, fieldMessage, validator, form, options)
	{
		var fieldElm = $(field.elm);
		var elmName = field.elm.name;
		var errMsgElm = $('#'+options.inlineMessageElementIdPrefix + $.validator.filterName(elmName), form);
		fieldElm.addClass(options.fieldErrorCssClass).parents('div.'+options.formRowCssClass+':first').addClass(options.fieldErrorCssClass);

		if (field.type=='date')	{
			$(field.year).addClass(options.fieldErrorCssClass);
			$(field.month).addClass(options.fieldErrorCssClass);
			$(field.day).addClass(options.fieldErrorCssClass);
		} else if (field.type=='time') {
			$(field.hour).addClass(options.fieldErrorCssClass);
			$(field.min).addClass(options.fieldErrorCssClass);
		}

		// show inline error messages
		if (options.showInlineMessages && errMsgElm.length){
			errMsgElm.show();
			if ($('div.'+options.inlineMessageElementIdPrefix+validator, errMsgElm).length){ // text predefined; just show
				$('div.'+options.inlineMessageElementIdPrefix+validator, errMsgElm).show();
			} else {
				if (!$('div.'+options.inlineMessageElementIdPrefix+'dynamic', errMsgElm).length){
					errMsgElm.append('<div class="'+options.inlineMessageElementIdPrefix+'dynamic"></div>');
				}
				$('div.'+options.inlineMessageElementIdPrefix+'dynamic', errMsgElm).show().html(fieldMessage);
			}
		}
	},

	/**
	 * Set overlay on form
	 * @param object form		Form object
	 */
	setOverlay: function(form)
	{
		var	formElm = $(form),
			overlayElm = $('div.formOverlay', form),
			warningElm = $('div.formWarning', form);
			
		if (overlayElm.length==0) return;
			
		if ($.browser.msie && $.browser.version <= 6) $('select', form).css('visibility', 'hidden');			
		overlayElm.height(formElm.height()).width(formElm.width()).show();
		warningElm.css({top: parseInt((formElm.height()-warningElm.height())/2)+'px'}).show();
	},
	
	/**
	 * Unset overlay from form
	 * @param object form		Form object
	 */
	unsetOverlay: function(form)
	{
		if ($.browser.msie && $.browser.version <= 6) $('select', form).css('visibility', 'visible');
		$('div.formWarning,div.formOverlay', form).hide();
	},

	/**
	 * Filter form input name
	 * @param string name	Name
	 * @return string
	 */
	filterName: function(name)
	{
		return (name ? name.replace(/([\[\]])/g, '\\$1') : '');
	},

	/**
	 * Add new validator method
	 * @param string name		Name
	 * @param function func		Function
	 */
	addValidator: function(name, func)
	{
		$.validator.customValidators[name] = func;
	},
	
	/**
	 * Enable validator with tokens
	 * @param object options form and assigned token
	 */	
	tokenEnable: function(options){
	
		jQuery.each(options, function(frm, key) {
	      $('#'+frm).validatorEnable({validatorKey:key});
	    });
		
	},
	
	/**
	 * Assign single token to all forms
	 * @param string key assigned token
	 */	
	tokenEnableAll: function(key){
		
		$('form').each(function(){
			$('#'+this.id).validatorEnable({validatorKey:key});
		});	
	}
	
	
};

})(jQuery);
