/*********************************/
/* javascript by gonchuki - 2007 */
/*********************************************************************/
/* CEO Validator: based on code and documentation by Fernando Doglio */
/*********************************************************************/

var CEO = CEO || {};

CEO.Validator = {
	
	validations: [],
	field_regexp: /rq_([^_]+(_[^_]+)?)_([a-z]+)/,
	
	/* re-bind functions with external apis if available */
	init: function() {
		if (typeof $ == 'function') this.$ = $;
	},
	
	add_validation: function (key, validation) {
		this.validations[key] = validation;
	},
	
	validate: function(form, no_jump, paint_field, no_error) {
		var vv = this.validations;
		var valid = true;
		var fields = form.elements;
		var matches = [];
		
		for (var i = 0; i < fields.length; i++) {
			var field = fields[i];
			if (field.getAttribute('id')) {
				if (matches = field.getAttribute('id').match(this.field_regexp)) {
					/* get the container */
					var container = this.$('container_' + field.name) || this.$('container_' + matches[1]);
					
					valid &= this.run_validation_on_field(field, matches[3], container, paint_field);
				}
			}
		}
		
		if (!valid) {
			if (!no_error && this.$('error')) this.$('error').style.display = 'block';
			if (!no_jump) window.location.href = window.location.href.split('#')[0] + '#error';
		} else {
			if (!no_error && this.$('error')) this.$('error').style.display = 'none';
		}
		
		return Boolean(valid);
	},
	
	run_validation_on_field: function(field, key, container, paint_field) {
		/* assume valid if no validation available for this field */
		if (!this.validations[key]) return true;
		
		/* validate */
		var result = this.validations[key](field);
		
		if (container) {
			if (!result)
				this.mark_error(container, field);
			else
				this.clean_error(container, field);
		}
		
		if (paint_field) {
			if (!result)
				this.mark_error(field);
			else
				this.clean_error(field);
		}
		
		return result;
	},
	
	clone_validation: function(key) {
		return this.validations[key];
	},
	
	mark_error: function(container, field) {
		if (!this.has_attr(container, 'error_bucket', field.id )) {
			this.add_attr(container, 'className', 'error');
			this.add_attr(container, 'error_bucket', field.id);
		}
	},
	
	clean_error: function(container, field) {
		if (this.has_attr(container, 'error_bucket', field.id )) {
			this.remove_attr(container, 'error_bucket', field.id);
			if (container['error_bucket'] == '') this.remove_attr(container, 'className', 'error');
		}
	},
	
	has_attr: function(container, attr, value) {
		return (' ') ? (' ' + container[attr] + ' ').indexOf(' ' + value + ' ') > -1 : container[attr].indexOf(value) > -1;   
	},
	
	add_attr: function(container, attr, value) {
		if (!this.has_attr(container, attr, value)) container[attr] = ( (typeof container[attr] != 'undefined' ? container[attr] + ' ' : '' ) + value).replace(/\s{2,}/g, ' ').replace(/^\s+|\s+$/g, '');
	},
	
	remove_attr: function(container, attr, value) {
		container[attr] = container[attr].replace(new RegExp('(^|\\s)' + value + '(?:\\s|$)'), '$1').replace(/\s{2,}/g, ' ').replace(/^\s+|\s+$/g, '');
	},
	
	$: function(el) {
		return document.getElementById(el);
	}
	
};


/* -- standard validations -- */

/* str, txt: at least one letter from the alphabet */
CEO.Validator.add_validation('str', function(field){ return(/\w+/.test(field.value)); });
CEO.Validator.add_validation('txt', CEO.Validator.clone_validation('str'));
/* mail: email validation with full RFC 2822 compliance http://tools.ietf.org/html/rfc2822 */
CEO.Validator.add_validation('mail', function(field){ return(/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/.test(field.value)); });


/* -- init -- */
CEO.Validator.init();