Akyla.injectTranslations({
	"nl_NL":
		{
			"This field is required." : "Dit is een verplicht veld.",
			"Please enter a valid number in this field." : "Vul een geldig getal in.",
			"Please enter a valid 6 digit number in this field." : "Vul een geldig 6 cijferig getal in.",
			"Please enter a valid integer in this field." : "Vul een geldig heel getal in.",
			"Please enter a valid phone number. Phone numbers can start with a + and can contain \"()- \". For example +31-(57)-20 30 40." : "Vul een geldig telefoonnummer in. Telefoon nummers kunnen beginnen met een + en kunnen \"() - bevatten. Bijvoorbeeld : +31-(57)-20 30 40.\"",
			"Please use numbers only in this field. Please avoid spaces or other characters such as dots or commas." : "Gebruik alleen nummers in dit veld. Vermijd het gebruik van spaties en andere karakters zoals punten en kommma's.",
			"Please use letters only (a-z) in this field." : "Gebruik alleen letters (a-z) in dit veld.",
			"Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed." : "Gebruik alleen letters (a-z) en getallen (0-9) in dit veld. Spaties en andere karakters zijn niet toegestaan.",
			"Please enter a valid email address. For example email@domain.com." : "Vul een geldig email adres in. Bijvoorbeeld email@domain.com",
			"Please enter a valid URL." : "Vul een geldige URL in.",
			"Please use this date format: %s. For example %s ." : "Gebruik a.u.b. het volgende formaat: %s.  Bijvoorbeeld %s .",
			"Please enter a valid currency amount. For example %s ." : "Vul een geldige waarde in. Bijvoorbeeld %s .",
			"Please make a selection." : "Maak een selectie.",
			"Please select one of the above options." : "Kies een van de bovenstaande opties.",
			"Your password must be more than 6 characters and not be \"password\" or \"1234567\"." : "Wachtwoord dient minimaal uit 7 karakters te bestaan.",
			"Your confirmation password does not match your first password, please try again." : "Bevestigings wachtwoord komt niet overeen met het eerste wachtwoord, probeer het opnieuw.",
			"Please enter a valid IBAN number." : "Vul een geldig IBAN in.",
			"Please enter a valid BIC number." : "Vul een geldig BIC in.",
			"Please enter a valid bank number." : "Vul een geldig banknummer in. Postbanknummers beginnen met een P",
			"Please enter a valid polish bank number." : "Vul een geldig pools banknummer in ('PL' + 26 cijfers)",
			"Please enter a valid german bank number." : "Vul een geldig duits banknummer in ('DE' + 20 cijfers)",
			"Please enter a valid bank number." : "Vul een geldig banknummer in. Postbanknummers beginnen met een P",
			"Please enter a valid Chamber of Commerce number." : "Vul een geldig KvK nummer in.",
			"Please enter a valid VAT number." : "Vul een geldig BTW nummer in.",
			"Please enter a valid BSN number." : "Vul een geldig BSN nummer in."
		}
	});
/**
 * The javascripts for an unobtrusive Form Validator
 * @author Ozgur Ayten
 */

