From 5858909a6a5c6cfe4e77ff677e61286597ac1913 Mon Sep 17 00:00:00 2001 From: Philip Diffenderfer Date: Mon, 6 Jun 2016 01:06:40 -0400 Subject: [PATCH] Updated build & README.md --- Gulpfile.js | 45 ++-- README.md | 211 ++++++++++++++- build/rekord-validation.js | 409 +++++++++++++++-------------- build/rekord-validation.min.js | 1 + build/rekord-validation.min.js.map | 2 +- package.json | 6 +- 6 files changed, 450 insertions(+), 224 deletions(-) diff --git a/Gulpfile.js b/Gulpfile.js index ef5b94d..76f6256 100644 --- a/Gulpfile.js +++ b/Gulpfile.js @@ -1,5 +1,7 @@ 'use strict'; +var fs = require('fs'); +var pkg = JSON.parse( fs.readFileSync('./package.json') ); var gulp = require('gulp'); var sourcemaps = require('gulp-sourcemaps'); var plugins = require('gulp-load-plugins')(); @@ -9,6 +11,8 @@ var shell = require('gulp-shell'); var merge = require('merge-stream'); var size = require('gulp-check-filesize'); var jshint = require('gulp-jshint'); +var rename = require('gulp-rename'); +var insert = require('gulp-insert'); var build = { filename: 'rekord-validation.js', @@ -21,14 +25,19 @@ var build = { ] }; +var comments = [ + "/*", pkg.name, pkg.version, '-', pkg.description, 'by', pkg.author, "*/\n" +]; + var executeMinifiedBuild = function(props) { return function() { return gulp - .src( props.include ) + .src( props.output + props.filename ) + .pipe( rename( props.minified ) ) .pipe( sourcemaps.init() ) - .pipe( plugins.concat( props.minified ) ) .pipe( plugins.uglify().on('error', gutil.log) ) + .pipe( insert.prepend( comments.join(' ') ) ) .pipe( sourcemaps.write('.') ) .pipe( size({enableGzip: true}) ) .pipe( gulp.dest( props.output ) ) @@ -42,11 +51,12 @@ var executeBuild = function(props) return gulp .src( props.include ) .pipe( plugins.concat( props.filename ) ) + .pipe( insert.prepend( comments.join(' ') ) ) .pipe( size({enableGzip: true}) ) .pipe( gulp.dest( props.output ) ) - .pipe(jshint()) - .pipe(jshint.reporter('default')) - .pipe(jshint.reporter('fail')) + .pipe( jshint() ) + .pipe( jshint.reporter('default') ) + .pipe( jshint.reporter('fail') ) ; }; }; @@ -54,23 +64,28 @@ var executeBuild = function(props) var executeTest = function(file) { return function() { - return gulp.src( file ).pipe( qunit() ); + return gulp + .src( file ) + .pipe( qunit() ) + ; }; }; gulp.task('lint', function() { return gulp - .src(build.output + build.filename) - .pipe(jshint()) - .pipe(jshint.reporter('default')) - .pipe(jshint.reporter('fail')) + .src( build.output + build.filename ) + .pipe( jshint() ) + .pipe( jshint.reporter('default') ) + .pipe( jshint.reporter('fail') ) ; }); +gulp.task( 'js', executeBuild( build ) ); +gulp.task( 'js:min', ['js'], executeMinifiedBuild( build ) ); + +gulp.task( 'default', ['js:min']); + +gulp.task( 'test', ['js'], executeTest( './test/index.html' ) ); + gulp.task( 'docs', shell.task(['./node_modules/.bin/jsdoc -c jsdoc.json'])); gulp.task( 'clean', shell.task(['rm -rf build/*.js', 'rm -rf build/*.map'])); -gulp.task( 'test', executeTest( './test/index.html' ) ); - -gulp.task( 'js:min', executeMinifiedBuild( build ) ); -gulp.task( 'js', executeBuild( build ) ); -gulp.task( 'default', ['js:min', 'js']); diff --git a/README.md b/README.md index f86bf1f..b858476 100644 --- a/README.md +++ b/README.md @@ -14,5 +14,212 @@ rekord-validation adds rules, expressions, transforms, and custom validation fun The easiest way to install rekord-validation is through bower via `bower install rekord-validation`. -- rekord-validation.js is `46KB` (`7.55KB` gzipped) -- rekord-validation.min.js is `18KB` (`5.24KB` gzipped) +- rekord-validation.js is `45KB` (`7.6KB` gzipped) +- rekord-validation.min.js is `18KB` (`5.3KB` gzipped) + +### Example + +```javascript +// Simplest rule definition +var Task = Rekord({ + name: 'task', + fields: ['name', 'done', 'done_at'], + validation: { + rules: { + name: 'required|alpha_dash', + done: 'yesno', + done_at: 'if:done:accepted|required|date_like' + }, + required: true // the rules must pass to $save model instances + } +}); + +var t0 = new Task({name: '^', done: true}); +t0.$save(); +t0.$valid; // false +t0.$validationMessages; // array of below messages +t0.$validations; /* { + name: 'name should only contain alpha-numeric characters, dashes, and underscores.', + done_at: 'done_at is required.' +} */ + +// You can use aliases to make messages friendlier +var Task = Rekord({ + name: 'task', + fields: ['name', 'done', 'done_at'], + validation: { + rules: { + name: 'required|alpha_dash', + done: 'yesno', + done_at: 'if:done:accepted|required|date_like' + }, + aliases: { + name: 'Task name', + done: 'Task completed', + done_at: 'Task completed at' + } + } +}); + +var t1 = new Task({name: '', done: false}); +t1.$save(); /* { + name: 'Task name is required.' +} */ + +var t2 = new Task({name: 'task2', done: true, done_at: 'not date'}); +t2.$save(); /* { + done_at: 'Task completed at must be a valid date.' +} */ + +// You can specify field level custom messages +var Task = Rekord({ + name: 'task', + fields: ['name', 'done', 'done_at'], + validation: { + rules: { + name: 'required|alpha_dash', + done: 'yesno', + done_at: 'if:done:accepted|required|date_like' + }, + messages: { + name: 'Task name is required and must be alpha-numeric and can contain dashes and hyphens.', + done_at: 'When a task is completed, the completed date is required.' + } + } +}); + +var t3 = new Task({name: '?', done: true, done_at: 'not date'}); +t3.$save(); /* { + name: 'Task name is required and must be alpha-numeric and can contain dashes and hyphens.', + done_at: 'When a task is completed, the completed date is required.' +} */ + +// You can specify rule level custom messages +var Task = Rekord({ + name: 'task', + fields: ['name', 'done', 'done_at'], + validation: { + rules: { + name: { + 'required': false, // defaults to field level - then default + 'alpha_dash': 'Task name must be alpha-numeric and can contain dashes and hyphens.' + }, + done: 'yesno', + done_at: { + 'if:done:accepted': false, // defaults to field level - then default + 'required': 'Task completed date is required when the task is complete.', + 'date_like': 'Task completed date must be a valid date when the task is complete.' + } + }, + aliases: { + name: 'Task name' + } + } +}); + +var t4 = new Task({name: '?', done: true, done_at: 'not date'}); +t4.$save(); /* { + name: 'Task name must be alpha-numeric and can contain dashes and hyphens.', + done_at: 'Task completed date must be a valid date when the task is complete.' +} */ + +var t5 = new Task({done: true}); +t5.$save(); /* { + name: 'Task name is required.', + done_at: 'Task completed date is required when the task is complete.' +} */ + +// There are even more specific ways to define rules - depending on the rule. +// Check out the tests! + +``` + +### Concepts + +- "date like": number (millis since Unix Epoch), Date object, or string that can be parsed with `Date.parse` +- "number like": number or a string that begins with a number + +### Rules + +#### Simple +- `accepted`: The field must be an accepted value (1, yes, on, y, or true) +- `after:date`: If the field is like a date, it must be after the given `date` expression +- `after_on:date`: If the field is like a date, it must be on or after the given `date` expression +- `before:date`: If the field is like a date, it must be before the given `date` expression +- `before_on:date`: If the field is like a date, it must be on or before the given `date` expression +- `date_like`: The field must look like a date (Date, number, or valid date string) +- `required_if:field,value0,valueN`: The field is required is another `field` has any of the given values +- `required_unless:field,value0,valueN`: The field is required if another `field` does not have any of the given values +- `confirmed:field`: The field must match another `field` +- `different:field`: The field must NOT match another `field` +- `if_valid:field0,fieldN`: The rules following this one for this field will not be executed if any of the `field`s are invalid at this point in time in validation +- `required_with:field0,fieldN`: The field is required if any of the `field`s have a non-empty value +- `required_with_all:field0,fieldN`: The field is required if all of the `field`s have a non-empty value +- `required_without:field0,fieldN`: The field is required if any of the `field`s have an empty value +- `required_without_all:field0,fieldN`: The field is required if all of the `field`s have an empty value +- `exists` `exists:models` `exists:models,field`: The field value must exist in the given database (`models` - or this if none specified) in the given `field` (this field if not given) +- `unique` `unique:models` `unique:models,field`: The field value must NOT exist in the given database (`models` - or this if none specified) in the given `field` (this field if not given) +- `if:rule0\|ruleN`: The rules following this one for this field will not be executed unless all `rule`s pass +- `if_any:rule0\|ruleN`: The rules following this one for this field will not be executed unless at lease one `rule` passes +- `if_not:rule0\|ruleN`: The rules following this one for this field will only be executed if all `rule`s fail +- `in:value0,valueN`: This field must have a value in the given `value`s +- `not_in:value0,valueN`: This field must NOT have a value in the given `value`s +- `between:start,end`: This field must have a size between (inclusive) the `start` and `end` (string, number, array, or object) +- `not_between:start,end`: This field must NOT have a size between (inclusive) the `start` and `end` (works with strings, numbers, arrays, object keys) +- `alpha`: The field should only contain alphabetic characters +- `alpha_dash`: The field should only contain alpha-numeric characters, dashes, and underscores +- `alpha_num`: The field should only contain alpha-numeric characters +- `email`: The field should look like an email +- `url`: The field should look like a URL +- `uri`: The field should look like a URI +- `phone`: The field should look like a phone number +- `regex:/rgx/`: The field should pass the regular expression +- `required`: The field must be a non-empty value +- `min:number`: The field must be at least `number` in size (string, number, array, or object) +- `greater_than:number`: The field must be greater than `number` in size (string, number, array, or object) +- `max:number`: The field must be no more than `number` in size (string, number, array, or object) +- `less_than:number`: The field must be less than `number` in size (string, number, array, or object) +- `equal:number`: The field must be equal to `number` in size (string, number, array, or object) +- `not_equal:number`: The field must not be equal to `number` in size (string, number, array, or object) +- `array`: The field must be an instance of Array +- `object`: The field must be an object (arrays count as objects) +- `string`: The field must be a string +- `number`: The field must be a number +- `boolean`: The field must be a boolean +- `model`: The field must be a model instance +- `whole`: The field must look like a whole number +- `numeric`: The field must look like a number +- `yesno`: The field must look like a boolean (true, t, yes, y, 1, false, f, no, n, 0) + +#### Relationship +- `contains:field,value`: The relation field must contain a model with at least one `field` matching the given `value` +- `not_contains:field,value`: The relation field must NOT contain a model with at least one `field` matching the given `value` +- `validate`: The relation field must contain all valid models + +### Expressions +Expressions can be passed to rules (like date rules) and are generated on validation + +- `MM/dd/yyyy`: Parses to a date time +- `field`: Takes a field value from the model being validated +- `-1 day`: Relative amount of time from current time (+-)N (ms,s,min,hr,day,month,wk,yr) +- `today`: Todays date (start of day) +- `tomorrow`: Tomorrows date (start of day) +- `yesterday`: Yesterdays date (start of day) + +### Transforms +Transforms modify the value being validated so all subsequent rules use the modified values. Some transforms can apply the modified value back to the model after validation. + +- `trim`: If the field value is a string, return the trimmed value +- `abs`: If the field value looks like a number, parse it and return the absolute value +- `ceil`: If the field value looks like a number, parse it and return the ceiling value +- `floor`: If the field value looks like a number, parse it and return the floored value +- `round`: If the field value looks like a number, parse it and return the rounded value +- `endOfDay`: If the field value looks like a date, return its end of day +- `startOfDay`: If the field value looks like a date, return its start of day +- `base64`: Base64 encode the current value +- `unbase64`: Un-base64 the current value +- `filter`: If the field value is an array or object, remove the null and undefined properties/elements +- `mod:number`: If the field value looks like a number, parse it and return the remainder to the division between the field value and `number` + +- `null`: Apply null back to the model (can be used in conjuction with `if`) +- `apply`: Apply the currently transformed value back to the model diff --git a/build/rekord-validation.js b/build/rekord-validation.js index 1625a14..2b0d7d5 100644 --- a/build/rekord-validation.js +++ b/build/rekord-validation.js @@ -1,3 +1,4 @@ +/* rekord-validation 1.0.1 - Advanced validation rules for rekord by Philip Diffenderfer */ (function(global, Rekord, undefined) { var Model = Rekord.Model; @@ -543,6 +544,210 @@ Validation.Expressions.push(function(expr, database) } }) - 1; +Validation.Rules.abs = function(field, params, database, alias, message) +{ + return function(value, model, setMessage) + { + value = tryParseFloat( value ); + + if ( isNumber( value ) ) + { + value = Math.abs( value ); + } + + return value; + }; +}; + +Validation.Rules.apply = function(field, params, database, alias, message) +{ + return function(value, model, setMessage) + { + model.$set( field, value ); + + return value; + }; +}; + +Validation.Rules.base64 = function(field, params, database, alias, message) +{ + return function(value, model, setMessage) + { + if ( global.btoa ) + { + value = global.btoa( value ); + } + + return value; + }; +}; + +Validation.Rules.ceil = function(field, params, database, alias, message) +{ + return function(value, model, setMessage) + { + value = tryParseFloat( value ); + + if ( isNumber( value ) ) + { + value = Math.ceil( value ); + } + + return value; + }; +}; + +Validation.Rules.endOfDay = function(field, params, database, alias, message) +{ + return function(value, model, setMessage) + { + return endOfDay( value ); + }; +}; + +Validation.Rules.filter = function(field, params, database, alias, message) +{ + return function(value, model, setMessage) + { + if ( isArray( value ) ) + { + for (var i = value.length - 1; i >= 0; i--) + { + if ( !isValue( value[ i ] ) ) + { + value.splice( i, 1 ); + } + } + } + else if ( isObject( value ) ) + { + for (var prop in value) + { + if ( !isValue( value[ prop ] ) ) + { + delete value[ prop ]; + } + } + } + + return value; + }; +}; + +Validation.Rules.floor = function(field, params, database, alias, message) +{ + return function(value, model, setMessage) + { + value = tryParseFloat( value ); + + if ( isNumber( value ) ) + { + value = Math.floor( value ); + } + + return value; + }; +}; + +Validation.Rules.mod = function(field, params, database, alias, message) +{ + var number = tryParseFloat( params ); + + if ( !isNumber( number ) ) + { + throw '"' + number + '" is not a valid number for the mod rule.'; + } + + return function(value, model, setMessage) + { + value = tryParseFloat( value ); + + if ( isNumber( value ) ) + { + value = value % number; + } + + return value; + }; +}; + +Validation.Rules.null = function(field, params, database, alias, message) +{ + return function(value, model, setMessage) + { + model.$set( field, null ); + + return null; + }; +}; + +Validation.Rules.round = function(field, params, database, alias, message) +{ + return function(value, model, setMessage) + { + value = tryParseFloat( value ); + + if ( isNumber( value ) ) + { + value = Math.round( value ); + } + + return value; + }; +}; + +Validation.Rules.startOfDay = function(field, params, database, alias, message) +{ + return function(value, model, setMessage) + { + return startOfDay( value ); + }; +}; + +Validation.Rules.trim = function(field, params, database, alias, message) +{ + var trim = (function() + { + if ( String.prototype.trim ) + { + return function(x) { + return x.trim(); + }; + } + + var regex = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; + + return function(x) + { + return x.replace( regex, '' ); + }; + + })(); + + return function(value, model, setMessage) + { + if ( isString( value ) ) + { + value = trim( value ); + } + + return value; + }; +}; + +Validation.Rules.unbase64 = function(field, params, database, alias, message) +{ + return function(value, model, setMessage) + { + if ( global.atob ) + { + value = global.atob( value ); + } + + return value; + }; +}; + // accepted Validation.Rules.accepted = function(field, params, database, getAlias, message) { @@ -1789,210 +1994,6 @@ Validation.Rules.yesno.map = '0': false }; -Validation.Rules.abs = function(field, params, database, alias, message) -{ - return function(value, model, setMessage) - { - value = tryParseFloat( value ); - - if ( isNumber( value ) ) - { - value = Math.abs( value ); - } - - return value; - }; -}; - -Validation.Rules.apply = function(field, params, database, alias, message) -{ - return function(value, model, setMessage) - { - model.$set( field, value ); - - return value; - }; -}; - -Validation.Rules.base64 = function(field, params, database, alias, message) -{ - return function(value, model, setMessage) - { - if ( global.btoa ) - { - value = global.btoa( value ); - } - - return value; - }; -}; - -Validation.Rules.ceil = function(field, params, database, alias, message) -{ - return function(value, model, setMessage) - { - value = tryParseFloat( value ); - - if ( isNumber( value ) ) - { - value = Math.ceil( value ); - } - - return value; - }; -}; - -Validation.Rules.endOfDay = function(field, params, database, alias, message) -{ - return function(value, model, setMessage) - { - return endOfDay( value ); - }; -}; - -Validation.Rules.filter = function(field, params, database, alias, message) -{ - return function(value, model, setMessage) - { - if ( isArray( value ) ) - { - for (var i = value.length - 1; i >= 0; i--) - { - if ( !isValue( value[ i ] ) ) - { - value.splice( i, 1 ); - } - } - } - else if ( isObject( value ) ) - { - for (var prop in value) - { - if ( !isValue( value[ prop ] ) ) - { - delete value[ prop ]; - } - } - } - - return value; - }; -}; - -Validation.Rules.floor = function(field, params, database, alias, message) -{ - return function(value, model, setMessage) - { - value = tryParseFloat( value ); - - if ( isNumber( value ) ) - { - value = Math.floor( value ); - } - - return value; - }; -}; - -Validation.Rules.mod = function(field, params, database, alias, message) -{ - var number = tryParseFloat( params ); - - if ( !isNumber( number ) ) - { - throw '"' + number + '" is not a valid number for the mod rule.'; - } - - return function(value, model, setMessage) - { - value = tryParseFloat( value ); - - if ( isNumber( value ) ) - { - value = value % number; - } - - return value; - }; -}; - -Validation.Rules.null = function(field, params, database, alias, message) -{ - return function(value, model, setMessage) - { - model.$set( field, null ); - - return null; - }; -}; - -Validation.Rules.round = function(field, params, database, alias, message) -{ - return function(value, model, setMessage) - { - value = tryParseFloat( value ); - - if ( isNumber( value ) ) - { - value = Math.round( value ); - } - - return value; - }; -}; - -Validation.Rules.startOfDay = function(field, params, database, alias, message) -{ - return function(value, model, setMessage) - { - return startOfDay( value ); - }; -}; - -Validation.Rules.trim = function(field, params, database, alias, message) -{ - var trim = (function() - { - if ( String.prototype.trim ) - { - return function(x) { - return x.trim(); - }; - } - - var regex = /^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g; - - return function(x) - { - return x.replace( regex, '' ); - }; - - })(); - - return function(value, model, setMessage) - { - if ( isString( value ) ) - { - value = trim( value ); - } - - return value; - }; -}; - -Validation.Rules.unbase64 = function(field, params, database, alias, message) -{ - return function(value, model, setMessage) - { - if ( global.atob ) - { - value = global.atob( value ); - } - - return value; - }; -}; - Rekord.Validation = Validation; diff --git a/build/rekord-validation.min.js b/build/rekord-validation.min.js index ce2cba8..adb2bf2 100644 --- a/build/rekord-validation.min.js +++ b/build/rekord-validation.min.js @@ -1,2 +1,3 @@ +/* rekord-validation 1.0.1 - Advanced validation rules for rekord by Philip Diffenderfer */ !function(e,t,r){function n(e){var t=parseFloat(e);return isNaN(t)||(e=t),e}function a(e){var t=parseInt(e);return isNaN(t)||(e=t),e}function i(e){return z(e)?e.setHours(0,0,0,0):N(e)&&(e-=e%864e5),e}function s(e){return z(e)?e.setHours(23,59,59,999):N(e)&&(e=e-e%864e5+864e5-1),e}function u(e,t,r){K.Rules[e]=function(t,n,a,i,s){c(e,t,n);var u=o(e,s);return function(e,n,a){function s(t){e=t}return r(e,n,s)&&a(m(t,i(t),e,n,u)),e}},K.Rules[e].message=t}function o(e,t){return t||K.Rules[e].message}function l(e,t,r,n){var a=e.slice();if(n)for(var i=0;ie}),h("before","{$alias} must be before {$date}.",function(e,t){return e>t}),h("before_on","{$alias} must be before or equal to {$date}.",function(e,t){return e>s(t)}),u("date_like","{$alias} must be a valid date.",function(e,t,r){var n=U(e),a=n===!1;return a||r(n.getTime()),a}),v("required_if","{$alias} is required.",function(e,t,r,n,a){var i=a[t.$get(r)];return i&&A(e)}),v("required_unless","{$alias} is required.",function(e,t,r,n,a){var i=!a[t.$get(r)];return i&&A(e)}),$("confirmed","{$alias} must match {$fieldAliases}.",function(e,t,r,n){for(var a=!0,i=0;i0}),b("if_any",function(e,t){return e>=t}),b("if_not",function(e,t){return t>e}),p("in","{$alias} must be one of {$list}.",function(e,t,r){return!r(e,t)}),p("not_in","{$alias} must not be one of {$list}.",function(e,t,r){return r(e,t)}),R("between",{string:"{$alias} must have between {$start} to {$end} characters.",number:"{$alias} must be between {$start} and {$end}.",object:"{$alias} must have between {$start} to {$end} items."},function(e,t,r){return t>e||e>r}),R("not_between",{string:"{$alias} must not have between {$start} to {$end} characters.",number:"{$alias} must not be between {$start} and {$end}.",object:"{$alias} must not have between {$start} to {$end} items."},function(e,t,r){return e>=t&&r>=e}),w("alpha","{$alias} should only contain alphabetic characters.",/^[a-zA-Z]*$/),w("alpha_dash","{$alias} should only contain alpha-numeric characters, dashes, and underscores.",/^[a-zA-Z0-9_-]*$/),w("alpha_num","{$alias} should only contain alpha-numeric characters.",/^[a-zA-Z0-9]*$/),w("email","{$alias} is not a valid email.",/^.+@.+\..+$/),w("url","{$alias} is not a valid URL.",/^(https?:\/\/)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&\/\/=]*)$/),w("uri","{$alias} is not a valid URI.",/^(\w+:\/\/)?[-a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b([-a-zA-Z0-9@:%_\+.~#?&\/\/=]*)$/),w("phone","{$alias} is not a valid phone number.",/^1?\W*([2-9][0-8][0-9])\W*([2-9][0-9]{2})\W*([0-9]{4})(\se?x?t?(\d*))?$/),K.Rules.regex=function(e,t,r,n,a){var i;if(D(t)){var s=/^\/(.*)\/([gmi]*)$/.exec(t);s&&(i=new RegExp(s[1],s[2]))}else P(t)&&(i=t);if(!i)throw t+" is not a valid regular expression for the regex rule";var u=o("regex",a);return function(t,r,a){return i.test(t)||a(m(e,n(e),t,r,u)),t}},K.Rules.regex.message="{$alias} is not a valid value.",u("required","{$alias} is required.",function(e){return A(e)}),y("min",{string:"{$alias} must have a minimum of {$number} characters.",number:"{$alias} must be at least {$number}.",object:"{$alias} must have at least {$number} items."},function(e,t){return t>e}),y("greater_than",{string:"{$alias} must have more than {$number} characters.",number:"{$alias} must be greater than {$number}.",object:"{$alias} must have more than {$number} items."},function(e,t){return t>=e}),y("max",{string:"{$alias} must have no more than {$number} characters.",number:"{$alias} must be no more than {$number}.",object:"{$alias} must have no more than {$number} items."},function(e,t){return e>t}),y("less_than",{string:"{$alias} must have less than {$number} characters.",number:"{$alias} must be less than {$number}.",object:"{$alias} must have less than {$number} items."},function(e,t){return e>=t}),y("equal",{string:"{$alias} must have {$number} characters.",number:"{$alias} must equal {$number}.",object:"{$alias} must have {$number} items."},function(e,t){return e!==t}),y("not_equal",{string:"{$alias} must not have {$number} characters.",number:"{$alias} must not equal {$number}.",object:"{$alias} must not have {$number} items."},function(e,t){return e===t}),u("array","{$alias} must be an array.",function(e){return!M(e)}),u("object","{$alias} must be an object.",function(e){return!j(e)}),u("string","{$alias} must be a string.",function(e){return!D(e)}),u("number","{$alias} must be a number.",function(e){return!N(e)}),u("boolean","{$alias} must be a true or false.",function(e){return!k(e)}),u("model","{$alias} must have a value.",function(e){return!(e instanceof x)}),u("whole","{$alias} must be a whole number.",function(e,t,r){var n=a(e),i=parseFloat(e),s=!N(n);return s||(s=Math.floor(n)!==i,s||r(n)),s}),u("numeric","{$alias} must be numeric.",function(e,t,r){var a=n(e),i=!N(a);return i||r(a),i}),u("yesno","{$alias} must be a yes or no.",function(e,t,r){var n=K.Rules.yesno.map[e],a=!k(n);return a||r(n),a}),K.Rules.yesno.map={"true":!0,t:!0,yes:!0,y:!0,1:!0,"false":!1,f:!1,no:!1,n:!1,0:!1},K.Rules.abs=function(e,t,r,a,i){return function(e,t,r){return e=n(e),N(e)&&(e=Math.abs(e)),e}},K.Rules.apply=function(e,t,r,n,a){return function(t,r,n){return r.$set(e,t),t}},K.Rules.base64=function(t,r,n,a,i){return function(t,r,n){return e.btoa&&(t=e.btoa(t)),t}},K.Rules.ceil=function(e,t,r,a,i){return function(e,t,r){return e=n(e),N(e)&&(e=Math.ceil(e)),e}},K.Rules.endOfDay=function(e,t,r,n,a){return function(e,t,r){return s(e)}},K.Rules.filter=function(e,t,r,n,a){return function(e,t,r){if(M(e))for(var n=e.length-1;n>=0;n--)G(e[n])||e.splice(n,1);else if(j(e))for(var a in e)G(e[a])||delete e[a];return e}},K.Rules.floor=function(e,t,r,a,i){return function(e,t,r){return e=n(e),N(e)&&(e=Math.floor(e)),e}},K.Rules.mod=function(e,t,r,a,i){var s=n(t);if(!N(s))throw'"'+s+'" is not a valid number for the mod rule.';return function(e,t,r){return e=n(e),N(e)&&(e%=s),e}},K.Rules["null"]=function(e,t,r,n,a){return function(t,r,n){return r.$set(e,null),null}},K.Rules.round=function(e,t,r,a,i){return function(e,t,r){return e=n(e),N(e)&&(e=Math.round(e)),e}},K.Rules.startOfDay=function(e,t,r,n,a){return function(e,t,r){return i(e)}},K.Rules.trim=function(e,t,r,n,a){var i=function(){if(String.prototype.trim)return function(e){return e.trim()};var e=/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g;return function(t){return t.replace(e,"")}}();return function(e,t,r){return D(e)&&(e=i(e)),e}},K.Rules.unbase64=function(t,r,n,a,i){return function(t,r,n){return e.atob&&(t=e.atob(t)),t}},t.Validation=K,t.ruleGenerator=u,t.rangeRuleGenerator=R,t.collectionRuleGenerator=d,t.dateRuleGenerator=h,t.fieldListRuleGenerator=v,t.fieldsRuleGenerator=$,t.foreignRuleGenerator=g,t.subRuleGenerator=b,t.listRuleGenerator=p,t.regexRuleGenerator=w,t.sizeRuleGenerator=y,t.joinFriendly=l,t.tryParseFloat=n,t.tryParseInt=a,t.startOfDay=i,t.endOfDay=s,t.determineMessage=o,t.mapFromArray=f,t.checkNoParams=c,t.generateMessage=m}(this,this.Rekord); //# sourceMappingURL=rekord-validation.min.js.map diff --git a/build/rekord-validation.min.js.map b/build/rekord-validation.min.js.map index cb1ea1d..50fb603 100644 --- a/build/rekord-validation.min.js.map +++ b/build/rekord-validation.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["header.js","util.js","rules/collection.js","rules/dates.js","rules/field_list.js","rules/fields.js","rules/foreign.js","rules/if.js","rules/list.js","rules/range.js","rules/regex.js","rules/sizes.js","validation.js","expressions/date.js","expressions/field.js","expressions/relative.js","expressions/today.js","expressions/tomorrow.js","expressions/yesterday.js","rules/accepted.js","rules/required.js","rules/types.js","transforms/abs.js","transforms/apply.js","transforms/base64.js","transforms/ceil.js","transforms/endOfDay.js","transforms/filter.js","transforms/floor.js","transforms/mod.js","transforms/null.js","transforms/round.js","transforms/startOfDay.js","transforms/trim.js","transforms/unbase64.js","footer.js"],"names":["global","Rekord","undefined","tryParseFloat","x","parsed","parseFloat","isNaN","tryParseInt","parseInt","startOfDay","d","isDate","setHours","isNumber","endOfDay","ruleGenerator","ruleName","defaultMessage","isInvalid","Validation","Rules","field","params","database","getAlias","message","checkNoParams","messageTemplate","determineMessage","value","model","setMessage","setValue","newValue","generateMessage","joinFriendly","arr","lastSeparatorCustom","itemSeparatorCustom","copy","slice","i","length","last","pop","lastSeparator","itemSeparator","join","mapFromArray","map","alias","extra","isFunction","base","$field","$alias","$value","transfer","isObject","format","collectionRuleGenerator","matchField","matchValue","equality","isString","comma","indexOf","substring","isArray","equals","equalsCompare","fields","$matchField","$matchAlias","$matchValue","dateRuleGenerator","dateExpression","parseExpression","parseDate","parsedTime","getTime","noop","$date","date","fieldListRuleGenerator","matchValues","parts","split","shift","values","list","$params","$list","fieldsRuleGenerator","fieldNames","fieldAliases","$fields","$fieldAliases","foreignRuleGenerator","modelName","models","fieldName","isValue","name","ModelCollection","get","success","modelClass","all","isRekord","$class","subRuleGenerator","otherField","otherRules","colon","rules","validators","parseRules","invalids","setInvalid","Stop","listRuleGenerator","inList","isPrimitiveArray","rangeRuleGenerator","defaultMessages","start","end","range","string","number","object","$start","$end","size","sizeof","type","typeMessage","$size","regexRuleGenerator","regex","test","sizeRuleGenerator","$number","Model","Database","Promise","Collection","isEmpty","isBoolean","isRegExp","addMethod","replaceMethod","on","Events","Plugins","db","options","aliases","validation","Defaults","messages","required","validations","prototype","$this","this","$trigger","PreValidate","$valid","$validations","$validationMessages","chain","$get","fieldValid","push","ValidatePass","ValidateFail","$init","apply","arguments","$save","$isDeleted","debug","Debugs","SAVE_DELETED","$db","resolve","$validate","Expression","Expressions","Delimiter","Escape","RuleSeparator","rule","defaultMessageValidator","parseRule","ruleProperty","ruleMessageOrData","ruleMessage","ruleInput","input","customMessageValidator","charAt","customValidator","ruleParams","validatorFactory","expr","parsers","parser","expressionFunction","functionName","result","RELATIVE_REGEX","RELATIVE_UNITS","ms","millisecond","milliseconds","s","second","seconds","min","mins","minute","minutes","hr","hour","hours","day","days","wk","week","weeks","month","months","yr","year","years","relative","exec","amount","unit","unitScale","Date","setTime","getter","setter","today","tomorrow","setDate","getDate","yesterday","accepted","acceptable","valueString","toLowerCase","1","yes","y","true","contains","m","validate","messageOption","invalid","related","pluck","confirmed","different","valid","invalidCount","totalCount","RegExp","numeric","Math","floor","mapped","yesno","t","false","f","no","n","0","abs","$set","base64","btoa","ceil","filter","splice","prop","mod","round","trim","String","replace","unbase64","atob"],"mappings":"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","file":"rekord-validation.min.js","sourcesContent":["(function(global, Rekord, undefined)\n{\n var Model = Rekord.Model;\n var Database = Rekord.Database;\n var Promise = Rekord.Promise;\n var Collection = Rekord.Collection;\n var ModelCollection = Rekord.ModelCollection;\n\n var isEmpty = Rekord.isEmpty;\n var isString = Rekord.isString;\n var isArray = Rekord.isArray;\n var isObject = Rekord.isObject;\n var isFunction = Rekord.isFunction;\n var isDate = Rekord.isDate;\n var isNumber = Rekord.isNumber;\n var isBoolean = Rekord.isBoolean;\n var isValue = Rekord.isValue;\n var isPrimitiveArray = Rekord.isPrimitiveArray;\n var isRegExp = Rekord.isRegExp;\n var isRekord = Rekord.isRekord;\n\n var noop = Rekord.noop;\n var equalsCompare = Rekord.equalsCompare;\n var equals = Rekord.equals;\n var indexOf = Rekord.indexOf;\n var sizeof = Rekord.sizeof;\n\n var split = Rekord.split;\n var transfer = Rekord.transfer;\n var format = Rekord.format;\n\n var parseDate = Rekord.parseDate;\n\n var addMethod = Rekord.addMethod;\n var replaceMethod = Rekord.replaceMethod;\n","function tryParseFloat(x)\n{\n var parsed = parseFloat( x );\n\n if ( !isNaN( parsed ) )\n {\n x = parsed;\n }\n\n return x;\n}\n\nfunction tryParseInt(x)\n{\n var parsed = parseInt( x );\n\n if ( !isNaN( parsed ) )\n {\n x = parsed;\n }\n\n return x;\n}\n\nfunction startOfDay(d)\n{\n if ( isDate( d ) )\n {\n d.setHours( 0, 0, 0, 0 );\n }\n else if ( isNumber( d ) )\n {\n d = d - (d % 86400000);\n }\n\n return d;\n}\n\nfunction endOfDay(d)\n{\n if ( isDate( d ) )\n {\n d.setHours( 23, 59, 59, 999 );\n }\n else if ( isNumber( d ) )\n {\n d = d - (d % 86400000) + 86400000 - 1;\n }\n\n return d;\n}\n\nfunction ruleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n checkNoParams( ruleName, field, params );\n\n var messageTemplate = determineMessage( ruleName, message );\n\n return function(value, model, setMessage)\n {\n function setValue( newValue )\n {\n value = newValue;\n }\n\n if ( isInvalid( value, model, setValue ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n\nfunction determineMessage(ruleName, message)\n{\n return message || Validation.Rules[ ruleName ].message;\n}\n\nfunction joinFriendly(arr, lastSeparatorCustom, itemSeparatorCustom, getAlias)\n{\n var copy = arr.slice();\n\n if ( getAlias )\n {\n for (var i = 0; i < copy.length; i++)\n {\n copy[ i ] = getAlias( copy[ i ] );\n }\n }\n\n var last = copy.pop();\n var lastSeparator = lastSeparatorCustom || 'and';\n var itemSeparator = itemSeparatorCustom || ', ';\n\n switch (copy.length) {\n case 0:\n return last;\n case 1:\n return copy[ 0 ] + ' ' + lastSeparator + ' ' + last;\n default:\n return copy.join( itemSeparator ) + itemSeparator + lastSeparator + ' ' + last;\n }\n}\n\nfunction mapFromArray(arr, value)\n{\n var map = {};\n\n for (var i = 0; i < arr.length; i++)\n {\n map[ arr[ i ] ] = value;\n }\n\n return map;\n}\n\nfunction checkNoParams(ruleName, field, params)\n{\n if ( params )\n {\n throw 'the rule ' + ruleName + ' for field ' + field + ' has no arguments';\n }\n}\n\nfunction generateMessage(field, alias, value, model, message, extra)\n{\n if ( isFunction( message ) )\n {\n message = message( field, alias, value, model, extra );\n }\n\n var base = {};\n base.$field = field;\n base.$alias = alias;\n base.$value = value;\n\n transfer( model, base );\n\n if ( isObject( extra ) )\n {\n transfer( extra, base );\n }\n\n return format( message, base );\n}\n","// contains:field,value\ncollectionRuleGenerator('contains',\n '{$alias} does not contain an item whose {$matchAlias} equals {$matchValue}.',\n function isInvalid(value, model, matchField, matchValue, equality)\n {\n return !value.contains(function isMatch(m)\n {\n return m !== model && equality( matchValue, m.$get( matchField ) );\n });\n }\n);\n\n// not_contains:field,value\ncollectionRuleGenerator('not_contains',\n '{$alias} contains an item whose {$matchAlias} equals {$matchValue}.',\n function isInvalid(value, model, matchField, matchValue, equality)\n {\n return value.contains(function isMatch(m)\n {\n return m !== model && equality( matchValue, m.$get( matchField ) );\n });\n }\n);\n\nfunction collectionRuleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires field & value arguments';\n }\n\n var matchField, matchValue, equality;\n\n if ( isString( params ) )\n {\n var comma = params.indexOf(',');\n\n if ( comma === -1 )\n {\n throw ruleName + ' validation rule requires field & value arguments';\n }\n\n matchField = params.substring( 0, comma );\n matchValue = params.substring( comma + 1 );\n }\n else if ( isArray( params ) )\n {\n matchField = params[ 0 ];\n matchValue = params[ 1 ];\n equality = params[ 2 ];\n }\n else if ( isObject( params ) )\n {\n matchField = params.field;\n matchValue = params.value;\n equality = params.equals;\n }\n\n if ( !isFunction( equality ) )\n {\n equality = equalsCompare;\n }\n\n if ( indexOf( database.fields, matchField ) === -1 )\n {\n throw matchField + ' is not a valid field for the ' + ruleName + ' rule';\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var extra = {\n $matchField: matchField,\n $matchAlias: getAlias( matchField ),\n $matchValue: matchValue\n };\n\n return function(value, model, setMessage)\n {\n if ( isInvalid( value, model, matchField, matchValue, equality ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate, extra ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n\nValidation.Rules.validate = function(field, params, database, getAlias, message)\n{\n // message, models, validations\n var messageOption = params || 'message';\n var messageTemplate = determineMessage( 'validate', message );\n\n return function(value, model, setMessage)\n {\n if ( isArray( value ) )\n {\n var invalid = new Collection();\n\n for (var i = 0; i < value.length; i++)\n {\n var related = value[ i ];\n\n if ( related && related.$validate && !related.$validate() )\n {\n invalid.push( related );\n }\n }\n\n if ( invalid.length )\n {\n switch (messageOption)\n {\n case 'models':\n setMessage( invalid );\n break;\n case 'validations':\n setMessage( invalid.pluck( '$validations', '$$key' ) );\n break;\n default: // message\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate ) );\n break;\n }\n }\n }\n\n return value;\n };\n};\n\nValidation.Rules.validate.message = '{$alias} is not valid.';\n","// after:today\ndateRuleGenerator('after',\n '{$alias} must be after {$date}.',\n function isInvalid(value, date) {\n return value < endOfDay( date );\n }\n);\n\n// after_on:tomorrow\ndateRuleGenerator('after_on',\n '{$alias} must be after or equal to {$date}.',\n function isInvalid(value, date) {\n return value < date;\n }\n);\n\n// before:yesterday\ndateRuleGenerator('before',\n '{$alias} must be before {$date}.',\n function isInvalid(value, date) {\n return value > date;\n }\n);\n\n// before_on:+2days\ndateRuleGenerator('before_on',\n '{$alias} must be before or equal to {$date}.',\n function isInvalid(value, date) {\n return value > endOfDay( date );\n }\n);\n\n// date\nruleGenerator('date_like',\n '{$alias} must be a valid date.',\n function isInvalid(value, model, setValue) {\n var parsed = parseDate( value );\n var invalid = parsed === false;\n if ( !invalid ) {\n setValue( parsed.getTime() );\n }\n return invalid;\n }\n);\n\nfunction dateRuleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires a date expression argument';\n }\n\n var dateExpression;\n\n if ( isString( params ) )\n {\n dateExpression = Validation.parseExpression( params, database );\n }\n else if ( isFunction( params ) )\n {\n dateExpression = params;\n }\n else\n {\n var parsed = parseDate( params );\n\n if ( parsed !== false )\n {\n var parsedTime = parsed.getTime();\n\n dateExpression = function()\n {\n return parsedTime;\n };\n }\n }\n\n if ( !dateExpression || dateExpression === noop )\n {\n throw params + ' is not a valid date expression for the ' + ruleName + ' rule';\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var extra = {\n $date: params\n };\n\n return function(value, model, setMessage)\n {\n var parsed = parseDate( value );\n\n if ( parsed !== false )\n {\n value = parsed.getTime();\n\n var date = dateExpression( value, model );\n\n if ( isNumber( date ) && isInvalid( value, date ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate, extra ) );\n }\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n","\n// required_if:X,Y,...\nfieldListRuleGenerator('required_if',\n '{$alias} is required.',\n function isInvalid(value, model, field, values, map) {\n var required = map[ model.$get( field ) ];\n\n return required && isEmpty( value );\n }\n);\n\n// required_unless:X,Y,...\nfieldListRuleGenerator('required_unless',\n '{$alias} is required.',\n function isInvalid(value, model, field, values, map) {\n var required = !map[ model.$get( field ) ];\n\n return required && isEmpty( value );\n }\n);\n\nfunction fieldListRuleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires a field and list arguments';\n }\n\n var matchField, matchValues;\n\n if ( isString( params ) )\n {\n var parts = split( params, /(,)/, '\\\\' );\n\n matchField = parts.shift();\n matchValues = parts;\n }\n else if ( isArray( params ) )\n {\n matchField = params.shift();\n matchValues = params;\n }\n else if ( isObject( params ) )\n {\n matchField = params.field;\n matchValues = params.values;\n }\n\n if ( indexOf( database.fields, matchField ) === false )\n {\n throw matchField + ' is not a valid field for the ' + ruleName + ' rule';\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var list = joinFriendly( matchValues );\n var extra = {\n $params: params,\n $matchField: matchField,\n $matchAlias: getAlias( matchField ),\n $list: list\n };\n var map = mapFromArray( matchValues, true );\n\n return function(value, model, setMessage)\n {\n if ( isInvalid( value, model, matchField, matchValues, map ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate, extra ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n","// confirmed:X\nfieldsRuleGenerator('confirmed',\n '{$alias} must match {$fieldAliases}.',\n function isInvalid(value, model, fields, setValue) {\n var confirmed = true;\n\n for (var i = 0; i < fields.length; i++)\n {\n if ( !equals( value, model.$get( fields[ i ] ) ) )\n {\n confirmed = false;\n }\n }\n\n return !confirmed;\n }\n);\n\n// different:X\nfieldsRuleGenerator('different',\n '{$alias} must not match {$fieldAliases}.',\n function isInvalid(value, model, fields, setValue) {\n var different = false;\n\n for (var i = 0; i < fields.length; i++)\n {\n if ( !equals( value, model.$get( fields[ i ] ) ) )\n {\n different = true;\n }\n }\n\n return !different;\n }\n);\n\n// if_valid:X\nfieldsRuleGenerator('if_valid',\n '',\n function isInvalid(value, model, fields, setValue) {\n var valid = true;\n\n for (var i = 0; i < fields.length && valid; i++)\n {\n if ( model.$validations[ fields[ i ] ] )\n {\n valid = false;\n }\n }\n\n if ( !valid )\n {\n setValue( Validation.Stop );\n }\n\n return false;\n }\n);\n\n// The field under validation must be present only if any of the other specified fields are present.\n// required_with:X,Y,...\nfieldsRuleGenerator('required_with',\n '{$alias} is required.',\n function isInvalid(value, model, fields, setValue) {\n var required = false;\n\n for (var i = 0; i < fields.length && !required; i++)\n {\n if ( !isEmpty( model.$get( fields[ i ] ) ) )\n {\n required = true;\n }\n }\n\n return required && isEmpty( value );\n }\n);\n\n// The field under validation must be present only if all of the other specified fields are present.\n// required_with_all:X,Y,...\nfieldsRuleGenerator('required_with_all',\n '{$alias} is required.',\n function isInvalid(value, model, fields, setValue) {\n var required = true;\n\n for (var i = 0; i < fields.length && required; i++)\n {\n if ( isEmpty( model.$get( fields[ i ] ) ) )\n {\n required = false;\n }\n }\n\n return required && isEmpty( value );\n }\n);\n\n// The field under validation must be present only when any of the other specified fields are not present.\n// required_without:X,Y,...\nfieldsRuleGenerator('required_without',\n '{$alias} is required.',\n function isInvalid(value, model, fields, setValue) {\n var required = false;\n\n for (var i = 0; i < fields.length && !required; i++)\n {\n if ( isEmpty( model.$get( fields[ i ] ) ) )\n {\n required = true;\n }\n }\n\n return required && isEmpty( value );\n }\n);\n\n// The field under validation must be present only when all of the other specified fields are not present.\n// required_without_all:X,Y,...\nfieldsRuleGenerator('required_without_all',\n '{$alias} is required.',\n function isInvalid(value, model, fields, setValue) {\n var required = true;\n\n for (var i = 0; i < fields.length && required; i++)\n {\n if ( !isEmpty( model.$get( fields[ i ] ) ) )\n {\n required = false;\n }\n }\n\n return required && isEmpty( value );\n }\n);\n\nfunction fieldsRuleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires an array of fields argument';\n }\n\n var fields = split( params, /(\\s*,\\s*)/, '\\\\' );\n\n for (var i = 0; i < fields.length; i++)\n {\n if ( indexOf( database.fields, fields[ i ] ) === -1 )\n {\n throw fields[ i ] + ' is not a valid field for the ' + ruleName + ' rule';\n }\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var fieldNames = joinFriendly( fields );\n var fieldAliases = joinFriendly( fields, false, false, getAlias );\n var extra = {\n $fields: fieldNames,\n $fieldAliases: fieldAliases\n };\n\n return function(value, model, setMessage)\n {\n function setValue( newValue )\n {\n value = newValue;\n }\n\n if ( isInvalid( value, model, fields, setValue ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate, extra ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n","// exists:X,Y\nforeignRuleGenerator('exists',\n '{$alias} must match an existing {$matchAlias} in a {$class}',\n function isInvalid(value, model, models, fieldName)\n {\n return !models.contains(function isDifferentMatch(m)\n {\n return m !== model && equals( value, m.$get( fieldName ) );\n });\n }\n);\n\n// unique:X,Y\nforeignRuleGenerator('unique',\n '{$alias} must be a unique {$matchAlias} in a {$class}',\n function isInvalid(value, model, models, fieldName)\n {\n return models.contains(function isDifferentMatch(m)\n {\n return m !== model && equals( value, m.$get( fieldName ) );\n });\n }\n);\n\n// 'ruleName'\n// 'ruleName:name'\n// 'ruleName:,field'\n// 'ruleName:name,field'\n// 'ruleName:name,field': '...'\n// 'ruleName': {input: {field: 'field', model: 'name'}, message: '...'}\n// 'ruleName': {input: {field: 'field', model: ModelClass}, message: '...'}\n// 'ruleName': {input: {field: 'field', models: [...]}, message: '...'}\n// 'ruleName': {field: 'field', model: 'name'}\n// 'ruleName': {field: 'field', model: ModelClass}\n// 'ruleName': {field: 'field', models: [...]}\nfunction foreignRuleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n var modelName, models, fieldName;\n\n if ( !isValue( params ) || isString( params ) )\n {\n var parts = split( params || '', /(\\s*,\\s*)/, '\\\\' );\n modelName = parts[0] || database.name;\n fieldName = parts[1] || field;\n models = null;\n }\n else if ( isArray( params ) )\n {\n modelName = isString( params[0] ) ? params.shift() : database.name;\n fieldName = isString( params[0] ) ? params.shift() : field;\n models = new ModelCollection( database, params );\n }\n else if ( isObject( params ) )\n {\n modelName = params.model || database.name;\n fieldName = params.field || field;\n models = params.models;\n }\n\n if ( !models )\n {\n if ( !modelName )\n {\n throw 'model, model class, or models is required for ' + ruleName + ' rule';\n }\n\n if ( isString( modelName ) )\n {\n Rekord.get( modelName ).success(function(modelClass)\n {\n models = modelClass.all();\n });\n }\n else if ( isRekord( modelName ) )\n {\n models = modelName.all();\n }\n }\n\n if ( indexOf( database.fields, fieldName ) === false )\n {\n throw fieldName + ' is not a valid field for the ' + ruleName + ' rule';\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var extra = {\n $class: modelName,\n $matchField: fieldName,\n $matchAlias: getAlias( fieldName )\n };\n\n return function(value, model, setMessage)\n {\n if ( models && isValue( value ) )\n {\n if ( isInvalid( value, model, models, fieldName ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate, extra ) );\n }\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n","// if:due_date:before:today|required\n\n// if all rules pass for the given field, continue with remaining rules\nsubRuleGenerator('if',\n function isInvalid(invalidCount, totalCount) {\n return invalidCount > 0;\n }\n);\n\n// if any rules pass for the given field, continue with remaining rules\nsubRuleGenerator('if_any',\n function isInvalid(invalidCount, totalCount) {\n return invalidCount >= totalCount;\n }\n);\n\n// if no rules pass for the given field, continue with remaining rules\nsubRuleGenerator('if_not',\n function isInvalid(invalidCount, totalCount) {\n return invalidCount < totalCount;\n }\n);\n\n\n\nfunction subRuleGenerator(ruleName, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires a validation rule argument';\n }\n\n var otherField, otherRules;\n\n if ( isString( params ) )\n {\n var colon = params.indexOf( ':' );\n\n if ( colon === -1 )\n {\n throw params + ' is not a valid argument for the ' + ruleName + ' rule';\n }\n\n otherField = params.substring( 0, colon ) || field;\n otherRules = params.substring( colon + 1 );\n }\n else if ( isArray( params ) )\n {\n otherField = params.shift() || field;\n otherRules = params;\n }\n else if ( isObject( params ) )\n {\n otherField = params.field || field;\n otherRules = params.rules;\n }\n\n if ( indexOf( database.fields, otherField ) === -1 )\n {\n throw otherField + ' is not a valid field for the ' + ruleName + ' rule';\n }\n\n if ( !otherRules )\n {\n throw 'rules are required for the ' + ruleName + ' rule';\n }\n\n var validators = Validation.parseRules( otherRules, otherField, database, getAlias );\n\n return function(value, model, setMessage)\n {\n var invalids = 0;\n\n var setInvalid = function(message)\n {\n if ( message )\n {\n invalids++;\n }\n };\n\n for (var i = 0; i < validators.length; i++)\n {\n validators[ i ]( value, model, setInvalid );\n }\n\n return isInvalid( invalids, validators.length ) ? Validation.Stop : value;\n };\n };\n}\n","// in:X,Y,Z,...\nlistRuleGenerator('in',\n '{$alias} must be one of {$list}.',\n function isInvalid(value, model, inList)\n {\n return !inList( value, model );\n }\n);\n\n// not_in:X,Y,Z,...\nlistRuleGenerator('not_in',\n '{$alias} must not be one of {$list}.',\n function isInvalid(value, model, inList)\n {\n return inList( value, model );\n }\n);\n\nfunction listRuleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires a list argument';\n }\n\n var values, inList = false;\n\n if ( isString( params ) )\n {\n values = split( params, /(,)/, '\\\\' );\n }\n else if ( isArray( params ) )\n {\n values = params;\n }\n else if ( isFunction( params ) )\n {\n values = inList;\n }\n\n if ( inList !== false )\n {\n if ( !values || values.length === 0 )\n {\n throw params + ' is not a valid list of values for the ' + ruleName + ' rule';\n }\n }\n\n if ( isPrimitiveArray( values ) )\n {\n var map = mapFromArray( values, true );\n\n inList = function(value)\n {\n return map[ value ];\n };\n }\n else\n {\n inList = function(value)\n {\n return indexOf( values, value, equals );\n };\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var list = joinFriendly( values, 'or' );\n var extra = {\n $params: params,\n $list: list\n };\n\n return function(value, model, setMessage)\n {\n if ( isInvalid( value, model, inList ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate, extra ) );\n }\n\n return value;\n };\n };\n\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n","// between:3,10\nrangeRuleGenerator('between', {\n 'string': '{$alias} must have between {$start} to {$end} characters.',\n 'number': '{$alias} must be between {$start} and {$end}.',\n 'object': '{$alias} must have between {$start} to {$end} items.'\n },\n function isInvalid(value, start, end) {\n return value < start || value > end;\n }\n);\n\n// not_between\nrangeRuleGenerator('not_between', {\n 'string': '{$alias} must not have between {$start} to {$end} characters.',\n 'number': '{$alias} must not be between {$start} and {$end}.',\n 'object': '{$alias} must not have between {$start} to {$end} items.'\n },\n function isInvalid(value, start, end) {\n return value >= start && value <= end;\n }\n);\n\nfunction rangeRuleGenerator(ruleName, defaultMessages, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires a range argument';\n }\n\n var start, end;\n\n if ( isString( params ) )\n {\n var range = split( params, /(\\s*,\\s*)/, '\\\\' );\n\n start = parseFloat( range[0] );\n end = parseFloat( range[1] );\n }\n else if ( isArray( params ) )\n {\n start = params[ 0 ];\n end = params[ 1 ];\n }\n else if ( isObject( params ) )\n {\n start = params.start;\n end = params.end;\n }\n\n if ( isNaN( start ) || isNaN( end ) )\n {\n throw params + ' is not a valid range of numbers for the ' + ruleName + ' rule';\n }\n\n if ( isString( message ) )\n {\n message = {\n 'string': message,\n 'number': message,\n 'object': message\n };\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var extra = {\n $start: start,\n $end: end\n };\n\n return function(value, model, setMessage)\n {\n var size = sizeof( value );\n var type = typeof( value );\n var typeMessage = messageTemplate[ type ];\n\n if ( typeMessage && isInvalid( size, start, end ) )\n {\n extra.$size = size;\n\n setMessage( generateMessage( field, getAlias( field ), value, model, typeMessage, extra ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessages;\n}\n","\n\nregexRuleGenerator('alpha',\n '{$alias} should only contain alphabetic characters.',\n /^[a-zA-Z]*$/\n);\n\nregexRuleGenerator('alpha_dash',\n '{$alias} should only contain alpha-numeric characters, dashes, and underscores.',\n /^[a-zA-Z0-9_-]*$/\n);\n\nregexRuleGenerator('alpha_num',\n '{$alias} should only contain alpha-numeric characters.',\n /^[a-zA-Z0-9]*$/\n);\n\nregexRuleGenerator('email',\n '{$alias} is not a valid email.',\n /^.+@.+\\..+$/\n);\n\nregexRuleGenerator('url',\n '{$alias} is not a valid URL.',\n /^(https?:\\/\\/)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)$/\n);\n\nregexRuleGenerator('uri',\n '{$alias} is not a valid URI.',\n /^(\\w+:\\/\\/)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)$/\n);\n\nregexRuleGenerator('phone',\n '{$alias} is not a valid phone number.',\n /^1?\\W*([2-9][0-8][0-9])\\W*([2-9][0-9]{2})\\W*([0-9]{4})(\\se?x?t?(\\d*))?$/\n);\n\nfunction regexRuleGenerator(ruleName, defaultMessage, regex)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n checkNoParams( ruleName, field, params );\n\n var messageTemplate = determineMessage( ruleName, message );\n\n return function(value, model, setMessage)\n {\n if ( !regex.test( value ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n\nValidation.Rules.regex = function(field, params, database, getAlias, message)\n{\n var regex;\n\n if ( isString( params ) )\n {\n var parsed = /^\\/(.*)\\/([gmi]*)$/.exec( params );\n\n if ( parsed )\n {\n regex = new RegExp( parsed[1], parsed[2] );\n }\n }\n else if ( isRegExp( params ) )\n {\n regex = params;\n }\n\n if ( !regex )\n {\n throw params + ' is not a valid regular expression for the regex rule';\n }\n\n var messageTemplate = determineMessage( 'regex', message );\n\n return function(value, model, setMessage)\n {\n if ( !regex.test( value ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate ) );\n }\n\n return value;\n };\n};\n\nValidation.Rules.regex.message = '{$alias} is not a valid value.';\n","// min:3\nsizeRuleGenerator('min', {\n 'string': '{$alias} must have a minimum of {$number} characters.',\n 'number': '{$alias} must be at least {$number}.',\n 'object': '{$alias} must have at least {$number} items.'\n },\n function isInvalid(value, number) {\n return value < number;\n }\n);\n\n// greater_than:0\nsizeRuleGenerator('greater_than', {\n 'string': '{$alias} must have more than {$number} characters.',\n 'number': '{$alias} must be greater than {$number}.',\n 'object': '{$alias} must have more than {$number} items.'\n },\n function isInvalid(value, number) {\n return value <= number;\n }\n);\n\n// max:10\nsizeRuleGenerator('max', {\n 'string': '{$alias} must have no more than {$number} characters.',\n 'number': '{$alias} must be no more than {$number}.',\n 'object': '{$alias} must have no more than {$number} items.'\n },\n function isInvalid(value, number) {\n return value > number;\n }\n);\n\n// less_than:5\nsizeRuleGenerator('less_than', {\n 'string': '{$alias} must have less than {$number} characters.',\n 'number': '{$alias} must be less than {$number}.',\n 'object': '{$alias} must have less than {$number} items.'\n },\n function isInvalid(value, number) {\n return value >= number;\n }\n);\n\n// equal:4.5\nsizeRuleGenerator('equal', {\n 'string': '{$alias} must have {$number} characters.',\n 'number': '{$alias} must equal {$number}.',\n 'object': '{$alias} must have {$number} items.'\n },\n function isInvalid(value, number) {\n return value !== number;\n }\n);\n\n// not_equal:0\nsizeRuleGenerator('not_equal', {\n 'string': '{$alias} must not have {$number} characters.',\n 'number': '{$alias} must not equal {$number}.',\n 'object': '{$alias} must not have {$number} items.'\n },\n function isInvalid(value, number) {\n return value === number;\n }\n);\n\nfunction sizeRuleGenerator(ruleName, defaultMessages, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n var number;\n\n if ( isString( params ) )\n {\n number = parseFloat( params );\n }\n else if ( isNumber( params ) )\n {\n number = params;\n }\n\n if ( isNaN( number ) )\n {\n throw '\"' + params + '\" is not a valid number for the ' + ruleName + ' rule';\n }\n\n if ( isString( message ) )\n {\n message = {\n 'string': message,\n 'number': message,\n 'object': message\n };\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var extra = {\n $number: params\n };\n\n return function(value, model, setMessage)\n {\n var size = sizeof( value );\n var type = typeof( value );\n var typeMessage = messageTemplate[ type ];\n\n if ( typeMessage && isInvalid( size, number ) )\n {\n extra.$size = size;\n\n setMessage( generateMessage( field, getAlias( field ), value, model, typeMessage, extra ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessages;\n}\n","Rekord.on( Rekord.Events.Plugins, function(model, db, options)\n{\n var validation = options.validation || Database.Defaults.validation;\n\n if ( isEmpty( validation ) )\n {\n return;\n }\n\n var rules = validation.rules || {};\n var messages = validation.messages || {};\n var aliases = validation.aliases || {};\n var required = !!validation.required;\n\n function getAlias(field)\n {\n return aliases[ field ] || field;\n }\n\n db.validations = {};\n\n for ( var field in rules )\n {\n db.validations[ field ] = Validation.parseRules( rules[ field ], field, db, getAlias, messages[ field ] );\n }\n\n addMethod( model.prototype, '$validate', function()\n {\n var $this = this;\n\n this.$trigger( Model.Events.PreValidate, [this] );\n\n this.$valid = true;\n this.$validations = {};\n this.$validationMessages.length = 0;\n\n for (var field in db.validations)\n {\n var chain = db.validations[ field ];\n var value = this.$get( field );\n var fieldValid = true;\n\n var setMessage = function(message) // jshint ignore:line\n {\n // Only accept for the first valid message\n if ( message && fieldValid )\n {\n fieldValid = false;\n\n $this.$validations[ field ] = message;\n $this.$validationMessages.push( message );\n $this.$valid = false;\n }\n };\n\n for (var i = 0; i < chain.length && fieldValid && value !== Validation.Stop; i++)\n {\n value = chain[ i ]( value, this, setMessage );\n }\n }\n\n this.$trigger( this.$valid ? Model.Events.ValidatePass : Model.Events.ValidateFail, [this] );\n\n return this.$valid;\n });\n\n replaceMethod( model.prototype, '$init', function($init)\n {\n return function()\n {\n this.$valid = undefined;\n this.$validations = {};\n this.$validationMessages = [];\n\n return $init.apply( this, arguments );\n };\n });\n\n if ( required )\n {\n replaceMethod( model.prototype, '$save', function($save)\n {\n return function()\n {\n if ( this.$isDeleted() )\n {\n Rekord.debug( Rekord.Debugs.SAVE_DELETED, this.$db, this );\n\n return Promise.resolve( this );\n }\n\n if ( !this.$validate() )\n {\n return Promise.resolve( this );\n }\n\n return $save.apply( this, arguments );\n };\n });\n }\n});\n\nModel.Events.PreValidate = 'pre-validate';\n\nModel.Events.ValidatePass = 'validate-pass';\n\nModel.Events.ValidateFail = 'validate-fail';\n\nvar Validation =\n{\n Rules: {},\n Expression: {},\n Expressions: [],\n Delimiter: /([|])/,\n Escape: '\\\\',\n RuleSeparator: ':',\n Stop: {},\n\n parseRules: function(rules, field, database, getAlias, message)\n {\n var validators = [];\n\n if ( isString( rules ) )\n {\n rules = split( rules, this.Delimiter, this.Escape );\n }\n\n if ( isArray( rules ) )\n {\n for (var i = 0; i < rules.length; i++)\n {\n var rule = rules[ i ];\n var defaultMessageValidator = this.parseRule( rule, field, database, getAlias, message );\n\n validators.push( defaultMessageValidator );\n }\n }\n else if ( isObject( rules ) )\n {\n for (var ruleProperty in rules)\n {\n var ruleMessageOrData = rules[ ruleProperty ];\n\n var ruleMessage = isObject( ruleMessageOrData ) ? ruleMessageOrData.message :\n ( isString( ruleMessageOrData ) ? ruleMessageOrData : undefined );\n\n var ruleInput = isObject( ruleMessageOrData ) && ruleMessageOrData.message ? ruleMessageOrData.input :\n ( isString( ruleMessageOrData ) ? undefined : ruleMessageOrData );\n\n var customMessageValidator = this.parseRule( ruleProperty, field, database, getAlias, ruleMessage || message, ruleInput );\n\n validators.push( customMessageValidator );\n }\n }\n\n return validators;\n },\n\n parseRule: function(rule, field, database, getAlias, message, input)\n {\n var colon = rule.indexOf( this.RuleSeparator );\n var ruleName = colon === -1 ? rule : rule.substring( 0, colon );\n\n if ( ruleName.charAt( 0 ) === '$' )\n {\n return this.customValidator( ruleName, field, database, getAlias, message );\n }\n\n var ruleParams = colon === -1 ? input : rule.substring( colon + 1 );\n var validatorFactory = Validation.Rules[ ruleName ];\n\n if ( !validatorFactory )\n {\n throw ruleName + ' is not a valid rule';\n }\n\n return validatorFactory( field, ruleParams, database, getAlias, message );\n },\n\n parseExpression: function(expr, database)\n {\n var parsers = Validation.Expressions;\n\n for (var i = 0; i < parsers.length; i++)\n {\n var parser = parsers[ i ];\n var expressionFunction = parser( expr, database );\n\n if ( isFunction( expressionFunction ) )\n {\n return expressionFunction; // (value, model)\n }\n }\n\n return noop;\n },\n\n customValidator: function(functionName, field, database, getAlias, message)\n {\n return function(value, model, setMessage)\n {\n var result = model[ functionName ]( value, getAlias, message );\n\n if ( isString( result ) )\n {\n setMessage( result );\n }\n\n return value;\n };\n }\n};\n","Validation.Expression.date =\nValidation.Expressions.push(function(expr, database)\n{\n var parsed = parseDate( expr );\n\n if ( parsed !== false )\n {\n var parsedTime = parsed.getTime();\n\n return function(value, model)\n {\n return parsedTime;\n };\n }\n}) - 1;\n","Validation.Expression.field =\nValidation.Expressions.push(function(expr, database)\n{\n if ( indexOf( database.fields, expr ) )\n {\n return function(value, model)\n {\n return model.$get( expr );\n };\n }\n}) - 1;\n","\nvar RELATIVE_REGEX = /^([+-]\\d+(\\.\\d+)?)\\s*(.+)$/;\n\nvar RELATIVE_UNITS = {\n ms: 1,\n millisecond: 1,\n milliseconds: 1,\n s: 1000,\n second: 1000,\n seconds: 1000,\n min: 1000 * 60,\n mins: 1000 * 60,\n minute: 1000 * 60,\n minutes: 1000 * 60,\n hr: 1000 * 60 * 60,\n hour: 1000 * 60 * 60,\n hours: 1000 * 60 * 60,\n day: 1000 * 60 * 60 * 24,\n days: 1000 * 60 * 60 * 24,\n wk: 1000 * 60 * 60 * 24 * 7,\n week: 1000 * 60 * 60 * 24 * 7,\n weeks: 1000 * 60 * 60 * 24 * 7,\n month: ['getMonth', 'setMonth'],\n months: ['getMonth', 'setMonth'],\n yr: ['getFullYear', 'setFullYear'],\n year: ['getFullYear', 'setFullYear'],\n years: ['getFullYear', 'setFullYear']\n};\n\nValidation.Expression.relative =\nValidation.Expressions.push(function(expr, database)\n{\n var parsed = RELATIVE_REGEX.exec( expr );\n\n if ( parsed !== null )\n {\n var amount = parseFloat( parsed[ 1 ] );\n var unit = parsed[ 3 ];\n var unitScale = RELATIVE_UNITS[ unit ];\n\n if ( !unitScale )\n {\n throw unit + ' is not a valid unit.';\n }\n\n return function(value, model)\n {\n var relative = new Date();\n\n if ( isNumber( unitScale ) )\n {\n relative.setTime( relative.getTime() + unitScale * amount );\n }\n else\n {\n var getter = unitScale[0];\n var setter = unitScale[1];\n\n relative[ setter ]( relative[ getter ]() + amount );\n }\n\n return relative.getTime();\n };\n }\n}) - 1;\n","Validation.Expression.today =\nValidation.Expressions.push(function(expr, database)\n{\n if ( expr === 'today' )\n {\n return function(value, model)\n {\n var today = new Date();\n\n startOfDay( today );\n\n return today.getTime();\n };\n }\n}) - 1;\n","Validation.Expression.tomorrow =\nValidation.Expressions.push(function(expr, database)\n{\n if ( expr === 'tomorrow' )\n {\n return function(value, model)\n {\n var tomorrow = new Date();\n\n tomorrow.setDate( tomorrow.getDate() + 1 );\n startOfDay( tomorrow );\n\n return tomorrow.getTime();\n };\n }\n}) - 1;\n","Validation.Expression.yesterday =\nValidation.Expressions.push(function(expr, database)\n{\n if ( expr === 'yesterday' )\n {\n return function(value, model)\n {\n var yesterday = new Date();\n\n yesterday.setDate( yesterday.getDate() - 1 );\n startOfDay( yesterday );\n\n return yesterday.getTime();\n };\n }\n}) - 1;\n","// accepted\nValidation.Rules.accepted = function(field, params, database, getAlias, message)\n{\n checkNoParams( 'accepted', field, params );\n\n var messageTemplate = determineMessage( 'accepted', message );\n var acceptable = Validation.Rules.accepted.acceptable;\n\n return function(value, model, setMessage)\n {\n var valueString = (value + '').toLowerCase();\n var accepted = acceptable[ valueString ];\n\n if ( !accepted )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate ) );\n }\n\n return value;\n };\n};\n\nValidation.Rules.accepted.message = '{$alias} has not been accepted.';\n\nValidation.Rules.accepted.acceptable =\n{\n '1': true,\n 'yes': true,\n 'on': true,\n 'y': true,\n 'true': true\n};\n","// required\nruleGenerator('required',\n '{$alias} is required.',\n function isInvalid(value) {\n return isEmpty( value );\n }\n);\n","\nruleGenerator('array',\n '{$alias} must be an array.',\n function isInvalid(value) {\n return !isArray( value );\n }\n);\n\nruleGenerator('object',\n '{$alias} must be an object.',\n function isInvalid(value) {\n return !isObject( value );\n }\n);\n\nruleGenerator('string',\n '{$alias} must be a string.',\n function isInvalid(value) {\n return !isString( value );\n }\n);\n\nruleGenerator('number',\n '{$alias} must be a number.',\n function isInvalid(value) {\n return !isNumber( value );\n }\n);\n\nruleGenerator('boolean',\n '{$alias} must be a true or false.',\n function isInvalid(value) {\n return !isBoolean( value );\n }\n);\n\nruleGenerator('model',\n '{$alias} must have a value.',\n function isInvalid(value) {\n return !(value instanceof Model);\n }\n);\n\nruleGenerator('whole',\n '{$alias} must be a whole number.',\n function isInvalid(value, model, setValue) {\n var parsed = tryParseInt( value );\n var numeric = parseFloat( value );\n var invalid = !isNumber( parsed );\n if ( !invalid ) {\n invalid = Math.floor( parsed ) !== numeric;\n if ( !invalid ) {\n setValue( parsed );\n }\n }\n return invalid;\n }\n);\n\nruleGenerator('numeric',\n '{$alias} must be numeric.',\n function isInvalid(value, model, setValue) {\n var parsed = tryParseFloat( value );\n var invalid = !isNumber( parsed );\n if ( !invalid ) {\n setValue( parsed );\n }\n return invalid;\n }\n);\n\nruleGenerator('yesno',\n '{$alias} must be a yes or no.',\n function isInvalid(value, model, setValue) {\n var mapped = Validation.Rules.yesno.map[ value ];\n var invalid = !isBoolean( mapped );\n if ( !invalid ) {\n setValue( mapped );\n }\n return invalid;\n }\n);\n\nValidation.Rules.yesno.map =\n{\n 'true': true,\n 't': true,\n 'yes': true,\n 'y': true,\n '1': true,\n 'false': false,\n 'f': false,\n 'no': false,\n 'n': false,\n '0': false\n};\n","Validation.Rules.abs = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n value = tryParseFloat( value );\n\n if ( isNumber( value ) )\n {\n value = Math.abs( value );\n }\n\n return value;\n };\n};\n","Validation.Rules.apply = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n model.$set( field, value );\n \n return value;\n };\n};\n","Validation.Rules.base64 = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n if ( global.btoa )\n {\n value = global.btoa( value );\n }\n\n return value;\n };\n};\n","Validation.Rules.ceil = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n value = tryParseFloat( value );\n \n if ( isNumber( value ) )\n {\n value = Math.ceil( value );\n }\n\n return value;\n };\n};\n","Validation.Rules.endOfDay = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n return endOfDay( value );\n };\n};\n","Validation.Rules.filter = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n if ( isArray( value ) )\n {\n for (var i = value.length - 1; i >= 0; i--)\n {\n if ( !isValue( value[ i ] ) )\n {\n value.splice( i, 1 );\n }\n }\n }\n else if ( isObject( value ) )\n {\n for (var prop in value)\n {\n if ( !isValue( value[ prop ] ) )\n {\n delete value[ prop ];\n }\n }\n }\n\n return value;\n };\n};\n","Validation.Rules.floor = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n value = tryParseFloat( value );\n \n if ( isNumber( value ) )\n {\n value = Math.floor( value );\n }\n\n return value;\n };\n};\n","Validation.Rules.mod = function(field, params, database, alias, message)\n{\n var number = tryParseFloat( params );\n\n if ( !isNumber( number ) )\n {\n throw '\"' + number + '\" is not a valid number for the mod rule.';\n }\n\n return function(value, model, setMessage)\n {\n value = tryParseFloat( value );\n\n if ( isNumber( value ) )\n {\n value = value % number;\n }\n\n return value;\n };\n};\n","Validation.Rules.null = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n model.$set( field, null );\n\n return null;\n };\n};\n","Validation.Rules.round = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n value = tryParseFloat( value );\n\n if ( isNumber( value ) )\n {\n value = Math.round( value );\n }\n\n return value;\n };\n};\n","Validation.Rules.startOfDay = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n return startOfDay( value );\n };\n};\n","Validation.Rules.trim = function(field, params, database, alias, message)\n{\n var trim = (function()\n {\n if ( String.prototype.trim )\n {\n return function(x) {\n return x.trim();\n };\n }\n\n var regex = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g;\n\n return function(x)\n {\n return x.replace( regex, '' );\n };\n\n })();\n\n return function(value, model, setMessage)\n {\n if ( isString( value ) )\n {\n value = trim( value );\n }\n\n return value;\n };\n};\n","Validation.Rules.unbase64 = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n if ( global.atob )\n {\n value = global.atob( value );\n }\n\n return value;\n };\n};\n","\n\n Rekord.Validation = Validation;\n\n Rekord.ruleGenerator = ruleGenerator;\n Rekord.rangeRuleGenerator = rangeRuleGenerator;\n Rekord.collectionRuleGenerator = collectionRuleGenerator;\n Rekord.dateRuleGenerator = dateRuleGenerator;\n Rekord.fieldListRuleGenerator = fieldListRuleGenerator;\n Rekord.fieldsRuleGenerator = fieldsRuleGenerator;\n Rekord.foreignRuleGenerator = foreignRuleGenerator;\n Rekord.subRuleGenerator = subRuleGenerator;\n Rekord.listRuleGenerator = listRuleGenerator;\n Rekord.regexRuleGenerator = regexRuleGenerator;\n Rekord.sizeRuleGenerator = sizeRuleGenerator;\n\n Rekord.joinFriendly = joinFriendly;\n Rekord.tryParseFloat = tryParseFloat;\n Rekord.tryParseInt = tryParseInt;\n Rekord.startOfDay = startOfDay;\n Rekord.endOfDay = endOfDay;\n Rekord.determineMessage = determineMessage;\n Rekord.mapFromArray = mapFromArray;\n Rekord.checkNoParams = checkNoParams;\n Rekord.generateMessage = generateMessage;\n\n})(this, this.Rekord);\n"],"sourceRoot":"/source/"} \ No newline at end of file +{"version":3,"sources":["rekord-validation.min.js"],"names":["global","Rekord","undefined","tryParseFloat","x","parsed","parseFloat","isNaN","tryParseInt","parseInt","startOfDay","d","isDate","setHours","isNumber","endOfDay","ruleGenerator","ruleName","defaultMessage","isInvalid","Validation","Rules","field","params","database","getAlias","message","checkNoParams","messageTemplate","determineMessage","value","model","setMessage","setValue","newValue","generateMessage","joinFriendly","arr","lastSeparatorCustom","itemSeparatorCustom","copy","slice","i","length","last","pop","lastSeparator","itemSeparator","join","mapFromArray","map","alias","extra","isFunction","base","$field","$alias","$value","transfer","isObject","format","collectionRuleGenerator","matchField","matchValue","equality","isString","comma","indexOf","substring","isArray","equals","equalsCompare","fields","$matchField","$matchAlias","$matchValue","dateRuleGenerator","dateExpression","parseExpression","parseDate","parsedTime","getTime","noop","$date","date","fieldListRuleGenerator","matchValues","parts","split","shift","values","list","$params","$list","fieldsRuleGenerator","fieldNames","fieldAliases","$fields","$fieldAliases","foreignRuleGenerator","modelName","models","fieldName","isValue","name","ModelCollection","get","success","modelClass","all","isRekord","$class","subRuleGenerator","otherField","otherRules","colon","rules","validators","parseRules","invalids","setInvalid","Stop","listRuleGenerator","inList","isPrimitiveArray","rangeRuleGenerator","defaultMessages","start","end","range","string","number","object","$start","$end","size","sizeof","type","typeMessage","$size","regexRuleGenerator","regex","test","sizeRuleGenerator","$number","Model","Database","Promise","Collection","isEmpty","isBoolean","isRegExp","addMethod","replaceMethod","on","Events","Plugins","db","options","aliases","validation","Defaults","messages","required","validations","prototype","$this","this","$trigger","PreValidate","$valid","$validations","$validationMessages","chain","$get","fieldValid","push","ValidatePass","ValidateFail","$init","apply","arguments","$save","$isDeleted","debug","Debugs","SAVE_DELETED","$db","resolve","$validate","Expression","Expressions","Delimiter","Escape","RuleSeparator","rule","defaultMessageValidator","parseRule","ruleProperty","ruleMessageOrData","ruleMessage","ruleInput","input","customMessageValidator","charAt","customValidator","ruleParams","validatorFactory","expr","parsers","parser","expressionFunction","functionName","result","RELATIVE_REGEX","RELATIVE_UNITS","ms","millisecond","milliseconds","s","second","seconds","min","mins","minute","minutes","hr","hour","hours","day","days","wk","week","weeks","month","months","yr","year","years","relative","exec","amount","unit","unitScale","Date","setTime","getter","setter","today","tomorrow","setDate","getDate","yesterday","accepted","acceptable","valueString","toLowerCase","1","yes","y","true","contains","m","validate","messageOption","invalid","related","pluck","confirmed","different","valid","invalidCount","totalCount","RegExp","numeric","Math","floor","mapped","yesno","t","false","f","no","n","0","abs","$set","base64","btoa","ceil","filter","splice","prop","mod","round","trim","String","replace","unbase64","atob"],"mappings":"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","file":"rekord-validation.min.js","sourcesContent":["/* rekord-validation 1.0.1 - Advanced validation rules for rekord by Philip Diffenderfer */\n(function(global, Rekord, undefined)\n{\n var Model = Rekord.Model;\n var Database = Rekord.Database;\n var Promise = Rekord.Promise;\n var Collection = Rekord.Collection;\n var ModelCollection = Rekord.ModelCollection;\n\n var isEmpty = Rekord.isEmpty;\n var isString = Rekord.isString;\n var isArray = Rekord.isArray;\n var isObject = Rekord.isObject;\n var isFunction = Rekord.isFunction;\n var isDate = Rekord.isDate;\n var isNumber = Rekord.isNumber;\n var isBoolean = Rekord.isBoolean;\n var isValue = Rekord.isValue;\n var isPrimitiveArray = Rekord.isPrimitiveArray;\n var isRegExp = Rekord.isRegExp;\n var isRekord = Rekord.isRekord;\n\n var noop = Rekord.noop;\n var equalsCompare = Rekord.equalsCompare;\n var equals = Rekord.equals;\n var indexOf = Rekord.indexOf;\n var sizeof = Rekord.sizeof;\n\n var split = Rekord.split;\n var transfer = Rekord.transfer;\n var format = Rekord.format;\n\n var parseDate = Rekord.parseDate;\n\n var addMethod = Rekord.addMethod;\n var replaceMethod = Rekord.replaceMethod;\n\nfunction tryParseFloat(x)\n{\n var parsed = parseFloat( x );\n\n if ( !isNaN( parsed ) )\n {\n x = parsed;\n }\n\n return x;\n}\n\nfunction tryParseInt(x)\n{\n var parsed = parseInt( x );\n\n if ( !isNaN( parsed ) )\n {\n x = parsed;\n }\n\n return x;\n}\n\nfunction startOfDay(d)\n{\n if ( isDate( d ) )\n {\n d.setHours( 0, 0, 0, 0 );\n }\n else if ( isNumber( d ) )\n {\n d = d - (d % 86400000);\n }\n\n return d;\n}\n\nfunction endOfDay(d)\n{\n if ( isDate( d ) )\n {\n d.setHours( 23, 59, 59, 999 );\n }\n else if ( isNumber( d ) )\n {\n d = d - (d % 86400000) + 86400000 - 1;\n }\n\n return d;\n}\n\nfunction ruleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n checkNoParams( ruleName, field, params );\n\n var messageTemplate = determineMessage( ruleName, message );\n\n return function(value, model, setMessage)\n {\n function setValue( newValue )\n {\n value = newValue;\n }\n\n if ( isInvalid( value, model, setValue ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n\nfunction determineMessage(ruleName, message)\n{\n return message || Validation.Rules[ ruleName ].message;\n}\n\nfunction joinFriendly(arr, lastSeparatorCustom, itemSeparatorCustom, getAlias)\n{\n var copy = arr.slice();\n\n if ( getAlias )\n {\n for (var i = 0; i < copy.length; i++)\n {\n copy[ i ] = getAlias( copy[ i ] );\n }\n }\n\n var last = copy.pop();\n var lastSeparator = lastSeparatorCustom || 'and';\n var itemSeparator = itemSeparatorCustom || ', ';\n\n switch (copy.length) {\n case 0:\n return last;\n case 1:\n return copy[ 0 ] + ' ' + lastSeparator + ' ' + last;\n default:\n return copy.join( itemSeparator ) + itemSeparator + lastSeparator + ' ' + last;\n }\n}\n\nfunction mapFromArray(arr, value)\n{\n var map = {};\n\n for (var i = 0; i < arr.length; i++)\n {\n map[ arr[ i ] ] = value;\n }\n\n return map;\n}\n\nfunction checkNoParams(ruleName, field, params)\n{\n if ( params )\n {\n throw 'the rule ' + ruleName + ' for field ' + field + ' has no arguments';\n }\n}\n\nfunction generateMessage(field, alias, value, model, message, extra)\n{\n if ( isFunction( message ) )\n {\n message = message( field, alias, value, model, extra );\n }\n\n var base = {};\n base.$field = field;\n base.$alias = alias;\n base.$value = value;\n\n transfer( model, base );\n\n if ( isObject( extra ) )\n {\n transfer( extra, base );\n }\n\n return format( message, base );\n}\n\nRekord.on( Rekord.Events.Plugins, function(model, db, options)\n{\n var validation = options.validation || Database.Defaults.validation;\n\n if ( isEmpty( validation ) )\n {\n return;\n }\n\n var rules = validation.rules || {};\n var messages = validation.messages || {};\n var aliases = validation.aliases || {};\n var required = !!validation.required;\n\n function getAlias(field)\n {\n return aliases[ field ] || field;\n }\n\n db.validations = {};\n\n for ( var field in rules )\n {\n db.validations[ field ] = Validation.parseRules( rules[ field ], field, db, getAlias, messages[ field ] );\n }\n\n addMethod( model.prototype, '$validate', function()\n {\n var $this = this;\n\n this.$trigger( Model.Events.PreValidate, [this] );\n\n this.$valid = true;\n this.$validations = {};\n this.$validationMessages.length = 0;\n\n for (var field in db.validations)\n {\n var chain = db.validations[ field ];\n var value = this.$get( field );\n var fieldValid = true;\n\n var setMessage = function(message) // jshint ignore:line\n {\n // Only accept for the first valid message\n if ( message && fieldValid )\n {\n fieldValid = false;\n\n $this.$validations[ field ] = message;\n $this.$validationMessages.push( message );\n $this.$valid = false;\n }\n };\n\n for (var i = 0; i < chain.length && fieldValid && value !== Validation.Stop; i++)\n {\n value = chain[ i ]( value, this, setMessage );\n }\n }\n\n this.$trigger( this.$valid ? Model.Events.ValidatePass : Model.Events.ValidateFail, [this] );\n\n return this.$valid;\n });\n\n replaceMethod( model.prototype, '$init', function($init)\n {\n return function()\n {\n this.$valid = undefined;\n this.$validations = {};\n this.$validationMessages = [];\n\n return $init.apply( this, arguments );\n };\n });\n\n if ( required )\n {\n replaceMethod( model.prototype, '$save', function($save)\n {\n return function()\n {\n if ( this.$isDeleted() )\n {\n Rekord.debug( Rekord.Debugs.SAVE_DELETED, this.$db, this );\n\n return Promise.resolve( this );\n }\n\n if ( !this.$validate() )\n {\n return Promise.resolve( this );\n }\n\n return $save.apply( this, arguments );\n };\n });\n }\n});\n\nModel.Events.PreValidate = 'pre-validate';\n\nModel.Events.ValidatePass = 'validate-pass';\n\nModel.Events.ValidateFail = 'validate-fail';\n\nvar Validation =\n{\n Rules: {},\n Expression: {},\n Expressions: [],\n Delimiter: /([|])/,\n Escape: '\\\\',\n RuleSeparator: ':',\n Stop: {},\n\n parseRules: function(rules, field, database, getAlias, message)\n {\n var validators = [];\n\n if ( isString( rules ) )\n {\n rules = split( rules, this.Delimiter, this.Escape );\n }\n\n if ( isArray( rules ) )\n {\n for (var i = 0; i < rules.length; i++)\n {\n var rule = rules[ i ];\n var defaultMessageValidator = this.parseRule( rule, field, database, getAlias, message );\n\n validators.push( defaultMessageValidator );\n }\n }\n else if ( isObject( rules ) )\n {\n for (var ruleProperty in rules)\n {\n var ruleMessageOrData = rules[ ruleProperty ];\n\n var ruleMessage = isObject( ruleMessageOrData ) ? ruleMessageOrData.message :\n ( isString( ruleMessageOrData ) ? ruleMessageOrData : undefined );\n\n var ruleInput = isObject( ruleMessageOrData ) && ruleMessageOrData.message ? ruleMessageOrData.input :\n ( isString( ruleMessageOrData ) ? undefined : ruleMessageOrData );\n\n var customMessageValidator = this.parseRule( ruleProperty, field, database, getAlias, ruleMessage || message, ruleInput );\n\n validators.push( customMessageValidator );\n }\n }\n\n return validators;\n },\n\n parseRule: function(rule, field, database, getAlias, message, input)\n {\n var colon = rule.indexOf( this.RuleSeparator );\n var ruleName = colon === -1 ? rule : rule.substring( 0, colon );\n\n if ( ruleName.charAt( 0 ) === '$' )\n {\n return this.customValidator( ruleName, field, database, getAlias, message );\n }\n\n var ruleParams = colon === -1 ? input : rule.substring( colon + 1 );\n var validatorFactory = Validation.Rules[ ruleName ];\n\n if ( !validatorFactory )\n {\n throw ruleName + ' is not a valid rule';\n }\n\n return validatorFactory( field, ruleParams, database, getAlias, message );\n },\n\n parseExpression: function(expr, database)\n {\n var parsers = Validation.Expressions;\n\n for (var i = 0; i < parsers.length; i++)\n {\n var parser = parsers[ i ];\n var expressionFunction = parser( expr, database );\n\n if ( isFunction( expressionFunction ) )\n {\n return expressionFunction; // (value, model)\n }\n }\n\n return noop;\n },\n\n customValidator: function(functionName, field, database, getAlias, message)\n {\n return function(value, model, setMessage)\n {\n var result = model[ functionName ]( value, getAlias, message );\n\n if ( isString( result ) )\n {\n setMessage( result );\n }\n\n return value;\n };\n }\n};\n\nValidation.Expression.date =\nValidation.Expressions.push(function(expr, database)\n{\n var parsed = parseDate( expr );\n\n if ( parsed !== false )\n {\n var parsedTime = parsed.getTime();\n\n return function(value, model)\n {\n return parsedTime;\n };\n }\n}) - 1;\n\nValidation.Expression.field =\nValidation.Expressions.push(function(expr, database)\n{\n if ( indexOf( database.fields, expr ) )\n {\n return function(value, model)\n {\n return model.$get( expr );\n };\n }\n}) - 1;\n\n\nvar RELATIVE_REGEX = /^([+-]\\d+(\\.\\d+)?)\\s*(.+)$/;\n\nvar RELATIVE_UNITS = {\n ms: 1,\n millisecond: 1,\n milliseconds: 1,\n s: 1000,\n second: 1000,\n seconds: 1000,\n min: 1000 * 60,\n mins: 1000 * 60,\n minute: 1000 * 60,\n minutes: 1000 * 60,\n hr: 1000 * 60 * 60,\n hour: 1000 * 60 * 60,\n hours: 1000 * 60 * 60,\n day: 1000 * 60 * 60 * 24,\n days: 1000 * 60 * 60 * 24,\n wk: 1000 * 60 * 60 * 24 * 7,\n week: 1000 * 60 * 60 * 24 * 7,\n weeks: 1000 * 60 * 60 * 24 * 7,\n month: ['getMonth', 'setMonth'],\n months: ['getMonth', 'setMonth'],\n yr: ['getFullYear', 'setFullYear'],\n year: ['getFullYear', 'setFullYear'],\n years: ['getFullYear', 'setFullYear']\n};\n\nValidation.Expression.relative =\nValidation.Expressions.push(function(expr, database)\n{\n var parsed = RELATIVE_REGEX.exec( expr );\n\n if ( parsed !== null )\n {\n var amount = parseFloat( parsed[ 1 ] );\n var unit = parsed[ 3 ];\n var unitScale = RELATIVE_UNITS[ unit ];\n\n if ( !unitScale )\n {\n throw unit + ' is not a valid unit.';\n }\n\n return function(value, model)\n {\n var relative = new Date();\n\n if ( isNumber( unitScale ) )\n {\n relative.setTime( relative.getTime() + unitScale * amount );\n }\n else\n {\n var getter = unitScale[0];\n var setter = unitScale[1];\n\n relative[ setter ]( relative[ getter ]() + amount );\n }\n\n return relative.getTime();\n };\n }\n}) - 1;\n\nValidation.Expression.today =\nValidation.Expressions.push(function(expr, database)\n{\n if ( expr === 'today' )\n {\n return function(value, model)\n {\n var today = new Date();\n\n startOfDay( today );\n\n return today.getTime();\n };\n }\n}) - 1;\n\nValidation.Expression.tomorrow =\nValidation.Expressions.push(function(expr, database)\n{\n if ( expr === 'tomorrow' )\n {\n return function(value, model)\n {\n var tomorrow = new Date();\n\n tomorrow.setDate( tomorrow.getDate() + 1 );\n startOfDay( tomorrow );\n\n return tomorrow.getTime();\n };\n }\n}) - 1;\n\nValidation.Expression.yesterday =\nValidation.Expressions.push(function(expr, database)\n{\n if ( expr === 'yesterday' )\n {\n return function(value, model)\n {\n var yesterday = new Date();\n\n yesterday.setDate( yesterday.getDate() - 1 );\n startOfDay( yesterday );\n\n return yesterday.getTime();\n };\n }\n}) - 1;\n\n// accepted\nValidation.Rules.accepted = function(field, params, database, getAlias, message)\n{\n checkNoParams( 'accepted', field, params );\n\n var messageTemplate = determineMessage( 'accepted', message );\n var acceptable = Validation.Rules.accepted.acceptable;\n\n return function(value, model, setMessage)\n {\n var valueString = (value + '').toLowerCase();\n var accepted = acceptable[ valueString ];\n\n if ( !accepted )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate ) );\n }\n\n return value;\n };\n};\n\nValidation.Rules.accepted.message = '{$alias} has not been accepted.';\n\nValidation.Rules.accepted.acceptable =\n{\n '1': true,\n 'yes': true,\n 'on': true,\n 'y': true,\n 'true': true\n};\n\n// contains:field,value\ncollectionRuleGenerator('contains',\n '{$alias} does not contain an item whose {$matchAlias} equals {$matchValue}.',\n function isInvalid(value, model, matchField, matchValue, equality)\n {\n return !value.contains(function isMatch(m)\n {\n return m !== model && equality( matchValue, m.$get( matchField ) );\n });\n }\n);\n\n// not_contains:field,value\ncollectionRuleGenerator('not_contains',\n '{$alias} contains an item whose {$matchAlias} equals {$matchValue}.',\n function isInvalid(value, model, matchField, matchValue, equality)\n {\n return value.contains(function isMatch(m)\n {\n return m !== model && equality( matchValue, m.$get( matchField ) );\n });\n }\n);\n\nfunction collectionRuleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires field & value arguments';\n }\n\n var matchField, matchValue, equality;\n\n if ( isString( params ) )\n {\n var comma = params.indexOf(',');\n\n if ( comma === -1 )\n {\n throw ruleName + ' validation rule requires field & value arguments';\n }\n\n matchField = params.substring( 0, comma );\n matchValue = params.substring( comma + 1 );\n }\n else if ( isArray( params ) )\n {\n matchField = params[ 0 ];\n matchValue = params[ 1 ];\n equality = params[ 2 ];\n }\n else if ( isObject( params ) )\n {\n matchField = params.field;\n matchValue = params.value;\n equality = params.equals;\n }\n\n if ( !isFunction( equality ) )\n {\n equality = equalsCompare;\n }\n\n if ( indexOf( database.fields, matchField ) === -1 )\n {\n throw matchField + ' is not a valid field for the ' + ruleName + ' rule';\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var extra = {\n $matchField: matchField,\n $matchAlias: getAlias( matchField ),\n $matchValue: matchValue\n };\n\n return function(value, model, setMessage)\n {\n if ( isInvalid( value, model, matchField, matchValue, equality ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate, extra ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n\nValidation.Rules.validate = function(field, params, database, getAlias, message)\n{\n // message, models, validations\n var messageOption = params || 'message';\n var messageTemplate = determineMessage( 'validate', message );\n\n return function(value, model, setMessage)\n {\n if ( isArray( value ) )\n {\n var invalid = new Collection();\n\n for (var i = 0; i < value.length; i++)\n {\n var related = value[ i ];\n\n if ( related && related.$validate && !related.$validate() )\n {\n invalid.push( related );\n }\n }\n\n if ( invalid.length )\n {\n switch (messageOption)\n {\n case 'models':\n setMessage( invalid );\n break;\n case 'validations':\n setMessage( invalid.pluck( '$validations', '$$key' ) );\n break;\n default: // message\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate ) );\n break;\n }\n }\n }\n\n return value;\n };\n};\n\nValidation.Rules.validate.message = '{$alias} is not valid.';\n\n// after:today\ndateRuleGenerator('after',\n '{$alias} must be after {$date}.',\n function isInvalid(value, date) {\n return value < endOfDay( date );\n }\n);\n\n// after_on:tomorrow\ndateRuleGenerator('after_on',\n '{$alias} must be after or equal to {$date}.',\n function isInvalid(value, date) {\n return value < date;\n }\n);\n\n// before:yesterday\ndateRuleGenerator('before',\n '{$alias} must be before {$date}.',\n function isInvalid(value, date) {\n return value > date;\n }\n);\n\n// before_on:+2days\ndateRuleGenerator('before_on',\n '{$alias} must be before or equal to {$date}.',\n function isInvalid(value, date) {\n return value > endOfDay( date );\n }\n);\n\n// date\nruleGenerator('date_like',\n '{$alias} must be a valid date.',\n function isInvalid(value, model, setValue) {\n var parsed = parseDate( value );\n var invalid = parsed === false;\n if ( !invalid ) {\n setValue( parsed.getTime() );\n }\n return invalid;\n }\n);\n\nfunction dateRuleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires a date expression argument';\n }\n\n var dateExpression;\n\n if ( isString( params ) )\n {\n dateExpression = Validation.parseExpression( params, database );\n }\n else if ( isFunction( params ) )\n {\n dateExpression = params;\n }\n else\n {\n var parsed = parseDate( params );\n\n if ( parsed !== false )\n {\n var parsedTime = parsed.getTime();\n\n dateExpression = function()\n {\n return parsedTime;\n };\n }\n }\n\n if ( !dateExpression || dateExpression === noop )\n {\n throw params + ' is not a valid date expression for the ' + ruleName + ' rule';\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var extra = {\n $date: params\n };\n\n return function(value, model, setMessage)\n {\n var parsed = parseDate( value );\n\n if ( parsed !== false )\n {\n value = parsed.getTime();\n\n var date = dateExpression( value, model );\n\n if ( isNumber( date ) && isInvalid( value, date ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate, extra ) );\n }\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n\n\n// required_if:X,Y,...\nfieldListRuleGenerator('required_if',\n '{$alias} is required.',\n function isInvalid(value, model, field, values, map) {\n var required = map[ model.$get( field ) ];\n\n return required && isEmpty( value );\n }\n);\n\n// required_unless:X,Y,...\nfieldListRuleGenerator('required_unless',\n '{$alias} is required.',\n function isInvalid(value, model, field, values, map) {\n var required = !map[ model.$get( field ) ];\n\n return required && isEmpty( value );\n }\n);\n\nfunction fieldListRuleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires a field and list arguments';\n }\n\n var matchField, matchValues;\n\n if ( isString( params ) )\n {\n var parts = split( params, /(,)/, '\\\\' );\n\n matchField = parts.shift();\n matchValues = parts;\n }\n else if ( isArray( params ) )\n {\n matchField = params.shift();\n matchValues = params;\n }\n else if ( isObject( params ) )\n {\n matchField = params.field;\n matchValues = params.values;\n }\n\n if ( indexOf( database.fields, matchField ) === false )\n {\n throw matchField + ' is not a valid field for the ' + ruleName + ' rule';\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var list = joinFriendly( matchValues );\n var extra = {\n $params: params,\n $matchField: matchField,\n $matchAlias: getAlias( matchField ),\n $list: list\n };\n var map = mapFromArray( matchValues, true );\n\n return function(value, model, setMessage)\n {\n if ( isInvalid( value, model, matchField, matchValues, map ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate, extra ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n\n// confirmed:X\nfieldsRuleGenerator('confirmed',\n '{$alias} must match {$fieldAliases}.',\n function isInvalid(value, model, fields, setValue) {\n var confirmed = true;\n\n for (var i = 0; i < fields.length; i++)\n {\n if ( !equals( value, model.$get( fields[ i ] ) ) )\n {\n confirmed = false;\n }\n }\n\n return !confirmed;\n }\n);\n\n// different:X\nfieldsRuleGenerator('different',\n '{$alias} must not match {$fieldAliases}.',\n function isInvalid(value, model, fields, setValue) {\n var different = false;\n\n for (var i = 0; i < fields.length; i++)\n {\n if ( !equals( value, model.$get( fields[ i ] ) ) )\n {\n different = true;\n }\n }\n\n return !different;\n }\n);\n\n// if_valid:X\nfieldsRuleGenerator('if_valid',\n '',\n function isInvalid(value, model, fields, setValue) {\n var valid = true;\n\n for (var i = 0; i < fields.length && valid; i++)\n {\n if ( model.$validations[ fields[ i ] ] )\n {\n valid = false;\n }\n }\n\n if ( !valid )\n {\n setValue( Validation.Stop );\n }\n\n return false;\n }\n);\n\n// The field under validation must be present only if any of the other specified fields are present.\n// required_with:X,Y,...\nfieldsRuleGenerator('required_with',\n '{$alias} is required.',\n function isInvalid(value, model, fields, setValue) {\n var required = false;\n\n for (var i = 0; i < fields.length && !required; i++)\n {\n if ( !isEmpty( model.$get( fields[ i ] ) ) )\n {\n required = true;\n }\n }\n\n return required && isEmpty( value );\n }\n);\n\n// The field under validation must be present only if all of the other specified fields are present.\n// required_with_all:X,Y,...\nfieldsRuleGenerator('required_with_all',\n '{$alias} is required.',\n function isInvalid(value, model, fields, setValue) {\n var required = true;\n\n for (var i = 0; i < fields.length && required; i++)\n {\n if ( isEmpty( model.$get( fields[ i ] ) ) )\n {\n required = false;\n }\n }\n\n return required && isEmpty( value );\n }\n);\n\n// The field under validation must be present only when any of the other specified fields are not present.\n// required_without:X,Y,...\nfieldsRuleGenerator('required_without',\n '{$alias} is required.',\n function isInvalid(value, model, fields, setValue) {\n var required = false;\n\n for (var i = 0; i < fields.length && !required; i++)\n {\n if ( isEmpty( model.$get( fields[ i ] ) ) )\n {\n required = true;\n }\n }\n\n return required && isEmpty( value );\n }\n);\n\n// The field under validation must be present only when all of the other specified fields are not present.\n// required_without_all:X,Y,...\nfieldsRuleGenerator('required_without_all',\n '{$alias} is required.',\n function isInvalid(value, model, fields, setValue) {\n var required = true;\n\n for (var i = 0; i < fields.length && required; i++)\n {\n if ( !isEmpty( model.$get( fields[ i ] ) ) )\n {\n required = false;\n }\n }\n\n return required && isEmpty( value );\n }\n);\n\nfunction fieldsRuleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires an array of fields argument';\n }\n\n var fields = split( params, /(\\s*,\\s*)/, '\\\\' );\n\n for (var i = 0; i < fields.length; i++)\n {\n if ( indexOf( database.fields, fields[ i ] ) === -1 )\n {\n throw fields[ i ] + ' is not a valid field for the ' + ruleName + ' rule';\n }\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var fieldNames = joinFriendly( fields );\n var fieldAliases = joinFriendly( fields, false, false, getAlias );\n var extra = {\n $fields: fieldNames,\n $fieldAliases: fieldAliases\n };\n\n return function(value, model, setMessage)\n {\n function setValue( newValue )\n {\n value = newValue;\n }\n\n if ( isInvalid( value, model, fields, setValue ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate, extra ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n\n// exists:X,Y\nforeignRuleGenerator('exists',\n '{$alias} must match an existing {$matchAlias} in a {$class}',\n function isInvalid(value, model, models, fieldName)\n {\n return !models.contains(function isDifferentMatch(m)\n {\n return m !== model && equals( value, m.$get( fieldName ) );\n });\n }\n);\n\n// unique:X,Y\nforeignRuleGenerator('unique',\n '{$alias} must be a unique {$matchAlias} in a {$class}',\n function isInvalid(value, model, models, fieldName)\n {\n return models.contains(function isDifferentMatch(m)\n {\n return m !== model && equals( value, m.$get( fieldName ) );\n });\n }\n);\n\n// 'ruleName'\n// 'ruleName:name'\n// 'ruleName:,field'\n// 'ruleName:name,field'\n// 'ruleName:name,field': '...'\n// 'ruleName': {input: {field: 'field', model: 'name'}, message: '...'}\n// 'ruleName': {input: {field: 'field', model: ModelClass}, message: '...'}\n// 'ruleName': {input: {field: 'field', models: [...]}, message: '...'}\n// 'ruleName': {field: 'field', model: 'name'}\n// 'ruleName': {field: 'field', model: ModelClass}\n// 'ruleName': {field: 'field', models: [...]}\nfunction foreignRuleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n var modelName, models, fieldName;\n\n if ( !isValue( params ) || isString( params ) )\n {\n var parts = split( params || '', /(\\s*,\\s*)/, '\\\\' );\n modelName = parts[0] || database.name;\n fieldName = parts[1] || field;\n models = null;\n }\n else if ( isArray( params ) )\n {\n modelName = isString( params[0] ) ? params.shift() : database.name;\n fieldName = isString( params[0] ) ? params.shift() : field;\n models = new ModelCollection( database, params );\n }\n else if ( isObject( params ) )\n {\n modelName = params.model || database.name;\n fieldName = params.field || field;\n models = params.models;\n }\n\n if ( !models )\n {\n if ( !modelName )\n {\n throw 'model, model class, or models is required for ' + ruleName + ' rule';\n }\n\n if ( isString( modelName ) )\n {\n Rekord.get( modelName ).success(function(modelClass)\n {\n models = modelClass.all();\n });\n }\n else if ( isRekord( modelName ) )\n {\n models = modelName.all();\n }\n }\n\n if ( indexOf( database.fields, fieldName ) === false )\n {\n throw fieldName + ' is not a valid field for the ' + ruleName + ' rule';\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var extra = {\n $class: modelName,\n $matchField: fieldName,\n $matchAlias: getAlias( fieldName )\n };\n\n return function(value, model, setMessage)\n {\n if ( models && isValue( value ) )\n {\n if ( isInvalid( value, model, models, fieldName ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate, extra ) );\n }\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n\n// if:due_date:before:today|required\n\n// if all rules pass for the given field, continue with remaining rules\nsubRuleGenerator('if',\n function isInvalid(invalidCount, totalCount) {\n return invalidCount > 0;\n }\n);\n\n// if any rules pass for the given field, continue with remaining rules\nsubRuleGenerator('if_any',\n function isInvalid(invalidCount, totalCount) {\n return invalidCount >= totalCount;\n }\n);\n\n// if no rules pass for the given field, continue with remaining rules\nsubRuleGenerator('if_not',\n function isInvalid(invalidCount, totalCount) {\n return invalidCount < totalCount;\n }\n);\n\n\n\nfunction subRuleGenerator(ruleName, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires a validation rule argument';\n }\n\n var otherField, otherRules;\n\n if ( isString( params ) )\n {\n var colon = params.indexOf( ':' );\n\n if ( colon === -1 )\n {\n throw params + ' is not a valid argument for the ' + ruleName + ' rule';\n }\n\n otherField = params.substring( 0, colon ) || field;\n otherRules = params.substring( colon + 1 );\n }\n else if ( isArray( params ) )\n {\n otherField = params.shift() || field;\n otherRules = params;\n }\n else if ( isObject( params ) )\n {\n otherField = params.field || field;\n otherRules = params.rules;\n }\n\n if ( indexOf( database.fields, otherField ) === -1 )\n {\n throw otherField + ' is not a valid field for the ' + ruleName + ' rule';\n }\n\n if ( !otherRules )\n {\n throw 'rules are required for the ' + ruleName + ' rule';\n }\n\n var validators = Validation.parseRules( otherRules, otherField, database, getAlias );\n\n return function(value, model, setMessage)\n {\n var invalids = 0;\n\n var setInvalid = function(message)\n {\n if ( message )\n {\n invalids++;\n }\n };\n\n for (var i = 0; i < validators.length; i++)\n {\n validators[ i ]( value, model, setInvalid );\n }\n\n return isInvalid( invalids, validators.length ) ? Validation.Stop : value;\n };\n };\n}\n\n// in:X,Y,Z,...\nlistRuleGenerator('in',\n '{$alias} must be one of {$list}.',\n function isInvalid(value, model, inList)\n {\n return !inList( value, model );\n }\n);\n\n// not_in:X,Y,Z,...\nlistRuleGenerator('not_in',\n '{$alias} must not be one of {$list}.',\n function isInvalid(value, model, inList)\n {\n return inList( value, model );\n }\n);\n\nfunction listRuleGenerator(ruleName, defaultMessage, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires a list argument';\n }\n\n var values, inList = false;\n\n if ( isString( params ) )\n {\n values = split( params, /(,)/, '\\\\' );\n }\n else if ( isArray( params ) )\n {\n values = params;\n }\n else if ( isFunction( params ) )\n {\n values = inList;\n }\n\n if ( inList !== false )\n {\n if ( !values || values.length === 0 )\n {\n throw params + ' is not a valid list of values for the ' + ruleName + ' rule';\n }\n }\n\n if ( isPrimitiveArray( values ) )\n {\n var map = mapFromArray( values, true );\n\n inList = function(value)\n {\n return map[ value ];\n };\n }\n else\n {\n inList = function(value)\n {\n return indexOf( values, value, equals );\n };\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var list = joinFriendly( values, 'or' );\n var extra = {\n $params: params,\n $list: list\n };\n\n return function(value, model, setMessage)\n {\n if ( isInvalid( value, model, inList ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate, extra ) );\n }\n\n return value;\n };\n };\n\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n\n// between:3,10\nrangeRuleGenerator('between', {\n 'string': '{$alias} must have between {$start} to {$end} characters.',\n 'number': '{$alias} must be between {$start} and {$end}.',\n 'object': '{$alias} must have between {$start} to {$end} items.'\n },\n function isInvalid(value, start, end) {\n return value < start || value > end;\n }\n);\n\n// not_between\nrangeRuleGenerator('not_between', {\n 'string': '{$alias} must not have between {$start} to {$end} characters.',\n 'number': '{$alias} must not be between {$start} and {$end}.',\n 'object': '{$alias} must not have between {$start} to {$end} items.'\n },\n function isInvalid(value, start, end) {\n return value >= start && value <= end;\n }\n);\n\nfunction rangeRuleGenerator(ruleName, defaultMessages, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n if ( !params )\n {\n throw ruleName + ' validation rule requires a range argument';\n }\n\n var start, end;\n\n if ( isString( params ) )\n {\n var range = split( params, /(\\s*,\\s*)/, '\\\\' );\n\n start = parseFloat( range[0] );\n end = parseFloat( range[1] );\n }\n else if ( isArray( params ) )\n {\n start = params[ 0 ];\n end = params[ 1 ];\n }\n else if ( isObject( params ) )\n {\n start = params.start;\n end = params.end;\n }\n\n if ( isNaN( start ) || isNaN( end ) )\n {\n throw params + ' is not a valid range of numbers for the ' + ruleName + ' rule';\n }\n\n if ( isString( message ) )\n {\n message = {\n 'string': message,\n 'number': message,\n 'object': message\n };\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var extra = {\n $start: start,\n $end: end\n };\n\n return function(value, model, setMessage)\n {\n var size = sizeof( value );\n var type = typeof( value );\n var typeMessage = messageTemplate[ type ];\n\n if ( typeMessage && isInvalid( size, start, end ) )\n {\n extra.$size = size;\n\n setMessage( generateMessage( field, getAlias( field ), value, model, typeMessage, extra ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessages;\n}\n\n\n\nregexRuleGenerator('alpha',\n '{$alias} should only contain alphabetic characters.',\n /^[a-zA-Z]*$/\n);\n\nregexRuleGenerator('alpha_dash',\n '{$alias} should only contain alpha-numeric characters, dashes, and underscores.',\n /^[a-zA-Z0-9_-]*$/\n);\n\nregexRuleGenerator('alpha_num',\n '{$alias} should only contain alpha-numeric characters.',\n /^[a-zA-Z0-9]*$/\n);\n\nregexRuleGenerator('email',\n '{$alias} is not a valid email.',\n /^.+@.+\\..+$/\n);\n\nregexRuleGenerator('url',\n '{$alias} is not a valid URL.',\n /^(https?:\\/\\/)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)$/\n);\n\nregexRuleGenerator('uri',\n '{$alias} is not a valid URI.',\n /^(\\w+:\\/\\/)?[-a-zA-Z0-9@:%._\\+~#=]{2,256}\\.[a-z]{2,6}\\b([-a-zA-Z0-9@:%_\\+.~#?&//=]*)$/\n);\n\nregexRuleGenerator('phone',\n '{$alias} is not a valid phone number.',\n /^1?\\W*([2-9][0-8][0-9])\\W*([2-9][0-9]{2})\\W*([0-9]{4})(\\se?x?t?(\\d*))?$/\n);\n\nfunction regexRuleGenerator(ruleName, defaultMessage, regex)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n checkNoParams( ruleName, field, params );\n\n var messageTemplate = determineMessage( ruleName, message );\n\n return function(value, model, setMessage)\n {\n if ( !regex.test( value ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessage;\n}\n\nValidation.Rules.regex = function(field, params, database, getAlias, message)\n{\n var regex;\n\n if ( isString( params ) )\n {\n var parsed = /^\\/(.*)\\/([gmi]*)$/.exec( params );\n\n if ( parsed )\n {\n regex = new RegExp( parsed[1], parsed[2] );\n }\n }\n else if ( isRegExp( params ) )\n {\n regex = params;\n }\n\n if ( !regex )\n {\n throw params + ' is not a valid regular expression for the regex rule';\n }\n\n var messageTemplate = determineMessage( 'regex', message );\n\n return function(value, model, setMessage)\n {\n if ( !regex.test( value ) )\n {\n setMessage( generateMessage( field, getAlias( field ), value, model, messageTemplate ) );\n }\n\n return value;\n };\n};\n\nValidation.Rules.regex.message = '{$alias} is not a valid value.';\n\n// required\nruleGenerator('required',\n '{$alias} is required.',\n function isInvalid(value) {\n return isEmpty( value );\n }\n);\n\n// min:3\nsizeRuleGenerator('min', {\n 'string': '{$alias} must have a minimum of {$number} characters.',\n 'number': '{$alias} must be at least {$number}.',\n 'object': '{$alias} must have at least {$number} items.'\n },\n function isInvalid(value, number) {\n return value < number;\n }\n);\n\n// greater_than:0\nsizeRuleGenerator('greater_than', {\n 'string': '{$alias} must have more than {$number} characters.',\n 'number': '{$alias} must be greater than {$number}.',\n 'object': '{$alias} must have more than {$number} items.'\n },\n function isInvalid(value, number) {\n return value <= number;\n }\n);\n\n// max:10\nsizeRuleGenerator('max', {\n 'string': '{$alias} must have no more than {$number} characters.',\n 'number': '{$alias} must be no more than {$number}.',\n 'object': '{$alias} must have no more than {$number} items.'\n },\n function isInvalid(value, number) {\n return value > number;\n }\n);\n\n// less_than:5\nsizeRuleGenerator('less_than', {\n 'string': '{$alias} must have less than {$number} characters.',\n 'number': '{$alias} must be less than {$number}.',\n 'object': '{$alias} must have less than {$number} items.'\n },\n function isInvalid(value, number) {\n return value >= number;\n }\n);\n\n// equal:4.5\nsizeRuleGenerator('equal', {\n 'string': '{$alias} must have {$number} characters.',\n 'number': '{$alias} must equal {$number}.',\n 'object': '{$alias} must have {$number} items.'\n },\n function isInvalid(value, number) {\n return value !== number;\n }\n);\n\n// not_equal:0\nsizeRuleGenerator('not_equal', {\n 'string': '{$alias} must not have {$number} characters.',\n 'number': '{$alias} must not equal {$number}.',\n 'object': '{$alias} must not have {$number} items.'\n },\n function isInvalid(value, number) {\n return value === number;\n }\n);\n\nfunction sizeRuleGenerator(ruleName, defaultMessages, isInvalid)\n{\n Validation.Rules[ ruleName ] = function(field, params, database, getAlias, message)\n {\n var number;\n\n if ( isString( params ) )\n {\n number = parseFloat( params );\n }\n else if ( isNumber( params ) )\n {\n number = params;\n }\n\n if ( isNaN( number ) )\n {\n throw '\"' + params + '\" is not a valid number for the ' + ruleName + ' rule';\n }\n\n if ( isString( message ) )\n {\n message = {\n 'string': message,\n 'number': message,\n 'object': message\n };\n }\n\n var messageTemplate = determineMessage( ruleName, message );\n var extra = {\n $number: params\n };\n\n return function(value, model, setMessage)\n {\n var size = sizeof( value );\n var type = typeof( value );\n var typeMessage = messageTemplate[ type ];\n\n if ( typeMessage && isInvalid( size, number ) )\n {\n extra.$size = size;\n\n setMessage( generateMessage( field, getAlias( field ), value, model, typeMessage, extra ) );\n }\n\n return value;\n };\n };\n\n Validation.Rules[ ruleName ].message = defaultMessages;\n}\n\n\nruleGenerator('array',\n '{$alias} must be an array.',\n function isInvalid(value) {\n return !isArray( value );\n }\n);\n\nruleGenerator('object',\n '{$alias} must be an object.',\n function isInvalid(value) {\n return !isObject( value );\n }\n);\n\nruleGenerator('string',\n '{$alias} must be a string.',\n function isInvalid(value) {\n return !isString( value );\n }\n);\n\nruleGenerator('number',\n '{$alias} must be a number.',\n function isInvalid(value) {\n return !isNumber( value );\n }\n);\n\nruleGenerator('boolean',\n '{$alias} must be a true or false.',\n function isInvalid(value) {\n return !isBoolean( value );\n }\n);\n\nruleGenerator('model',\n '{$alias} must have a value.',\n function isInvalid(value) {\n return !(value instanceof Model);\n }\n);\n\nruleGenerator('whole',\n '{$alias} must be a whole number.',\n function isInvalid(value, model, setValue) {\n var parsed = tryParseInt( value );\n var numeric = parseFloat( value );\n var invalid = !isNumber( parsed );\n if ( !invalid ) {\n invalid = Math.floor( parsed ) !== numeric;\n if ( !invalid ) {\n setValue( parsed );\n }\n }\n return invalid;\n }\n);\n\nruleGenerator('numeric',\n '{$alias} must be numeric.',\n function isInvalid(value, model, setValue) {\n var parsed = tryParseFloat( value );\n var invalid = !isNumber( parsed );\n if ( !invalid ) {\n setValue( parsed );\n }\n return invalid;\n }\n);\n\nruleGenerator('yesno',\n '{$alias} must be a yes or no.',\n function isInvalid(value, model, setValue) {\n var mapped = Validation.Rules.yesno.map[ value ];\n var invalid = !isBoolean( mapped );\n if ( !invalid ) {\n setValue( mapped );\n }\n return invalid;\n }\n);\n\nValidation.Rules.yesno.map =\n{\n 'true': true,\n 't': true,\n 'yes': true,\n 'y': true,\n '1': true,\n 'false': false,\n 'f': false,\n 'no': false,\n 'n': false,\n '0': false\n};\n\nValidation.Rules.abs = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n value = tryParseFloat( value );\n\n if ( isNumber( value ) )\n {\n value = Math.abs( value );\n }\n\n return value;\n };\n};\n\nValidation.Rules.apply = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n model.$set( field, value );\n \n return value;\n };\n};\n\nValidation.Rules.base64 = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n if ( global.btoa )\n {\n value = global.btoa( value );\n }\n\n return value;\n };\n};\n\nValidation.Rules.ceil = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n value = tryParseFloat( value );\n \n if ( isNumber( value ) )\n {\n value = Math.ceil( value );\n }\n\n return value;\n };\n};\n\nValidation.Rules.endOfDay = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n return endOfDay( value );\n };\n};\n\nValidation.Rules.filter = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n if ( isArray( value ) )\n {\n for (var i = value.length - 1; i >= 0; i--)\n {\n if ( !isValue( value[ i ] ) )\n {\n value.splice( i, 1 );\n }\n }\n }\n else if ( isObject( value ) )\n {\n for (var prop in value)\n {\n if ( !isValue( value[ prop ] ) )\n {\n delete value[ prop ];\n }\n }\n }\n\n return value;\n };\n};\n\nValidation.Rules.floor = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n value = tryParseFloat( value );\n \n if ( isNumber( value ) )\n {\n value = Math.floor( value );\n }\n\n return value;\n };\n};\n\nValidation.Rules.mod = function(field, params, database, alias, message)\n{\n var number = tryParseFloat( params );\n\n if ( !isNumber( number ) )\n {\n throw '\"' + number + '\" is not a valid number for the mod rule.';\n }\n\n return function(value, model, setMessage)\n {\n value = tryParseFloat( value );\n\n if ( isNumber( value ) )\n {\n value = value % number;\n }\n\n return value;\n };\n};\n\nValidation.Rules.null = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n model.$set( field, null );\n\n return null;\n };\n};\n\nValidation.Rules.round = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n value = tryParseFloat( value );\n\n if ( isNumber( value ) )\n {\n value = Math.round( value );\n }\n\n return value;\n };\n};\n\nValidation.Rules.startOfDay = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n return startOfDay( value );\n };\n};\n\nValidation.Rules.trim = function(field, params, database, alias, message)\n{\n var trim = (function()\n {\n if ( String.prototype.trim )\n {\n return function(x) {\n return x.trim();\n };\n }\n\n var regex = /^[\\s\\uFEFF\\xA0]+|[\\s\\uFEFF\\xA0]+$/g;\n\n return function(x)\n {\n return x.replace( regex, '' );\n };\n\n })();\n\n return function(value, model, setMessage)\n {\n if ( isString( value ) )\n {\n value = trim( value );\n }\n\n return value;\n };\n};\n\nValidation.Rules.unbase64 = function(field, params, database, alias, message)\n{\n return function(value, model, setMessage)\n {\n if ( global.atob )\n {\n value = global.atob( value );\n }\n\n return value;\n };\n};\n\n\n\n Rekord.Validation = Validation;\n\n Rekord.ruleGenerator = ruleGenerator;\n Rekord.rangeRuleGenerator = rangeRuleGenerator;\n Rekord.collectionRuleGenerator = collectionRuleGenerator;\n Rekord.dateRuleGenerator = dateRuleGenerator;\n Rekord.fieldListRuleGenerator = fieldListRuleGenerator;\n Rekord.fieldsRuleGenerator = fieldsRuleGenerator;\n Rekord.foreignRuleGenerator = foreignRuleGenerator;\n Rekord.subRuleGenerator = subRuleGenerator;\n Rekord.listRuleGenerator = listRuleGenerator;\n Rekord.regexRuleGenerator = regexRuleGenerator;\n Rekord.sizeRuleGenerator = sizeRuleGenerator;\n\n Rekord.joinFriendly = joinFriendly;\n Rekord.tryParseFloat = tryParseFloat;\n Rekord.tryParseInt = tryParseInt;\n Rekord.startOfDay = startOfDay;\n Rekord.endOfDay = endOfDay;\n Rekord.determineMessage = determineMessage;\n Rekord.mapFromArray = mapFromArray;\n Rekord.checkNoParams = checkNoParams;\n Rekord.generateMessage = generateMessage;\n\n})(this, this.Rekord);\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/package.json b/package.json index a7be2b2..1764df4 100644 --- a/package.json +++ b/package.json @@ -15,9 +15,11 @@ "gulp": "^3.9.0", "gulp-check-filesize": "^2.0.1", "gulp-concat": "^2.6.0", + "gulp-insert": "^0.5.0", "gulp-jshint": "^2.0.1", "gulp-load-plugins": "^1.1.0", "gulp-qunit": "^1.3.0", + "gulp-rename": "^1.2.2", "gulp-shell": "^0.5.1", "gulp-sourcemaps": "^1.6.0", "gulp-uglify": "^1.5.1", @@ -25,8 +27,8 @@ "gulp-watch": "^4.3.6", "jaguarjs-jsdoc": "0.0.1", "jsdoc": "^3.4.0", - "merge-stream": "^1.0.0", - "jshint": "^2.9.2" + "jshint": "^2.9.2", + "merge-stream": "^1.0.0" }, "dependencies": { "rekord": "^1.2.0"