function formValidator(parentForm, fields) {
	me = this;
	this.parent = $(parentForm);
	this.errors = [];
	
	this.keys = {
		numeric: {zero: 48,one: 49,two: 50,three: 51,
				four: 52,five: 53,six: 54,seven: 55,
				eight: 56,nine: 57},
		padNumeric: {zero: 96,one: 97,two: 98,three: 99,
					four: 100,five: 101,six: 102,seven: 103,
					eight: 104,nine: 105}
	};
	
	this.disableNumeric = function(input) {
		$(me.parent).find(input).bind('keydown', function(e) {
			if(!me.isNumericKey(e)) {
				e.preventDefault();
			}
		});
	}
	
	this.isNumericKey = function(e) {
		if((e.keyCode == me.keys.numeric.zero || e.keyCode == me.keys.numeric.one || e.keyCode == me.keys.numeric.two
		|| e.keyCode == me.keys.numeric.three || e.keyCode == me.keys.numeric.four || e.keyCode == me.keys.numeric.five
		|| e.keyCode == me.keys.numeric.six || e.keyCode == me.keys.numeric.seven || e.keyCode == me.keys.numeric.eight
		|| e.keyCode == me.keys.numeric.nine) || (e.keyCode == me.keys.padNumeric.zero || e.keyCode == me.keys.padNumeric.one || e.keyCode == me.keys.padNumeric.two
		|| e.keyCode == me.keys.padNumeric.three || e.keyCode == me.keys.padNumeric.four || e.keyCode == me.keys.padNumeric.five
		|| e.keyCode == me.keys.padNumeric.six || e.keyCode == me.keys.padNumeric.seven || e.keyCode == me.keys.padNumeric.eight
		|| e.keyCode == me.keys.padNumeric.nine)) {
			return true;
		}
		return false;
	}
	
	this.parent.bind('submit', function(e) {
		me.runRules(e, fields);
	});
	
	this.checkNum = function(ruleObj, str) {
		try {
			if (str != parseInt(str)) {
				throw ((typeof ruleObj.nicename != 'undefined') ? ruleObj.nicename : 'This') + ' m&aring;ste vara enbart siffror.';
			} else {
				return true;
			}
		} catch(Err) {
			this.addError(ruleObj, Err);
		}
	}
	
	this.checkAlpha = function(ruleObj, str) {
		try {
			if (!/^[0-9a-zA-Z]+$/.test(str)) {
				throw ((typeof ruleObj.nicename != 'undefined') ? ruleObj.nicename : 'This') + ' is not alphanumeric [a-zA-Z0-9}';
			} else {
				return true;
			}
		} catch(Err) {
			this.addError(ruleObj, Err);
		}
	}
	
	this.checkMinLength = function(ruleObj, str) {
		try {
			if(typeof ruleObj.values.minLength == 'undefined') {
				console.log('You need to specify a minLength');
			} else {
				if (!(str.length >= ruleObj.values.minLength)) {
					throw ((typeof ruleObj.nicename != 'undefined') ? ruleObj.nicename : 'This') + ' m&aring;ste vara ifyllt.';
				} else {
					return true;
				}
			}
		} catch(Err) {
			this.addError(ruleObj, Err);
		}
    }

    this.checkCompare = function (ruleObj, str) {
        try {
            if (typeof ruleObj.values.compareValue == 'undefined') {
                console.log('You need to specify a compareValue');
            } else {

                var valueToCompare = $(ruleObj.values.compareValue).val();

                if (str != valueToCompare) {
                    throw ((typeof ruleObj.nicename != 'undefined') ? ruleObj.nicename : 'This') + ' m&aring;ste fyllas i likadant tv&aring; g&aring;nger.';
                } else {
                    return true;
                }
            }
        } catch (Err) {
            this.addError(ruleObj, Err);
        }
    }
	
	this.checkMaxLength = function(ruleObj, str) {
		try {
			if(typeof ruleObj.values.maxLength == 'undefined') {
				console.log('You need to specify a maxLength');
			} else {
				if (str.length > ruleObj.values.maxLength) {
					throw ((typeof ruleObj.nicename != 'undefined') ? ruleObj.nicename : 'This') + ' får inte vara längre än ' + ruleObj.values.maxLength + ' siffror.';
				} else {
					return true;
				}
			}
		} catch(Err) {
			this.addError(ruleObj, Err);
		}
	}
	
	this.validEmail = function(ruleObj, str) {
		var pattern = new RegExp('/[a-zA-Z0-9\._%-\+]+@[a-zA-Z0-9\.-]+\.[a-zA-Z]{2,4}/');
		try {
			if (!str.match(pattern)) {
				throw ((typeof ruleObj.nicename != 'undefined') ? ruleObj.nicename : 'This') + ' &auml;r ej en korrekt epost-adress.';
			} else {
				return true;
			}
		} catch(Err) {
			this.addError(ruleObj, Err);
		}
    }
    this.IsNumeric = function (ruleObj, str) {
        try {
            if (IsNumeric(str)) {
                throw ((typeof ruleObj.nicename != 'undefined') ? ruleObj.nicename : 'This') + ' &auml;r ej en korrekt epost-adress.';
            } else {
                return true;
            }
        } catch (Err) {
            this.addError(ruleObj, Err);
        }
    }

	
	this.trim = function(ruleObj, str) {
		var trimmed = str.replace(/^\s+|\s+$/g, '');
		return trimmed;
	}

	this.runRules = function (e, rules) {
	    this.errors = [];
	    for (var i = 0 in rules) {
	        var ruleObj = rules[i],
				ruleSet = ruleObj.ruleSet.split('|'),
				value = ($(ruleObj.input).val() != $(ruleObj.input).attr('title')) ? $(ruleObj.input).val() : '';
	        for (var x = 0 in ruleSet) {
	            var rule = ruleSet[x];
	            switch (rule) {
	                case 'trim':
	                    var newVal = this.trim(ruleObj, value);
	                    $(ruleObj.input).val(newVal);
	                    break;
	                case 'numeric':
	                    this.checkNum(ruleObj, value);
	                    break;
	                case 'alphanumeric':
	                    this.checkAlpha(ruleObj, value);
	                    break;
	                case 'maxLength':
	                    this.checkMaxLength(ruleObj, value);
	                    break;
	                case 'minLength':
	                    this.checkMinLength(ruleObj, value);
	                    break;
	                case 'validEmail':
	                    this.validEmail(ruleObj, value);
	                    break;
	                case 'compare':
	                    this.checkCompare(ruleObj, value);
	                    break;
	                case 'isNumeric':
                        
	                    break;
	                default:
	                    console.log('Rule \'' + rule + '\' doesn\'t exist!');
	                    break;
	            }
	        }
	    }
	    if (this.errors.length > 0) {
	        e.preventDefault();
	        this.displayErrors();
	    } else {
	        return true;
	    }
	}
	
	this.displayErrors = function() {
		var errorList = $(this.parent).find('ul.validation-errors'),
			i = 0;
		if(errorList.length <= 0) {
			$(me.parent).append('<ul class="validation-errors"></ul>');
			errorList = $(this.parent).find('ul.validation-errors');
		} else {
			errorList.empty();
		}
		$(this.parent).find('input.validation-error').removeClass('validation-error');
		for(i in this.errors) {
			var error = this.errors[i];
			if(!$(error.input).hasClass('validation-error')) {
				$(error.input).addClass('validation-error');
			}
			errorList.append('<li>' + error.errorStr + '</li>');
		}
		$('.input.error').eq(0).focus();
	}
	
	this.addError = function(ruleObj, errorStr) {
		this.errors.push({input: $(ruleObj.input), errorStr: errorStr});
	}
}