var Akyla_Prototype_Form_Validator = Class.create(Akyla_Prototype_Observer,
{
	/**
	 * Name of the module 
	 */
	moduleName : "Akyla.Form.Validator",
	/**
	 * Load default preferences for the JSON  Table
	 */
	loadDefaultPreferences : function()
	{
		this.preferences = 
		{
			saveButtonReEnableDelay : 3000,
			autoFocus : false
		};
	},
	/**
	 * Processes a JSON component. In this cases it @use this.buildTable
	 * @param object component JSON component to process
	 */
	processComponent : function (component)
	{
	},
	/**
	 * Add form validation behaviour to a container containing possibly one or more forms which need validation.
	 * This will typically add validation behaviour to all elements containing a className "jsValidate"
	 *
	 * @param HTMLElement container HTMLElement containing forms to be validated
	 */
	observeContainer : function (container)
	{
		Element.select(container,"form.jsValidate").each(function (form)
		{
			/* Submit? make sure to recheck the form and stop the bubbling if something was wrong. */
			// Defer tabIndexing
			setTimeout(function ()
			{
				var tabIndex = 1;
				$(form).getElements().each(function (formElement)
				{
					if (formElement.type != "hidden")
					{
						formElement.tabIndex = tabIndex;
						formElement.writeAttribute("tabindex", tabIndex);
					}
					tabIndex++;
				}.bind(this));
			}.bind(this),0);
			if (form.hasAttribute("firebehaviour"))
			{
				setTimeout(function ()
				{
					var behaviours = form.readAttribute("firebehaviour").split(" ");
					behaviours.each(function (elementName)
					{
						form.select("[name="+elementName+"]").each(function (element)
						{
							if (element.type && element.type == "radio" && element.checked)
							{
								this.elementBlurred(element);
							}
						}.bind(this));
					}.bind(this));
				}.bind(this), 500);
			}
	
			// Observe mouse
			$(form).observe("mousedown", function (event)
			{
				var target=event.target;
				var tagName = target.tagName.toLowerCase();
				if (!target.tagName)
				{
					return;
				}
				if (tagName != "input" && tagName != "button")
				{
					target = target.up("input","button");
				}
				if (!target)
				{
					return;
				}
				this.handleClick(form,target,tagName,event);
			}.bind(this));
			/* Reset ? Reset the form and reset all the classes */
			$(form).observe("reset", function (event)
			{
				this.resetForm(form);
			}.bind(this));
			// Listen to focus and blur events
			if ($(form).addEventListener)
			{
				$(form).addEventListener("change", function (event)
				{
					var target = event.target;
					if ((target.tagName.toLowerCase() == "input" && target.type == "radio") || (target.tagName.toLowerCase() == "select"))
					{
						this.elementBlurred(event.target);
					}
				}.bind(this),true);
				// listen to the capture phase blur event
				$(form).addEventListener("blur", function (event)
				{
					event.target.removeAttribute("valid");
					this.testElement(event.target);
					this.elementBlurred(event.target);
				}.bind(this),true);
				// listen to the capture phase focus event
				$(form).addEventListener("focus", function (event)
				{
					var target = event.target;
					this.elementFocused(target);
				}.bind(this),true);
			}
			else
			{
				// listen to the capture phase focusin event on IE
				$(form).observe("focusin", function (event)
				{
					var target = event.target;
					this.elementFocused(target);
				}.bind(this));
				// listen to the capture phase focusout event on IE
				$(form).observe("focusout", function (event)
				{
					event.target.removeAttribute("valid");
					this.testElement(event.target);
					this.elementBlurred(event.target);
				}.bind(this));
			}
			/* Sympy remove the "jsValidate" class so we don't reobserve the elements */
			$(form).removeClassName("jsValidate");
			$(form).addClassName("jsValidated");
			//this.testFormAsync(form);
		}.bind(this));
	},
	/**
	 * Handles a click on an action button, atm only submit button is implemented. More appliances can be thought off
	 *
	 * @param object form Form to which the click applies
	 * @param object element The element which "sent" the click
	 * @param tagName Tag name of the element which sent the click
	 * @param event Event which sent the click if applicable
	 */
	handleClick : function (form, element, tagName, event)
	{
		if (element.type && (element.type == "submit" || element.type=="button"))
		{
			var img = element.down("img");
			var src = img.src;
			img.src = "image/gfx/ajax_process.gif";
			element.writeAttribute("disabled","disabled");
			var twinElement;
			if (element.up("div.formSubmitDiv"))
			{
				twinElement = element.up("div.content").down("div.toolbar button.saveButton[action=save]");
			}
			else
			{
				twinElement = element.up("div.content").down("form div.formSubmitDiv button[type=submit]");
			}
			if (twinElement)
			{
				var twinImage = twinElement.down("img");
				var twinSrc = twinImage.src;
				twinImage.src = "image/gfx/ajax_process.gif";
				twinElement.writeAttribute("disabled","disabled");
			}
			if (form.hasClassName("noCheck"))
			{
				Akyla.Ajax.ajaxRequest(form.readAttribute("postAction"),form,
				{
					onRequestError : function ()
					{
						img.src = src;
						element.removeAttribute("disabled");
						if (twinElement)
						{
							twinImage.src = twinSrc;
							twinElement.removeAttribute("disabled");
						}
					}
				});
				setTimeout(function ()
				{
					img.src = src;
					element.removeAttribute("disabled");
					if (twinElement)
					{
						twinImage.src = twinSrc;
						twinElement.removeAttribute("disabled");
					}
				},this.preferences.saveButtonReEnableDelay);
				if (event && event.type == "submit")
				{
					event.stop();
				}
				return;
			}
			this.testFormAsync(form, function (valid)
			{
				if (valid)
				{
					img.src = "image/icons/original/accept.png";
					if (twinImage)
					{
						twinImage.src = "image/icons/original/accept.png";
					}
					if (element.up("div.overlayWrapper"))
					{
						Akyla.Overlay.unOverlay();
					}

					Akyla.Ajax.ajaxRequest(form.readAttribute("postAction"),form,
					{
						onRequestError : function ()
						{
							img.src = src;
							element.removeAttribute("disabled");
							if (twinElement)
							{
								twinImage.src = twinSrc;
								twinElement.removeAttribute("disabled");
							}
						}
						
					});
					setTimeout(function ()
					{
						img.src = src;
						element.removeAttribute("disabled");
						if (twinElement)
						{
							twinImage.src = twinSrc;
							twinElement.removeAttribute("disabled");
						}
					},this.preferences.saveButtonReEnableDelay);
				}
				else
				{
					var div = new Element("div").addClassName("validationList");
					var validators = new Array();
					$(form).select("span.validationError").each(function (span)
					{
						if (!span.visible())
						{
							return;
						}
						var label = span.up("div.formPair").down("div.formElementLabelDiv");
						if (!label)
						{
							var td = span.up("td");
							if (td)
							{
								var cellIndex = td.cellIndex;
								var labels = span.up("table").down("thead").select("th");
								label = labels[cellIndex].down("div");
								label.className = "formElementLabelDiv";
							}
						}
						if (label)
						{
							validators.push(label.innerHTML);
						}

					});
					div.insert({bottom : "Volgende velden zijn niet correct ingevuld :<br />"});
					validators.uniq(true).each (function (item)
					{
						div.insert({bottom : "&nbsp;&nbsp;&nbsp;&nbsp;"+item+"<br />"});
					});
					delete validators;
					Akyla.WindowHandler.factory("Alert",
					{
						id : "alert",
						contentType : "htmlNode",
						content : div,
						afterClose : function()
						{
							var firstInvalidElement = form.down("div.formPair.invalid input");
							if (firstInvalidElement)
							{
								firstInvalidElement.activate();
							}
						}
					}).show();

					var firstInvalidElement = form.down("div.formPair.invalid input");
					if (firstInvalidElement)
					{
						firstInvalidElement.activate();
					}
					img.src = src;
					element.removeAttribute("disabled");
					if (twinElement)
					{
						twinImage.src = twinSrc;
						twinElement.removeAttribute("disabled");
					}
				}
			}.bind(this));
			if (event && event.type == "submit")
			{
				event.stop();
			}
		}
	},
	elementFocused : function(element)
	{
	},
	elementBlurred : function(element)
	{
	},
	calculateSectionDirtiness : function(parentSection,element)
	{
		var elementValue;
		if (typeof parentSection.dirty == "undefined")
		{
			parentSection.dirty = 0;
		}
		var parentDiv = element.up("div.formElementInputDiv");
		if (element.type == "radio")
		{
			//if (element.checked)
			//{
			//	elementValue = element.value;
			//}
			//else
			//{
				elementValue = "";
			//}
		}
		else
		{
			elementValue = element.value;
		}
		// Fix the dirty flag for elements
		var elementDirty = elementValue!=="";
		// first time
		if (typeof element.dirty == "undefined")
		{
			if (elementDirty)
			{
				parentSection.dirty++;
				if (parentSection.dirty === 1)
				{
					recheck = true;
				}
			}
		}
		else
		// second time that the input field is being adjusted
		{
			if (element.dirty !== elementDirty)
			{
				if (elementDirty)
				{
					parentSection.dirty++;
					if (parentSection.dirty === 1)
					{
						recheck = true;
					}
				}
				else
				{
					parentSection.dirty--;
					if (parentSection.dirty === 0)
					{
						recheck = true;
					}
				}
			}
		}
		element.dirty = elementDirty;
		parentSection.writeAttribute("dirty",parentSection.dirty);	
	},
	/**
	 * Test a form element on validness and creates advices
	 *
	 * @param object element The element to be checked
	 */
	testElement : function(element)
	{
		element = $(element);
		if (!element || !element.up)
		{
			return true;
		}
		if (element.hasClassName("ajaxSelect"))
		{
			element=element.next("input");
		}
		// element was already checked before, no need to do it again
		var parentSection = element.up("div.fieldset");
		var parentCompact = parentSection && parentSection.hasClassName("compact");
		if (parentCompact)
			var parentSection = element.up("tr");
		var parentDiv = element.up("div.formElementInputDiv");
		var parentContainer = element.up("div.formPair");
		var valid = true, elementValue = "";
		if (element.type == "radio")
		{
			//if (element.checked)
			//{
			//	elementValue = element.value;
			//}
			//else
			//{
				elementValue = "";
			//}
		}
		else
		{
			elementValue = element.value;
		}
		var recheck = false;
		if (!parentContainer || element.readOnly)
		{
			return valid;
		}
		if (parentSection)
		{
			this.calculateSectionDirtiness(parentSection,element);
		}
		var classes = element.classNames();
		// check all requirements
		classes.each(function (className)
		{
			// check if the class to be checked is in list of testables
			if (this.testables[className])
			{
				valid = valid && this.testables[className].tester(elementValue,element);

				var newMessage = '';
				if (typeof this.testables[className].message == "function")
				{
					newMessage = this.testables[className].message(elementValue, element);
				}
				else
				{
					newMessage = this.testables[className].message;
				}

				// fix advices
				var advice = parentDiv.down("span.validationError."+className);
				if (!valid)
				{
					if (advice)
					{
						if (className == 'bank')
						{
							advice.update(newMessage);
						}
						if (!advice.visible())
						{
							advice.show();
						}
					}
					else
					{
						parentDiv.insert({bottom : this.createAdvice(className,newMessage)});
					}
				}
				else
				{
					if (advice)
					{
						advice.hide();
					}
				}
			}
		}.bind(this));
		if (recheck)
		{
			parentSection.select(".required").each(function (el)
			{
				var tagName = el.tagName.toLowerCase();
				if (tagName == "input" || tagName == "select" || tagName == "textarea")
				{
					el.removeAttribute("valid");
				}
			}.bind(this));
		}
		// We now know if the whole thing is valie
		if (valid)
		{
			element.writeAttribute("valid","true");
			parentContainer.removeClassName("invalid").addClassName("valid");
		}
		else
		{
			element.writeAttribute("valid","false");
			// If the invalid element is in a collapsed div, uncollapse it
			//
			var switchedFieldset = element.up("div.fieldset.collapsed");
			if (switchedFieldset)
			{
				switchedFieldset.removeClassName("collapsed");
			}
			parentContainer.removeClassName("valid").addClassName("invalid");
		}
		return valid;
		// at this point the parent and the element dirty flags are set
	},
	/**
	 * Creates a simple advice with className and message
	 *
	 * @param string className Which classname should the advice get extra
	 * @param string message Which message should be shown
	 */
	createAdvice : function (className, message)
	{
		var span = new Element("span", {className : "validationError "+className}).update(message);
		return span;
	},
	/**
	 * Add behaviour to all existing forms in the document which are marked with jsValidate
	 * and observe the "container:change" event to add behaviour to changed content
	 */
	domLoaded : function()
	{
		Event.observe(document.body,"container:change", function (event)
		{
			this.observeContainer(event.target);
		}.bind(this));
	},
	/**
	 * Performs a check on all the form Elements of a form 
	 *
	 * @param HTMLElement Form to be checked
	 * @return boolean True if all form elements pass validation, False otherwise
	 */
	testForm : function (form)
	{
		var valid = true;
		var formElements = Form.getElements(form).reverse();
		setTimeout(function ()
		{
			formElements.each(function (element)
			{
				if (element.type != "hidden" && element.type != "button" && element.type != "submit" && element.type != "reset")
				{
					this.testElement(element);
				}
			}.bind(this));
		}.bind(this),0);
		return valid;
	},
	/**
	 * Asynchronously calls a testForm with a callback. Callback will be called with the result of the validation 
	 *
	 * @param object form Form to be validated
	 * @param function callback the function which will be called back with the validation result
	 */
	testFormAsync : function (form, callback)
	{
		form.valid = true;
		var formElements = $(form).getElements().reverse();
		this.testElementAsync(form,formElements,0, callback);
	},
	/**
	 * This starts testing form elements asynchronously in batches of 5 elements at a time. After every element has been validated
	 * the callback function gets called with the validation result. Rest of the parameters is for recursively calling itself.
	 *
	 * @param object form Form to be checked
	 * @param array elementList List of elements to be checked
	 * @param int index Which element should be started to be checked for first
	 * @param function callback which function should be called after the validation is ready
	 */
	testElementAsync : function(form, elementList, index, callback)
	{
		if (elementList.size() < 1)
		{
			return;
		}
		// Defer the checking
		setTimeout(function ()
		{
			var next = index;
			// Check first 5 in the batch
			for (next = index; next < index+5 && next < elementList.size(); next++)
			{
				var element = $(elementList[next]);
				if (!element)
				{
					return;
				}
				if (element.type != "hidden" && element.type != "button" && element.type != "submit" && element.type != "reset")
				{
					form.valid = form.valid & this.testElement(element);
				}
				if (next == elementList.size()-1)
				{
					callback(form.valid);
				}
			}
			// We are not ready yet, do another batch
			if (next < elementList.size())
			{
				this.testElementAsync(form, elementList, next, callback);
			}
		}.bind(this),0);
	},
	/**
	 * Resets all the form elements of a form for revalidation by removing all validation advices
	 * and validationFailed and validationPassed classes
	 *
	 * @param HTMLElement Form to be resetted
	 */
	resetForm : function (form)
	{
	},

	/**
	 * All the testables the form validator can check. For each of these testables the validator will seach the className
	 * of the htmlElement for the key, use the "tester" for testing on validation and use "message" for creating an advice
	 * if the validation fails
	 *
	 * Don't forget you can add your own testables on any page by doing
	 * Object.extend(Akyla.Form.Validator.testables,
		 {
			 primeNumber :
			 {
				 message : "This number is not a prime number",
				 tester : function (v, elm) { return Akyla.Tester.isEmpty(v) || Akyla.Tester.isPrimeNumber(v); }
			 }
		 });
	 */
	testables : 
	{
		required : 
		{
			message : Akyla.translate("This field is required."),
			tester : function (v, elm) 
			{
				var parentSection = elm.up("div.fieldset");
				var minOccurence = parseInt(parentSection.readAttribute("minoccurence"),10);
				var hasMinOccurence = parentSection.hasAttribute("minoccurence");
				var parentCompact = parentSection.hasClassName("compact");
				if (parentCompact)
					var parentSection = elm.up("tr");
				if (hasMinOccurence)
				{
					if (minOccurence > 0)
					{
						return !Akyla.Tester.isEmpty(v);
					}
					else
					{
						if (typeof parentSection.dirty == "undefined")
						{
							Akyla.Form.Validator.calculateSectionDirtiness(parentSection,elm);
						}
						return (parentSection.dirty < 1) || !Akyla.Tester.isEmpty(v);
					}
				}
				else
				{
					return !Akyla.Tester.isEmpty(v);
				}
			}
		},
		number :
		{
			message : Akyla.translate("Please enter a valid number in this field."),
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isNumber(v); }
		},
		numeric6 :
		{
			message : Akyla.translate("Please enter a valid 6 digit number in this field."),
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isXdigitNumber(v,6); }
		},
		integer :
		{
			message : Akyla.translate("Please enter a valid integer in this field."),
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isInteger(v); }
		},
		phone :
		{
			message : Akyla.translate("Please enter a valid phone number. Phone numbers can start with a + and can contain \"()- \". For example +31-(57)-20 30 40."),
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isPhoneNumber(v); }
		},
		digits :
		{
			message : Akyla.translate("Please use numbers only in this field. Please avoid spaces or other characters such as dots or commas."),
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isDigitsOnly(v); }
		},
		alpha :
		{
			message : Akyla.translate("Please use letters only (a-z) in this field."),
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isAlpha(v); }
		},
		alphanum :
		{
			message : Akyla.translate("Please use only letters (a-z) or numbers (0-9) only in this field. No spaces or other characters are allowed."),
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isAlphaNummeric(v); }
		},
		email :
		{
			message : Akyla.translate("Please enter a valid email address. For example email@domain.com."),
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isEmail(v); }
		},
		url :
		{
			message : Akyla.translate("Please enter a valid URL."),
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isURL(v); }
		},
		dateNl :
		{
			message : "Gebruik a.u.b. het volgende formaat: dd-mm-yyyy.  Bijv: 17-03-2006 voor de 17e van Maart, 2006 .",
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isValidDateI18n(v); }
		},
		date :
		{
			message : sprintf(Akyla.translate("Please use this date format: %s. For example %s ."),Akyla.preferences.localization.dateFormat,Akyla.Tester.dateExample()),
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isValidDateI18n(v); }
		},
		currencyDollar :
		{
			message : "Please enter a valid $ amount. For example $ 1,000.00 .",
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isDollar(v); }
		},
		currency :
		{
			message : sprintf(Akyla.translate("Please enter a valid currency amount. For example %s ."),Akyla.Tester.currencyExample()),
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isCurrency(v); }
		},
		currencyEuro :
		{
			message : Akyla.translate("Please enter a valid &euro; amount. For example &euro;1.000,00 ."),
			tester : function(v, elm) {  return Akyla.Tester.isEmpty(v) || Akyla.Tester.isEuro(v); }
		},
		selection :
		{
			message : Akyla.translate("Please make a selection."),
			tester : function(v, elm) {  return elm.options ? elm.selectedIndex > 0 : Akyla.Tester.isEmpty(v); }
		},
		iban : 
		{
			message : Akyla.translate("Please enter a valid IBAN number."),
			tester : function (v) {return Akyla.Tester.isEmpty(v) || Akyla.Tester.isIBAN(v);}
		},
		bic : 
		{
			message : Akyla.translate("Please enter a valid BIC number."),
			tester : function (v) {return Akyla.Tester.isEmpty(v) || Akyla.Tester.isBIC(v);}
		},
		bank : 
		{
			message : function (v,elm){
				if (/^(PL|pl).*$/.test(v))
				{
					return Akyla.translate("Please enter a valid polish bank number.")
				}
				else if (/^(DE|de).*$/.test(v))
				{
					return Akyla.translate("Please enter a valid german bank number.")
				}
				else
				{
					return Akyla.translate("Please enter a valid bank number.")
				}
			},
			tester : function (v) {return Akyla.Tester.isEmpty(v) || Akyla.Tester.isDutchBankNumber(v) || Akyla.Tester.isIBAN(v) || Akyla.Tester.isForeignBankNumber(v);}
		},
		kvk : 
		{
			message : Akyla.translate("Please enter a valid Chamber of Commerce number."),
			tester : function (v) {return Akyla.Tester.isEmpty(v) || Akyla.Tester.isKVK(v);}
		},
		btw : 
		{
			message : Akyla.translate("Please enter a valid VAT number."),
			tester : function (v) {return Akyla.Tester.isEmpty(v) || Akyla.Tester.isBTW(v);}
		},
		bsn : 
		{
			message : Akyla.translate("Please enter a valid BSN number."),
			tester : function (v) {return Akyla.Tester.isEmpty(v) || Akyla.Tester.isBSN(v);}
		},
		oneRequired : 
		{
			message : Akyla.translate("Please select one of the above options."),
			tester : function (v, elm)
			{
				var options = elm.parentNode.getElementsByTagName("INPUT");
				return $A(options).any(
					function(elm) 
					{
						return $F(elm);
					});
			}
		},
		password : 
		{
			message : Akyla.translate("Your password must be more than 6 characters and not be \"password\" or \"1234567\"."),
			tester : function (v, elm)
			{
				var opt = ["password","PASSWORD","1234567","0123456"];
				return (Akyla.Tester.isEmpty(v) || (v.length >= 7 && $A(opt).all(function(value) { return v != value; }))) ;
			}
		},
		passwordConfirm : 
		{
			message : Akyla.translate("Your confirmation password does not match your first password, please try again."),
			tester : function (v, elm)
			{
				return v == $F($(elm).readAttribute("alt"));
			}
		}
	},
	/**
	 * Holds translations of advices generated by the validator.
	 */
	localization : 
	{
	}
});

