/**********************************************************
Author:
Adam Barry
Klestrup partners
www.klestrup-partners.dk

Date: December 8 2008

© 2008 Adam Barry, all rights reserved
-----------------------------------------------------------

Name:
formValidation script (Microsoft .NET compatible)

-----------------------------------------------------------
Description:
Function that enable runs validation on userinputs on
various forms conforming to Microsoft.Net built pages.

-----------------------------------------------------------
Usage:
Simply place a link to the this script in the head-section
of the XHTML page. The script will then automatically
execute on page load.

<script type="text/javascript" src="formValidators.js"></script>
<script type="text/javascript" src="formValidation.Net.js"></script>

<form method="get" action="">


<div class="form">
<fieldset>
<legend>Form framework</legend>
<ul>
<li><label for="name">Name</label><input name="name" id="name" class="text required" type="text" /></li>
<li><label for="address">Address</label><input name="address" id="address" class="text" type="text" /></li>
<li><label for="email">E-mail</label><input name="email" id="email" class="text email" type="text" /></li>
<li><label for="number">Number</label><input name="number" id="number" class="text number required" type="text" /></li>
</ul>
<button type="button" class="submit"><span><span><span>Submit</span></span></span></button>
<button type="reset"><span><span><span>Reset</span></span></span></button>
</fieldset>
</div>

<div class="form">
<fieldset>
<legend>Form framework</legend>
<ul>
<li><label for="name">Name</label><input name="name" id="name" class="text required" type="text" /></li>
<li><label for="address">Address</label><input name="address" id="address" class="text" type="text" /></li>
<li><label for="email">E-mail</label><input name="email" id="email" class="text email" type="text" /></li>
</ul>
<button type="button" class="submit"><span><span><span>Submit</span></span></span></button>
<button type="reset"><span><span><span>Reset</span></span></span></button>
</fieldset>
</div>


</form>

Please note that the class attribute "required" and "email"
determins whether the specific form element is required.

-----------------------------------------------------------
Dependencies:
windowOnLoad.js

-----------------------------------------------------------
Revision history:

2009-05-15: Submit-on-enter functionality added

2009-05-18: Script refactored with emphasis on submit-on-
enter functionality

2009-06-27: Added additional check to test whether buttons onchange property has already been set
This allows script to be run multiple times on page

2010-03-24: Validators moved to separate JavaScript-file

2010-10-18 - Joakim: Re-merged with validator scripts, replaced the "onchange" function storage
trick with a Dictionary, ensuring cross-browser functionality (onchange didn't work in Chrome)

**********************************************************/
var buttonFunctions;

function initSubmitButtons() {
	
	if (!document.getElementsByTagName) return false;
	
	var buttons = document.getElementsByTagName("button");
	if (buttonFunctions == null) buttonFunctions = new Dictionary();

	for (var i = 0; i < buttons.length; i++) {
		var button = buttons[i];
		if (buttonFunctions[i] == null) {
			if (button.onclick != null) {
				buttonFunctions.Add(button.id, button.onclick);
			} else {
				buttonFunctions.Add(button, "");
			}
		}
		if (button.className.indexOf("submit") > -1) {
			if (button.onclick != null) {
				changeOnclick(button, buttonFunctions.Lookup(button.id));
			}
		}
	}
} addLoadEvent(function () { initSubmitButtons(); });

function changeOnclick(button, oldOnclick) {
	var me = button;
	me.onclick = function () {
		if (findDivForm(me) == true) {
			oldOnclick();
		}
		else {
			return false;
		}
	}
}

function initInputs() {

	/* Overcome stupid Firefox-error */
	var browser = navigator.userAgent;

	if (browser.indexOf('Firefox') > -1) {

		if (!document.getElementsByTagName) return false;

		var elements = document.getElementsByTagName("input");
		for (var i = 0; i < elements.length; i++) {
			elements[i].setAttribute("autocomplete", "off");
		}
	}
} addLoadEvent(function () { initInputs(); });


function findDivForm(button) {
	var formDivClassName = "form";
	var formDiv = button.parentNode;

	/* Loop throug the parentNodes of the clícked button until a div.form is found */
	while (formDiv.className.indexOf("form") == -1) {
		formDiv = formDiv.parentNode;
	}

	/* Validate the field elements in div.form */
	return validateForm(formDiv);
}

function submitButtonExecute(vThisform) {
	if (!vThisform) { return false; }

	buttons = vThisform.getElementsByTagName('button');
	if (!buttons) { return false; }

	for (var i = 0; i < buttons.length; i++) {
		if (buttons[i].className.indexOf('submit') > -1 && buttons[i].onclick != null) {
			buttons[i].onclick();
		}
	}
}

function submitPseudoForm(vThisform) {
	submitButtonExecute(vThisform);
	return false;
}


function validateCustomForm(button) {

	var formDivClassName = "form";
	var formDiv = button.parentNode;

	/* Loop throug the parentNodes of the clícked button until a div.form is found */
	while (formDiv.className.indexOf("form") == -1) {
		formDiv = formDiv.parentNode;
	}

	/*Validate the field elements in div.form */
	submitPseudoForm(formDiv);
}


/**********************************************************
Form validation
**********************************************************/

