/**
 * Framework2 - validation javascript plug-in
 *
 * @author    Erik Schierboom <erikatblixemdotnl>
 * @author    Mike Vervuren <mikeatvervurendotcom>
 * @copyright BliXem Internet Services
 * @version   $Id: validation.js 20663 2009-06-02 14:32:44Z mike $
 * @package   Script
 * @internal  $HeadURL: svn://repos.blixem.nl:3691/shared/framework2/trunk/script/validation.js $
 * @filesource
 */

// Make sure the jQuery library is loaded
if (typeof jQuery == 'undefined') {
	throw('Validation requires the jQuery JavaScript framework');
}

/**
 * This variable contains the validation ruleset
 * @todo Put this variable in the plug-in
 */
var ValidationRuleset = null;

/**
 * This jQuery plug-in allows for client-side validation to be applied using the
 * server-side defined validation rules.
 */
jQuery.fn.extend({
	
	/**
	 * The init function should be called to prepare for client-side validation
	 */
	initValidation: function() 
	{
		$('form.validate').each(function() {
		
			// Check if the form has a validation URL specified 
			var validationUrl = $(this).find('input[type="hidden"][name="validation-url"]').val();
			if (validationUrl != undefined) {
				// Only debug when a hidden element with the name 'validation-debug' is
				// present in the form and it's value is 'true'
				var debug = $(this).find('input[type="hidden"][name="validation-debug"]').val();
				debug = (debug != undefined && debug.toLowerCase() == 'true');
				
				// Find all elements which have the validate class
				$(this).find('.validate').each(function() {
					$(this).bindValidation(validationUrl, debug);
				});
			}
		});
	},
	
	
	/**
	 * Prepare an object for validation;
	 */
	bindValidation: function(validationUrl, debug)
	{		
		// Perform client-side validation at each change for file, radio and
		// checkbox input fields and for the select field
		if(this.is('input[type="file"]') || this.is('input[type="radio"]') || this.is('input[type="checkbox"]') || this.is('select')) {			
			this.bind('change', function() { $(this).prepareValidation($(this), validationUrl, debug); });
		}
		// Perform client-side validation at each keystroke for every remaining
		// validation element
		else {			
			this.bind('keyup', function() { $(this).prepareValidation($(this), validationUrl, debug); });
		}		
		
		// Perform client-side validation at each blur for every validation element
		this.bind('blur', function() { $(this).prepareValidation($(this), validationUrl, debug); });
	},
	
	
	/**
	 * Bind the validation to an element
	 */
	prepareValidation: function(validationElement, validationUrl, debug)
	{
		// Check if the JSON ruleset has not already been retrieved
		if (ValidationRuleset == null) {
			// Do an AJAX-request to retrieve the JSON ruleset
			$.ajax({
			  type: 'GET',
			  url: validationUrl,
			  dataType: 'json',
			  error: function(request, error, exception) {
			  	// Check if we should output the error response text
			  	if (debug) {
			  	 	alert(request.responseText);
			  	}
			  },
			  success: function(json) {
			  	// Store the ruleset and validate the element, as the datatype has
			  	// been specified as 'json', the returned data has automatically
			  	// been translated to a javascript object
					ValidationRuleset = json;
					validationElement.validate();
				}
			});			
		}
		else {
			// Validate the element
			$(this).validate();
		}			
	},
	
	
  /**
	 * Validate an element
	 */
	validate: function()
	{
		// Get the name, value and ruleset for the validation element
		var fieldName    = $(this).attr('name');
		var fieldValue   = $(this).val();
		var fieldRuleset = ValidationRuleset[fieldName];
		
		var errors = 0;
		
		// Loop through all checks defined for the validation element
		for (var validationField in fieldRuleset) {
            // IE adds a function to the ruleset - skip it
            if (typeof(fieldRuleset[validationField]) == "function") {
                continue;
            }

			// Extract the regular expression itself and its modifiers, which come in
			// the form '/<regex>/<modifiers>'
			var fieldRegexStr         = fieldRuleset[validationField].expression.substr(1);
			var fieldRegexModifierPos = fieldRegexStr.lastIndexOf('/');
			fieldRegexModifier        = fieldRegexStr.substr(fieldRegexModifierPos + 1);
			fieldRegexStr             = fieldRegexStr.substr(0, fieldRegexModifierPos);
			
			// Create the regular expression object
			var fieldRegex = new RegExp(fieldRegexStr, fieldRegexModifier);
			
			// Increment the error count if the test fails
			if (!fieldRegex.test(fieldValue)) {
				++errors;
			}
		}
		
		// Update the class of the validation element
		if (errors > 0) {
			$(this).removeClass('valid').addClass('error');
		}
		else {
			$(this).removeClass('error').addClass('valid');
		}
	}
});


// Initialize the validation when the document is ready loading
$(document).ready(function() {
	$(document).initValidation();
});

