/**
 * Copyright 2008, @author justin van horne
 */

var jForm = {};
jForm.configuration = {}

/**
 * Configuration for jForm
 * errorBorderColor	- The border color of the input that has an error
 * errorBackground	- The background color of the input tha thas an error
 * javascriptAlert	- Alert as a javascript or return as a string.
 *			  If returned as a string, the error is stored as an associative array
 *			  where the key is the name of the input and the value is the error.
 *			  jForm.errors is the associative array
 * callback		- The call back function if a form is invalid
 */
jForm.configuration.errorBorderColor	= "#2F3152";
jForm.configuration.errorBackground		= "#BEC0DA";
jForm.configuration.javascriptAlert		= true;
jForm.configuration.callback			= undefined;
jForm.errors = new Array();

/**
 * Validators
 * The associative array follows like this:
 * The key is the name being matched in smart mode.
 * The value is the regexp
 */
jForm.$validators = new Array();
jForm.$validators['name']	= "\\w";
//jForm.$validators['phone']	= "\\w";
jForm.$validators['comments']	= "\\w";
jForm.$validators['email']	= "^([0-9a-zA-Z]([-.\\w]*[0-9a-zA-Z])*@([0-9a-zA-Z][-\\w]*[0-9a-zA-Z]\\.)+[a-zA-Z]{2,9})$";
jForm.$validators['user']	= "\\w";
jForm.$validators['zip']	= "(^\\d{5}$)|(^\\d{5}-\\d{4}$)";
jForm.$validators['age']	= "\\d";


/**
 * Accessibility functions
 * $write		- Wrapper to document.writeln with variable length arguments
 * $id			- Wrapper to document.getElementById
 * $tag			- Wrapper to document.getElementsByTagName
 * $name		- Wrapper to document.getElementsByName; The first element.
 * $all_forms		- Returns all forms
 */
jForm.$write	= undefined;
jForm.$id		= function(id) { return document.getElementById(id); }
jForm.$tag		= function(tag) { return document.getElementsByTagName(tag); }
jForm.$name		= function(name) { x = document.getElementsByName(name); return x[0]; }
jForm.$all_form	= undefined;

/**
 * Any variable or method with an underscore is considered private
 */
jForm._initialized			= false;
jForm._windowLoadFunctions	= new Array();
jForm._inputMaps			= new Array();


/**
 * Initializer for jForm
 * @constructor
 */
jForm._constructor = function()
{
	_initialized		= true;
	jForm.$all_forms	= jForm.$tag("form");
}

/**
 * Returns a formatted array of parameters and their types
 * @param arguments The argument array from the caller function
 */
jForm._getArguments = function()
{
	caller_arguments = arguments[0];
	return_arguments = new Object();
	
	if (caller_arguments == undefined) {
		return_arguments.arguments	= new Array();
		return_arguments.param		= new Array(new Array());
		return_arguments.length		= 0;
		
		return return_arguments;
	}
	
	return_arguments.arguments	= caller_arguments;
	return_arguments.param		= new Array();
	return_arguments.param_type	= new Array()
	return_arguments.length		= return_arguments.arguments.length - 1;
	
	for (var i = 0; i <= return_arguments.length; i++) {
		return_arguments.param[i]		= return_arguments.arguments[i];
		return_arguments.param_type[i]	= typeof(return_arguments.arguments[i]);
	}

	return return_arguments;
}

/**
 * @param strings... Variable lengths
 */
jForm.$write = function()
{
	strings = jForm._getArguments(arguments);
	
	for (var i = 0; i <= string.length; i++) {
		document.writeln(strings.param[i] + "<br>");
	}
}

/**
 * Queues a list of functions to the window.onLoad - NON-DESTRUCTIVE
 * @param functions... The rest of the functions to add to the queue
 */
jForm._queueWindowLoad = function()
{
	with (jForm) {
		functions		= _getArguments(arguments);
		onload_exists	= 0;
		
		if (window.onload != undefined) {
			_windowLoadFunctions[0]	= window.onload;
			onload_exists			= 0;
		}
		
		for (var i = 0; i <= functions.length; i++) {
			_windowLoadFunctions[i + onload_exists] = functions.param[i];
		}
		
		/**
		 * The queue that will be called by the window.onload method
		 */
		loadQueue = function()
		{
			for (var i = 0; i < _windowLoadFunctions.length; i++) {
				_windowLoadFunctions[i]();
			}
		}
		
		window.onload = loadQueue;
	}
}

/**
 * Exactly like queueWindowLoad, but is destructive
 * @param functions... The rest of the functions to add to the queue
 */
jForm._newQueueWindowLoad = function()
{
	window.onload = undefined;
	jForm._queueWindowLoad(arguments);
}

/**
 * Tries to parse the name of a element smartly
 * @param {Object} name
 */
jForm._smartName = function(name)
{
	name = String(name).toLocaleLowerCase();
	for (var k in jForm.$validators) {
		var match = name.match(k);
		if (match != undefined) {
			return jForm.$validators[k];
		}
	}
}

jForm.validate = function()
{	
	with (jForm) {
		errors = "";
		for (var k in _inputMaps) {
			element = $name(k);
			
			if (element.disabled == 1)
				continue;
				
			matched = element.value.match(_inputMaps[k]);
			if (matched == undefined) {
				/**
				 * We want to preserve the attributes of the element we
				 * are showing errors with.
				 */
				element_border = element.style.border;
				element_background = element.style.background;
				element_focus = element.onfocus;
				element.style.borderColor = jForm.configuration.errorBorderColor;
				element.style.background = jForm.configuration.errorBackground;
				element.error_focused = false;
				
				
				focus = function()
				{
					if (this.error_focused == false) {
						this.style.background = element_background;
						this.style.border = element_border;
						this.error_focused = true;
					}
				}
				
				element.onfocus = focus;
				
				errors = errors + (element.title != undefined ? "You did not enter a valid " + element.title + "\n" : "You did not enter valid data for input" + k + "\n");
				jForm.errors[k] = (element.title != undefined ? "You did not enter a valid " + element.title + "\n" : "You did not enter valid data for input" + k + "\n");
			}
		}
		
		if (errors.length > 1) {
			if (configuration.javascriptAlert) {
				alert(errors);
			}
			if (configuration.callback != undefined) {
				configuration.callback();
			}
			return false;
		}
		else {
			return true;
		}
	}
}

/**
 * Tries to parse the document intelligently based off of the name of elements
 */
jForm.smartParse = function()
{
	with (jForm) {
		forms = $tag("form");
		forms = forms[0];
		
		for (var i = 0; i < forms.elements.length; i++) {
			var name = forms.elements[i].name;
			var validator = _smartName(name);
			
			if (validator != undefined) {
				_inputMaps[name] = validator;
			}
		}		
		forms.onsubmit = jForm.validate;
	}
}

/**
 * The queue to the window onLoad
 */
jForm._queueWindowLoad(jForm._constructor, jForm.smartParse);

