diff --git a/.gitignore b/.gitignore index 3c3629e..a088b6f 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ node_modules +bower_components diff --git a/bower.json b/bower.json index 2013fe8..a7a02a1 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "rekord-validation", - "version": "1.4.2", + "version": "1.4.3", "homepage": "https://github.com/Rekord/rekord-validation", "authors": [ "Philip Diffenderfer " diff --git a/build/rekord-validation.js b/build/rekord-validation.js index c5bcfa0..a10185b 100644 --- a/build/rekord-validation.js +++ b/build/rekord-validation.js @@ -1,6 +1,29 @@ -/* rekord-validation 1.4.2 - Advanced validation rules for rekord by Philip Diffenderfer */ -(function(global, Rekord, undefined) +/* rekord-validation 1.4.3 - Advanced validation rules for rekord by Philip Diffenderfer */ +// UMD (Universal Module Definition) +(function (root, factory) { + if (typeof define === 'function' && define.amd) // jshint ignore:line + { + // AMD. Register as an anonymous module. + define(['Rekord'], function(Rekord) { // jshint ignore:line + return factory(root, Rekord); + }); + } + else if (typeof module === 'object' && module.exports) // jshint ignore:line + { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(global, require('Rekord')); // jshint ignore:line + } + else + { + // Browser globals (root is window) + root.Rekord = factory(root, root.Rekord); + } +}(this, function(global, Rekord, undefined) +{ + var Model = Rekord.Model; var Database = Rekord.Database; var Promise = Rekord.Promise; @@ -1997,7 +2020,6 @@ Validation.Rules.unbase64 = function(field, params, database, alias, message) }; - Rekord.Validation = Validation; Rekord.ruleGenerator = ruleGenerator; @@ -2022,4 +2044,6 @@ Validation.Rules.unbase64 = function(field, params, database, alias, message) Rekord.checkNoParams = checkNoParams; Rekord.generateMessage = generateMessage; -})(this, this.Rekord); + return Rekord; + +})); diff --git a/build/rekord-validation.min.js b/build/rekord-validation.min.js index d3ab484..ec7e1e1 100644 --- a/build/rekord-validation.min.js +++ b/build/rekord-validation.min.js @@ -1,3 +1,3 @@ -/* rekord-validation 1.4.2 - 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); +/* rekord-validation 1.4.3 - Advanced validation rules for rekord by Philip Diffenderfer */ +!function(e,t){"function"==typeof define&&define.amd?define(["Rekord"],function(r){return t(e,r)}):"object"==typeof module&&module.exports?module.exports=t(global,require("Rekord")):e.Rekord=t(e,e.Rekord)}(this,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 V(e)?e.setHours(0,0,0,0):z(e)&&(e-=e%864e5),e}function s(e){return V(e)?e.setHours(23,59,59,999):z(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(d(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(d(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!z(e)}),u("boolean","{$alias} must be a true or false.",function(e){return!N(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=!z(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=!z(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=!N(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),z(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),z(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),z(e)&&(e=Math.floor(e)),e}},K.Rules.mod=function(e,t,r,a,i){var s=n(t);if(!z(s))throw'"'+s+'" is not a valid number for the mod rule.';return function(e,t,r){return e=n(e),z(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),z(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=m,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=d,t}); //# sourceMappingURL=rekord-validation.min.js.map diff --git a/build/rekord-validation.min.js.map b/build/rekord-validation.min.js.map index 99cd489..7df5c36 100644 --- a/build/rekord-validation.min.js.map +++ b/build/rekord-validation.min.js.map @@ -1 +1 @@ -{"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","testValue","$get","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","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.4.2 - 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 var testValue = otherField === field ? value : model.$get( otherField );\n\n for (var i = 0; i < validators.length; i++)\n {\n validators[ i ]( testValue, 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 +{"version":3,"sources":["rekord-validation.min.js"],"names":["root","factory","define","amd","Rekord","module","exports","global","require","this","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","testValue","$get","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","$trigger","PreValidate","$valid","$validations","$validationMessages","chain","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.4.3 - Advanced validation rules for rekord by Philip Diffenderfer */\n// UMD (Universal Module Definition)\n(function (root, factory)\n{\n if (typeof define === 'function' && define.amd) // jshint ignore:line\n {\n // AMD. Register as an anonymous module.\n define(['Rekord'], function(Rekord) { // jshint ignore:line\n return factory(root, Rekord);\n });\n }\n else if (typeof module === 'object' && module.exports) // jshint ignore:line\n {\n // Node. Does not work with strict CommonJS, but\n // only CommonJS-like environments that support module.exports,\n // like Node.\n module.exports = factory(global, require('Rekord')); // jshint ignore:line\n }\n else\n {\n // Browser globals (root is window)\n root.Rekord = factory(root, root.Rekord);\n }\n}(this, function(global, Rekord, undefined)\n{\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 var testValue = otherField === field ? value : model.$get( otherField );\n\n for (var i = 0; i < validators.length; i++)\n {\n validators[ i ]( testValue, 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 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 return Rekord;\n\n}));\n"],"sourceRoot":"/source/"} \ No newline at end of file diff --git a/package.json b/package.json index 4604f3e..e275b10 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "rekord-validation", - "version": "1.4.2", + "version": "1.4.3", "description": "Advanced validation rules for rekord", "author": "Philip Diffenderfer", "license": "MIT", diff --git a/src/footer.js b/src/footer.js index 1b8f596..647cc62 100644 --- a/src/footer.js +++ b/src/footer.js @@ -1,5 +1,4 @@ - Rekord.Validation = Validation; Rekord.ruleGenerator = ruleGenerator; @@ -24,4 +23,6 @@ Rekord.checkNoParams = checkNoParams; Rekord.generateMessage = generateMessage; -})(this, this.Rekord); + return Rekord; + +})); diff --git a/src/header.js b/src/header.js index 6b8c60b..86ad4bf 100644 --- a/src/header.js +++ b/src/header.js @@ -1,5 +1,28 @@ -(function(global, Rekord, undefined) +// UMD (Universal Module Definition) +(function (root, factory) { + if (typeof define === 'function' && define.amd) // jshint ignore:line + { + // AMD. Register as an anonymous module. + define(['Rekord'], function(Rekord) { // jshint ignore:line + return factory(root, Rekord); + }); + } + else if (typeof module === 'object' && module.exports) // jshint ignore:line + { + // Node. Does not work with strict CommonJS, but + // only CommonJS-like environments that support module.exports, + // like Node. + module.exports = factory(global, require('Rekord')); // jshint ignore:line + } + else + { + // Browser globals (root is window) + root.Rekord = factory(root, root.Rekord); + } +}(this, function(global, Rekord, undefined) +{ + var Model = Rekord.Model; var Database = Rekord.Database; var Promise = Rekord.Promise; diff --git a/test/index.html b/test/index.html index 3ba9637..667c9d8 100644 --- a/test/index.html +++ b/test/index.html @@ -7,7 +7,7 @@ - +