function array_unique (array) 
{
    // Removes duplicate values from array  
    // 
    // version: 909.322
    // discuss at: http://phpjs.org/functions/array_unique
    // +   original by: Carlos R. L. Rodrigues (http://www.jsfromhell.com)
    // +      input by: duncan
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   bugfixed by: Nate
    // +      input by: Brett Zamir (http://brett-zamir.me)
    // +   bugfixed by: Kevin van Zonneveld (http://kevin.vanzonneveld.net)
    // +   improved by: Michael Grier
    // %          note 1: the second argument, sort_flags is not implemented
    // *     example 1: array_unique(['Kevin','Kevin','van','Zonneveld','Kevin']);
    // *     returns 1: ['Kevin','van','Zonneveld']
    // *     example 2: array_unique({'a': 'green', 0: 'red', 'b': 'green', 1: 'blue', 2: 'red'});
    // *     returns 2: {'a': 'green', 0: 'red', 1: 'blue'}
    
    var key = '', tmp_arr1 = {}, tmp_arr2 = {};
    var val = '';
    tmp_arr1 = array;
    
    var __array_search = function (needle, haystack) 
	{
        var fkey = '';
        for (fkey in haystack) 
		{
            if ((haystack[fkey] + '') === (needle + '')) 
			{
                return fkey;
            }
        }
        return false;
    };

    for (key in tmp_arr1) 
	{
        val = tmp_arr1[key];
        if (false === __array_search(val, tmp_arr2)) 
		{
            tmp_arr2[key] = val;
        }
        
        delete tmp_arr1[key];
    }
    
    return tmp_arr2;
}

/*
 * Finally create the validator and initialize it
 */
Akyla.Form.Validator = new Akyla_Prototype_Form_Validator();

