jQuery.fn.containsOption = function(query) {
	var found = false;
	
	this.each(
		function() {
			if (this.nodeName.toLowerCase() == 'select') {
				for (var i = 0; i < this.options.length; i++) {
					if (query.value) {
						found = (query.value.constructor == RegExp) ? 
							this.options[i].value.match(query.value) : 
							this.options[i].value == query.value;
					} else if (query.text) {
						found = (query.text.constructor == RegExp) ? 
							this.options[i].text.match(query.text) : 
							this.options[i].text == query.text;
					}
					
					if (found)
						break;
				}
			} else return this;
		}
	);
	
	return found;
};

jQuery.fn.addOption = function(o) {
	var opt = o;
	
	this.each(
		function()
		{
			if (this.nodeName.toLowerCase() == 'select') {
				var option = document.createElement('OPTION');
				option.value = opt.value;
				option.text = opt.text;
				
				if (opt.selected)
					option.selected = opt.selected;
		
				this.options[this.options.length] = option;
			}
			else return this;
		}
	);
	
	return this;
};

jQuery.fn.clearOptions = function() {
	this.each(
		function () {
			if (this.nodeName.toLowerCase() == 'select') {
				this.options.length = 0;
			}
		}
	);
};

jQuery.fn.removeOption = function(val) {
	this.each(
		function() {
			if (this.nodeName.toLowerCase() == 'select') {
				for (var i = 0; i < this.options.length; i++) {
					if (this.options[i].value == val) {
						this.options[i] = null;
					}
				}
			} else return this;
		}
	);
	
	return this;
};

jQuery.fn.extend({
	validateFields : function(options) {
		var valid = true;
		
		this.each(function() {
			var thisValid = jQuery.formValidation.validateFields(this, options);
			if (!thisValid)
				valid = false;
		});
		
		return valid;
	}
});

jQuery.formValidation = {
	decimalPattern : /^(\d+\.\d{0,2}|\d+|\.\d{0,2})$/,
	imageFilePattern : /^.*(\.jpg|\.gif|\.png|\.jpeg)$/,
	emailPattern : /^[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,4}$/,
	fieldPattern : ':text, SELECT, TEXTAREA, :checkbox, :radio, DIV.validate_selected',
	
	validateFields : function(container, options) {
		var valid = true;
		jQuery.formValidation.findFields(container).filter('[@class *= "validate_"]').each(function() {
			var fieldValid = jQuery.formValidation.validateField(this);

			if (!fieldValid) {
				valid = false;
				
				if (options && options.onInvalid)
					options.onInvalid(this);
			} else {
				if (options && options.onValid)
					options.onValid(this);
			}
		});
		
		return valid;
	},
	
	validateField : function(field) {
		var valid = true;
		
		if (jQuery(field).is('.validate_nonBlank')) {
			if (!jQuery.formValidation.validateNonEmpty($(field).val())) {
				valid = false;
			}
		}

		if (jQuery(field).is('.validate_selected')) {
			if (!jQuery.formValidation.validateSelected(field)) {
				valid = false;
			}
		}

		if (jQuery(field).is('.validate_currency')) {
			if (!jQuery.formValidation.validatePrice($(field).val())) {
				valid = false;
			}
		}

		if (jQuery(field).is('.validate_percentage')) {
			if (!jQuery.formValidation.validatePercentage($(field).val())) {
				valid = false;
			}
		}
		
		if (jQuery(field).is('.validate_imageFile')) {
			if (!jQuery.formValidation.validateImageFile($(field).val())) {
				valid = false;
			}
		}
		
		if (jQuery(field).is('.validate_email')) {
			if (!jQuery.formValidation.validateEmailAddress($(field).val())) {
				valid = false;
			}
		}
		
		return valid;
	},
	
	isValidField : function(field) {
		return jQuery(field).is(jQuery.formValidation.fieldPattern);
	},
	
	findField : function(container) {
		if (jQuery(container).is(jQuery.formValidation.fieldPattern)) {
			return jQuery(container);
		}
		else {
			
			var fields = jQuery(jQuery.formValidation.fieldPattern, container);
		
			if (fields) {
				return fields.get(0);
			}
			else return null;
		}
	},
	
	findFields : function(container) {
		if (jQuery(container).is(jQuery.formValidation.fieldPattern))
			return jQuery(container);
		else
			return jQuery(jQuery.formValidation.fieldPattern, container);
	},
	
	validateNonEmpty : function(val) {
		if (val != null) {
			if (jQuery.trim(val) == '')
				return false;
				
		} else return false;
		
		return true;
	},
	
	validateDecimal : function(val) {
		if (jQuery.formValidation.validateNonEmpty(val)) {
			if (!val.match(jQuery.formValidation.decimalPattern))
				return false;
		} else return false;
		
		return true;
	},
	
	validatePrice : function(val) {
		if (jQuery.formValidation.validateNonEmpty(val)) {
			if (!jQuery.formValidation.validateDecimal(val)) {
				return false;
			} else if (parseFloat(val) < 1.00 || parseFloat(val) > 100000000.00) {
				return false;
			}
		} else return false;
		
		return true;
	},
	
	validatePercentage : function(val) {
		if (jQuery.formValidation.validateNonEmpty(val)) {
			if (!jQuery.formValidation.validateDecimal(val)) {
				return false;
			} else if (parseFloat(val) < 0.0 || parseFloat(val) > 100.0) {
				return false;
			}
		} else return false;
		
		return true;
	},
	
	validateEmailAddress : function (val) {
		if (jQuery.formValidation.validateNonEmpty(val)) {
			if (!val.match(jQuery.formValidation.emailPattern))
				return false;
		} else return false;
		
		return true;
	},
	
	validateImageFile : function(val) {
		if (jQuery.formValidation.validateNonEmpty(val)) {
			if (!val.match(jQuery.formValidation.imageFilePattern))
				return false;
		} else return false;
		
		return true;
	},
	
	validateSelected : function(field) {
		if (jQuery(field).is('SELECT')) {
			if (jQuery.trim(jQuery('option:selected', field).val()) == '')
				return false;
		} 
		else {	//look for a list of checkboxes or radio buttons
			var inputs = jQuery(':checkbox, :radio', field);
			
			if (inputs && inputs.length > 0) {
				if (!inputs.is('[@checked]'))
					return false;
			}
		}
		
		return true;
	}
};