/* ** Validator.js: ** author: John Chesley john at cheslicious dot com ** december 16, 2009 ** ** Two classes are defined here: Validator() and Filter() ----- Validator usage: var v = new Validator(); v.validate(validation_spec, value); available validation specs: currency, number, decimal, string, date, length, blank combine specs by separating them with a semi-colon; specify arguments to specs by putting them after a colon and separate them with a comma: 'length:max,min' - min is optional 'length:max' also works ----- Filter usage: var f = new Filter(); var s = f.filter(filters, string_to_filter); available filters: 'whitespace', 'dashes', 'parens' combine filters by separating them with a smi-colon ----- */ function Validator() { var regex = { decimal: /^-?\d{1,3}(,?\d\d\d)*(\.\d{0,2})?$/, currency:/^(-|\$)?\d{1,3}(,?\d\d\d)*(\.\d{0,2})?$/, number: /^[\d]+$/, string: /^[\w]+$/, date: /^([01]?[0-9]{1})(\/|-)([0-3]?[0-9]{1})(\/|-)([0-9]{4})$/ } var checkRegexp = function(val,regexp) { return regexp.test(val); } this.currency = function() { var value = arguments[0]; parens = /^\((.*)\)$/; if (!value) value = ""; else if (typeof(value) != 'string') value = String(value); if (m = value.match(parens)) value = m[1]; // strip off parens return checkRegexp(value, regex.currency); }; this.number = function(args) { var value = args[0]; return checkRegexp(value, regex.number); }; this.decimal = function(args) { var value = args[0]; return checkRegexp(value, regex.decimal); } this.string = function(args) { var value = args[0]; return checkRegexp(value, regex.string); } // first check that the text *could* be a date // then try to parse date info (fails if you try // for ex. 24/24/2009) // works on dates in format mm/dd/yyyy this.date = function(args) { var value = String(args[0]); if (!checkRegexp(value, regex.date)) return false; var m = value.match(regex.date); var d = new Date(value); return (d.getFullYear() == m[5] && d.getMonth()+1 == m[1] && d.getDate() == m[3]); } /* length([value, max, min]): ** value: string to check ** max: maximum length of value ** min: optional minumum lenght of value */ this.length = function(args) { var value = String(args[0]), max = parseInt(args[1]), min = parseInt(args[2]); if (value.length > max || (min && value.length < min)) return false; return true; } /* blank([value]): ** ** returns true if value is blank ** in the validate() method, this is a special case-- ** if blank is the only validation spec, it will return false ** if the value isn't blank ** if there are other validation filters, the result will depend on ** the results of those checks */ this.blank = function(args) { return String(args[0]) == "" } this.validate = function(specs, value) { var value = String(value); var specs = String(specs).split(/;/); var ret = true; for (var i in specs) { if (typeof specs[i] == 'function') { continue; } var spec = specs[i].split(/:/); var fn = spec.shift(); if (this[fn] === undefined) { continue; } // ignore unknown functions // allow for multiple arguments and push the value as the first arg var args = String(spec.shift()).split(/,/); args.unshift(value); if (fn == 'blank') { if (this[fn](args)) { return true; } else if (specs.length <= 1) { return false; } } else { ret = ret && this[fn](args); } } return ret; } } function Filter() { var regex = { whitespace: RegExp('[\\s]+', 'g'), dashes: RegExp('[-]+', 'g'), parens: RegExp('[()]+', 'g') }; this.filter = function(filters, value) { filters = String(filters).split(/;/); value = String(value); for (var f in filters) { if (typeof filters[f] == 'function') { continue; } if (regex[filters[f]]) { value = value.replace(regex[filters[f]], ''); } } return value; } }