function validateForm(vThisform) {

	if (!vThisform) { return false; }

	var thisform = vThisform.getElementsByTagName("*");

	/*	Loop through all form elements of 'thisform' and determine
	which of them have 'required' or 'email' classes and are not children of a
	noValidation fieldset */

	for (var i = 0; i < thisform.length; i++) {
		var me = thisform[i];

		/* Loop through the form's required fields */
		if (me.className.indexOf('required') > -1 && me.parentNode.parentNode.parentNode.className.indexOf('noValidation') == -1) {

			if (me.tagName.toLowerCase() == "input" || me.tagName.toLowerCase == "password") {

				if (validate_required(me) == false) {
					return false;
				}
			}

			if (me.tagName.toLowerCase() == "select") {

				if (validate_select(me) == false) {
					return false;
				}
			}

			if (me.tagName.toLowerCase() == "textarea") {

				if (validate_textarea(me) == false) {
					return false
				}
			}
		}

		/* Loop through the form's fields that have been filled out, although they are not required */
		if (me.className.indexOf('email') > -1 && me.value.length > 0) {

			if (validate_email(me) == false) {
				return false;
			}
		}

		if (me.className.indexOf('number') > -1 && me.value.length > 0) {

			if (validate_number(me) == false) {
				return false;
			}
		}
	}

	return true; /* Form is valid */
}

function validate_required(field) {

	with (field) {

		if (type == "checkbox") {
			if (checked == "") {
				field.className += " error";
				field.focus();
				return false;
			}
		}

		if (value == null || value.length <= 0 || value == " ") {
			field.className += " error";
			field.focus();
			return false;
		}

		else {
			field.className = field.className.replace(new RegExp("error\\b"), "");
			return true;
		}
	}
}


function validate_email(field) {

	with (field) {

		if (field.value.indexOf(".") > 0 && field.value.indexOf("@") > 0) {
			field.className = field.className.replace(new RegExp("error\\b"), "");
			return true;
		}
		else {
			field.className += " error";
			field.focus();
			return false;
		}
	}
}


function validate_number(field) {

	with (field) {

		if (field.value.match(/^\d+$/)) {
			field.className = field.className.replace(new RegExp("error\\b"), "");
			return true;
		}
		else {
			field.className += " error";
			field.focus();
			return false;
		}
	}
}

function validate_decimal(field) {

    with (field) {

        if (field.value.match(/^[0-9]+([,\.][0-9]{1,2})?$/)) {
            field.className = field.className.replace(new RegExp("error\\b"), "");
            return true;
        }
        else {
            field.className += " error";
            field.focus();
            return false;
        }
    }
}

function validate_select(element) {

	if (element.selectedIndex == 0) {
		element.focus();
		element.className += " error";
		return false;
	}
}


function validate_textarea(field) {

	if (field.value.length <= 0) {
		field.focus();
		field.className += " error";
		return false;
	}
}


/**********************************************************
No validation pseudo-forms
**********************************************************/

function noValidationCheckboxes() {
	if (!document.getElementsByTagName) return false;

	var inputs = document.getElementsByTagName('input');

	for (var i = 0; i < inputs.length; i++) {

		if (inputs[i].className.indexOf('noValidation') > -1) {
			var me = inputs[i];

			me.onclick = function () {

				/* if the page is reloaded and the checkbox is unchecked */
				if (me.checked == true && me.parentNode.className.indexOf('noValidation') > -1) {
					me.parentNode.className = me.parentNode.className.replace(new RegExp("noValidation\\b"), "");
				}

				if (me.checked == false) {
					me.parentNode.className = me.parentNode.className.replace(new RegExp("noValidation\\b"), "");
				}
				else {
					me.parentNode.className += " noValidation";
				}
			}
		}
	}

} addLoadEvent(function () { noValidationCheckboxes(); });


/**********************************************************
Eventhandlers
**********************************************************/

function checkFormsOnEnter() {
	if (!document.getElementsByTagName) return false;

	var forms = new Array();
	var elements = document.getElementsByTagName("div");

	for (var i = 0; i < elements.length; i++) {
		if (elements[i].className.indexOf("form") > -1) {
			forms.push(elements[i]);
		}
	}

	for (var i = 0; i < forms.length; i++) {
		forms[i].onkeydown = function (event) {

			var evt = event || window.event;

			if (evt) {
				var target = evt.target || evt.srcElement;

				switch (evt.keyCode) {
					case 13: /* Enter/return key */
						if (target.tagName.toLowerCase() == "textarea") {
							return true;
						}

						else {
							if (validateForm(this) == true) {
								submitPseudoForm(this);
							}
							return false;
							break;
						}
				}
			}
		}
	}
} addLoadEvent(function () { checkFormsOnEnter(); });

/**********************************************************
Dictionary object
**********************************************************/
function Lookup(key) {
	return (this[key]);
}

function Delete() {
	for (c = 0; c < Delete.arguments.length; c++) {
		this[Delete.arguments[c]] = null;
	}
	// Adjust the keys (not terribly efficient)
	var keys = new Array()
	for (var i = 0; i < this.Keys.length; i++) {
		if (this[this.Keys[i]] != null)
			keys[keys.length] = this.Keys[i];
	}
	this.Keys = keys;
}

function Add() {
	for (c = 0; c < Add.arguments.length; c += 2) {
		// Add the property
		this[Add.arguments[c]] = Add.arguments[c + 1];
		// And add it to the keys array
		this.Keys[this.Keys.length] = Add.arguments[c];
	}
}

function Dictionary() {
	this.Add = Add;
	this.Lookup = Lookup;
	this.Delete = Delete;
	this.Keys = new Array();
}
