From da5e9725778045efc316c87e7c3eaa8dc781bc1e Mon Sep 17 00:00:00 2001 From: Ghislain B Date: Thu, 29 Oct 2015 23:28:51 -0400 Subject: [PATCH] Added custom validation #75 - Added validation through custom user defined function --- app.js | 2 +- bower.json | 2 +- changelog.txt | 1 + dist/angular-validation.min.js | 12 +- more-examples/customJavascript/app.js | 78 +++++++++++++ more-examples/customJavascript/index.html | 117 +++++++++++++++++++ package.json | 2 +- protractor/conf.js | 5 +- protractor/custom_spec.js | 132 ++++++++++++++++++++++ readme.md | 3 +- src/validation-common.js | 110 ++++++++++++++++-- src/validation-rules.js | 8 ++ src/validation-service.js | 21 ++-- 13 files changed, 467 insertions(+), 26 deletions(-) create mode 100644 more-examples/customJavascript/app.js create mode 100644 more-examples/customJavascript/index.html create mode 100644 protractor/custom_spec.js diff --git a/app.js b/app.js index 8e6543a..a72ed91 100644 --- a/app.js +++ b/app.js @@ -83,7 +83,7 @@ myApp.controller('CtrlValidationDirective', ['$q', '$scope', 'validationService' // -- Controller to use Angular-Validation Directive with 2 forms // on this page we will pre-validate the form and show all errors on page load // --------------------------------------------------------------- -myApp.controller('Ctrl2forms', ['$scope', 'validationService', function ($scope, validationService) { +myApp.controller('Ctrl2forms', ['validationService', function (validationService) { var vm = this; // use the ControllerAs alias syntax // set the global options BEFORE any function declarations, we will prevalidate current form diff --git a/bower.json b/bower.json index 601db91..1e7fcb7 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-validation-ghiscoding", - "version": "1.4.10", + "version": "1.4.11", "author": "Ghislain B.", "description": "Angular-Validation Directive and Service (ghiscoding)", "main": [ diff --git a/changelog.txt b/changelog.txt index 4cf59fc..b2b767f 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,6 @@ Angular-Validation change logs +1.4.11 (2015-10-29) Enhancement #75 - Added custom rules validation through custom functions. Fixed issue #76 - problem with ui-mask in directive. 1.4.10 (2015-10-12) Sanitized error messages. Fixed issue #69 - Stop when invalid characters typed on input[number]. 1.4.9 (2015-10-05) Enhancement #57, #66, #67 - Added 3rd party addon validation (like ngTagsInput, Angular Multiselect, Dropdown multi-select, etc...) 1.4.8 (2015-09-12) Fixed issue #68 - Matching validation issue (password confirmation). diff --git a/dist/angular-validation.min.js b/dist/angular-validation.min.js index adb4b95..42daffa 100644 --- a/dist/angular-validation.min.js +++ b/dist/angular-validation.min.js @@ -2,11 +2,11 @@ * Angular-Validation Directive and Service (ghiscoding) * http://github.com/ghiscoding/angular-validation * @author: Ghislain B. - * @version: 1.4.10 + * @version: 1.4.11 * @license: MIT - * @build: Mon Oct 12 2015 22:47:06 GMT-0400 (Eastern Daylight Time) + * @build: Thu Oct 29 2015 22:48:12 GMT-0400 (Eastern Daylight Time) */ -angular.module("ghiscoding.validation",["pascalprecht.translate"]).directive("validation",["$q","$timeout","validationCommon",function(a,e,i){return{restrict:"A",require:"ngModel",link:function(t,n,r,l){function o(i,r){var o=a.defer(),d=!1,m="undefined"!=typeof r?r:V.typingLimit,s=V.getFormElementByName(l.$name);if(Array.isArray(i)){if($=[],E="",m=0,i.length>0)return"function"==typeof s.ctrl.$setTouched&&s.ctrl.$setTouched(),u(i,typeof i);m=0}return i&&i.badInput?v():(V.validate(i,!1),V.isFieldRequired()||""!==i&&null!==i&&"undefined"!=typeof i?(s&&(s.isValidationCancelled=!1),(i||V.isFieldRequired())&&l.$setValidity("validation",!1),"SELECT"===n.prop("tagName").toUpperCase()?(d=V.validate(i,!0),l.$setValidity("validation",d),o.resolve({isFieldValid:d,formElmObj:s,value:i}),o.promise):("undefined"!=typeof i&&(0===r?(d=V.validate(i,!0),t.$evalAsync(l.$setValidity("validation",d)),o.resolve({isFieldValid:d,formElmObj:s,value:i})):(V.updateErrorMsg(""),e.cancel(b),b=e(function(){d=V.validate(i,!0),t.$evalAsync(l.$setValidity("validation",d)),o.resolve({isFieldValid:d,formElmObj:s,value:i})},m))),o.promise)):(f(),o.resolve({isFieldValid:!0,formElmObj:s,value:i}),o.promise))}function d(a,e,i){var t=o(a,0);t&&"function"==typeof t.then&&($.push(t),parseInt(e)===i-1&&$.forEach(function(a){a.then(function(a){switch(O){case"all":if(a.isFieldValid===!1){var e=V.getGlobalOptions();a.formElmObj.translatePromise.then(function(i){E.length>0&&e.displayOnlyLastErrorMsg?E="["+a.value+"] :: "+(a.formElmObj.validator&&a.formElmObj.validator.params?String.format(i,a.formElmObj.validator.params):i):E+=" ["+a.value+"] :: "+(a.formElmObj.validator&&a.formElmObj.validator.params?String.format(i,a.formElmObj.validator.params):i),V.updateErrorMsg(E,{isValid:!1}),V.addToValidationSummary(a.formElmObj,E)})}break;case"one":default:a.isFieldValid===!0&&(l.$setValidity("validation",!0),f())}})}))}function m(a){var e=V.getFormElementByName(l.$name),i="undefined"!=typeof a.target.value?a.target.value:l.$modelValue;e.isValidationCancelled?l.$setValidity("validation",!0):o(i,10)}function u(a,e){var i=a.length;if("string"===e)for(var t in a)d(a[t],t,i);else if("object"===e)for(var t in a)if(a.hasOwnProperty(t)){var n=a[t];for(var r in n)if(n.hasOwnProperty(r)){if(j&&r!==j)continue;d(n[r],t,i)}}}function s(){f(),V.removeFromValidationSummary(h);var a=V.arrayFindObject(g,"elmName",l.$name);a&&a.watcherHandler()}function f(){var a=V.getFormElementByName(l.$name);a&&(a.isValidationCancelled=!0),e.cancel(b),V.updateErrorMsg(""),l.$setValidity("validation",!0),p()}function v(){e.cancel(b);var a=V.getFormElementByName(l.$name);V.updateErrorMsg("INVALID_KEY_CHAR",{isValid:!1,translate:!0}),V.addToValidationSummary(a,"INVALID_KEY_CHAR",!0)}function c(){return!!n.prop("validity")&&n.prop("validity").badInput===!0}function y(){var a=l.$modelValue||"";Array.isArray(a)||l.$setValidity("validation",V.validate(a,!1));var e=V.getFormElementByName(l.$name);e&&(e.isValidationCancelled=!1),p(),n.bind("blur",m)}function p(){"function"==typeof m&&n.unbind("blur",m)}var b,V=new i(t,n,r,l),E="",$=[],g=[],h=r.name,O=r.hasOwnProperty("validArrayRequireHowMany")?r.validArrayRequireHowMany:"one",j=r.hasOwnProperty("validationArrayObjprop")?r.validationArrayObjprop:null,F=t.$watch(function(){return c()?{badInput:!0}:l.$modelValue},function(a){return a&&a.badInput?(p(),v()):void o(a)},!0);g.push({elmName:h,watcherHandler:F}),r.$observe("disabled",function(a){a?(f(),V.removeFromValidationSummary(h)):y()}),n.on("$destroy",function(){s()}),t.$watch(function(){return n.attr("validation")},function(a){"undefined"==typeof a||""===a?s():(V.defineValidation(),y())}),n.bind("blur",m)}}}]); -angular.module("ghiscoding.validation").factory("validationCommon",["$rootScope","$translate","validationRules",function(e,t,a){function r(e,a,r){if("undefined"!=typeof e&&null!=e){var n=e.ctrl&&e.ctrl.$name?e.ctrl.$name:e.attrs&&e.attrs.name?e.attrs.name:e.elm.attr("name"),i=A(n,e),o=O(q,"field",n);if(o>=0&&""===a)q.splice(o,1);else if(""!==a){r&&(a=t.instant(a));var l=e.attrs&&e.friendlyName?t.instant(e.friendlyName):"",s={field:n,friendlyName:l,message:a,formName:i?i.$name:null};o>=0?q[o]=s:q.push(s)}if(e.scope.$validationSummary=q,i&&(i.$validationSummary=$(q,"formName",i.$name)),k&&k.controllerAs&&(k.controllerAs.$validationSummary=q,i)){var p=i.$name.indexOf(".")>=0?i.$name.split(".")[1]:i.$name,m=k.controllerAs[p]?k.controllerAs[p]:e.elm.controller()[p];m.$validationSummary=$(q,"formName",i.$name)}return q}}function n(){var e=this,t={};e.validators=[],e.typingLimit=F,e.validatorAttrs.hasOwnProperty("debounce")?e.typingLimit=parseInt(e.validatorAttrs.debounce,10):e.validatorAttrs.hasOwnProperty("typingLimit")?e.typingLimit=parseInt(e.validatorAttrs.typingLimit,10):k&&k.hasOwnProperty("debounce")&&(e.typingLimit=parseInt(k.debounce,10));var r=e.validatorAttrs.rules||e.validatorAttrs.validation;if(r.indexOf("pattern=/")>=0){var n=r.match(/pattern=(\/.*\/[igm]*)(:alt=(.*))?/);if(!n||n.length<3)throw'Regex validator within the validation needs to be define with an opening "/" and a closing "/", please review your validator.';var i=n[1],o=n[2]?n[2].replace(/\|(.*)/,""):"",l=i.match(new RegExp("^/(.*?)/([gimy]*)$")),s=new RegExp(l[1],l[2]);t={altMsg:o,message:o.replace(/:alt=/,""),pattern:s},r=r.replace("pattern="+i,"pattern")}else if(r.indexOf("regex:")>=0){var n=r.match("regex:(.*?):regex");if(n.length<2)throw'Regex validator within the validation needs to be define with an opening "regex:" and a closing ":regex", please review your validator.';var p=n[1].split(":=");t={message:p[0],pattern:p[1]},r=r.replace(n[0],"regex:")}var m=r.split("|");if(m){e.bFieldRequired=r.indexOf("required")>=0?!0:!1;for(var d=0,u=m.length;u>d;d++){var c=m[d].split(":"),f=m[d].indexOf("alt=")>=0?!0:!1;e.validators[d]=a.getElementValidators({altText:f===!0?2===c.length?c[1]:c[2]:"",customRegEx:t,rule:c[0],ruleParams:f&&2===c.length?null:c[1]})}}return e}function i(e){return b(L,"fieldName",e)}function o(e){return e?$(L,"formName",e):L}function l(){return k}function s(e,t,a,r){this.scope=e,this.elm=t,this.ctrl=r,this.validatorAttrs=a,h(t,a,r,e),this.defineValidation()}function p(){var e=this;return e.bFieldRequired}function m(e,t){var a={};for(var r in e)a[r]=e[r];for(var r in t)a[r]=t[r];return a}function d(e){var t=O(L,"fieldName",e);t>=0&&L.splice(t,1)}function u(e,t){var a=this,r=A(e,a),n=t||q,i=O(n,"field",e);if(i>=0&&n.splice(i,1),i=O(q,"field",e),i>=0&&q.splice(i,1),a.scope.$validationSummary=q,r&&(r.$validationSummary=$(q,"formName",r.$name)),k&&k.controllerAs&&(k.controllerAs.$validationSummary=q,r)){var o=r.$name.indexOf(".")>=0?r.$name.split(".")[1]:r.$name;k.controllerAs[o]&&(k.controllerAs[o].$validationSummary=$(q,"formName",r.$name))}return q}function c(e){k.displayOnlyLastErrorMsg=e}function f(e){var t=this;return k=m(k,e),t}function g(e,a){var r=this;a&&a.obj&&(r=a.obj,r.validatorAttrs=a.obj.attrs);var n=a&&a.elm?a.elm:r.elm,i=n&&n.attr("name")?n.attr("name"):null;if("undefined"==typeof i||null===i){var o=n?n.attr("ng-model"):"unknown";throw'Angular-Validation Service requires you to have a (name="") attribute on the element to validate... Your element is: ng-model="'+o+'"'}var l=a&&a.translate?t.instant(e):e,s=i.replace(/[|&;$%@"<>()+,\[\]\{\}]/g,""),p=null;if(r.validatorAttrs&&r.validatorAttrs.hasOwnProperty("validationErrorTo")){var m=r.validatorAttrs.validationErrorTo.charAt(0),d="."===m||"#"===m?r.validatorAttrs.validationErrorTo:"#"+r.validatorAttrs.validationErrorTo;p=angular.element(document.querySelector(d))}p&&0!==p.length||(p=angular.element(document.querySelector(".validation-"+s)));var u=a&&a.isSubmitted?a.isSubmitted:!1;a&&!a.isValid&&(u||r.ctrl.$dirty||r.ctrl.$touched)?p.length>0?p.html(l):n.after(''+l+""):p.html("")}function v(e,a){var n,o,l=this,s=!0,p=!0,m="";"undefined"==typeof e&&(e="");for(var d=l.ctrl&&l.ctrl.$name?l.ctrl.$name:l.attrs&&l.attrs.name?l.attrs.name:l.elm.attr("name"),u=i(d),c=l.validatorAttrs.rules||l.validatorAttrs.validation,f=0,g=l.validators.length;g>f;f++){if(o=l.validators[f],"autoDetect"===o.type&&(o=x(e)?{condition:o.conditionNum,message:o.messageNum,params:o.params,type:"conditionalNumber"}:{pattern:o.patternLength,message:o.messageLength,params:o.params,type:"regex"}),"conditionalDate"===o.type){var v=s=!1;if(e instanceof Date?v=!0:(n=new RegExp(o.pattern),v=(!o.pattern||"/\\S+/"===o.pattern.toString()||c&&"required"===o.pattern)&&null===e?!1:n.test(e)),v){var h=o.dateType,b=e instanceof Date?e:N(e,h).getTime();if(2==o.params.length){var $=N(o.params[0],h).getTime(),O=N(o.params[1],h).getTime(),S=R(o.condition[0],b,$),A=R(o.condition[1],b,O);s=S&&A?!0:!1}else{var E=N(o.params[0],h).getTime();s=R(o.condition,b,E)}}}else if("conditionalNumber"===o.type)if(2==o.params.length){var S=R(o.condition[0],parseFloat(e),parseFloat(o.params[0])),A=R(o.condition[1],parseFloat(e),parseFloat(o.params[1]));s=S&&A?!0:!1}else s=R(o.condition,parseFloat(e),parseFloat(o.params[0]));else if("matching"===o.type){var V=o.params[0],w=l.scope.$eval(V),T=angular.element(document.querySelector('[name="'+V+'"]')),F=o,L=l.ctrl,q=i(l.ctrl.$name);s=R(o.condition,e,w)&&!!e,T&&T.attr("friendly-name")?o.params[1]=T.attr("friendly-name"):o.params.length>1&&(o.params[1]=o.params[1]),l.scope.$watch(V,function(e,a){var r=R(F.condition,L.$viewValue,e);if(e!==a){if(r)y(l,q,"",!0,!0);else{q.isValid=!1;var n=F.message;F.altText&&F.altText.length>0&&(n=F.altText.replace("alt=","")),t(n).then(function(e){m=" "+(F&&F.params?String.format(e,F.params):e),y(l,q,m,r,!0)})}L.$setValidity("validation",r)}},!0)}else if("remote"===o.type){if(e&&a){l.ctrl.$processing=!0;var C=null,G=o.params[0];if(-1===G.indexOf("."))C=l.scope[G];else{var M=G.split(".");C=l.scope;for(var j=0,D=M.length;D>j;j++)C=C[M[j]]}var P="function"==typeof C?C():null;if(U.length>1)for(;U.length>0;){var I=U.pop();"function"==typeof I.abort&&I.abort()}if(U.push(P),!P||"function"!=typeof P.then)throw"Remote Validation requires a declared function (in your Controller) which also needs to return a Promise, please review your code.";l.ctrl.$setValidity("remote",!1),function(e){P.then(function(t){t=t.data||t,U.pop(),l.ctrl.$processing=!1;var r=m+" ";"boolean"==typeof t?s=t?!0:!1:"object"==typeof t&&(s=t.isValid?!0:!1),s===!1&&(u.isValid=!1,r+=t.message||e,y(l,u,r,!1,a)),s===!0&&p===!0&&(u.isValid=!0,l.ctrl.$setValidity("remote",!0),y(l,u,"",!0,a))})}(o.altText)}}else{var H=l.attrs?l.attrs.ngDisabled:l.validatorAttrs.ngDisabled;l.elm.prop("disabled")||l.scope.$eval(H)?s=!0:"string"==typeof e&&""===e&&l.elm.prop("type")&&"NUMBER"===l.elm.prop("type").toUpperCase()?s=!1:(n=new RegExp(o.pattern,o.patternFlag),s=(!o.pattern||"/\\S+/"===o.pattern.toString()||c&&"required"===o.pattern)&&null===e?!1:n.test(e))}(!l.bFieldRequired&&!e||l.elm.prop("disabled")||l.scope.$eval(H))&&(s=!0),s||(p=!1,function(e,r,n){var i=n.message;n.altText&&n.altText.length>0&&(i=n.altText.replace("alt=",""));var o=t(i);e.translatePromise=o,e.validator=n,o.then(function(t){m.length>0&&k.displayOnlyLastErrorMsg?m=" "+(n&&n.params?String.format(t,n.params):t):m+=" "+(n&&n.params?String.format(t,n.params):t),y(l,e,m,p,a)})["catch"](function(){n.altText&&n.altText.length>0&&(m.length>0&&k.displayOnlyLastErrorMsg?m=" "+i:m+=" "+i,y(l,e,m,p,a))})}(u,s,o))}return s&&(r(l,""),l.updateErrorMsg("",{isValid:s})),u&&(u.isValid=p,p&&(u.message="")),p}function h(e,a,r,n){var i=a.name?a.name:e.attr("name"),o=A(i,{scope:n}),l=a&&a.friendlyName?t.instant(a.friendlyName):"",s={fieldName:i,friendlyName:l,elm:e,attrs:a,ctrl:r,scope:n,isValid:!1,message:"",formName:o?o.$name:null},p=O(L,"fieldName",e.attr("name"));return p>=0?L[p]=s:L.push(s),L}function y(e,t,a,n,i){a=a.trim(),t&&t.isValidationCancelled===!0&&(a=""),r(t,a),t&&(t.message=a),(e.validatorAttrs.preValidateFormElements||k.preValidateFormElements)&&(t&&"function"==typeof e.ctrl.$setTouched&&t.ctrl.$setTouched(),e.ctrl.$dirty===!1&&g(a,{isSubmitted:!0,isValid:n,obj:t})),i&&t&&!t.isValid?e.updateErrorMsg(a,{isValid:n,obj:t}):t&&t.isValid&&r(t,"")}function b(e,t,a){if(e)for(var r=0;rr;r++)t[a[r]]&&(t=t[a[r]]);return t}function A(e,t){if(k&&k.formName){var a=document.querySelector('[name="'+k.formName+'"]');if(a)return a.$name=k.formName,a}for(var r=document.getElementsByName(e),a=null,n=0;n=0?S(i.name,t.scope):t.scope[i.name]))return"undefined"==typeof a.$name&&(a.$name=i.name),a}if(i&&i.name){var o={$name:i.name,specialNote:"Created by Angular-Validation for Isolated Scope usage"};if(k&&k.controllerAs&&i.name.indexOf(".")>=0){var l=i.name.split(".");return t.scope[l[0]][l[1]]=o}return t.scope[i.name]=o}return null}function x(e){return!isNaN(parseFloat(e))&&isFinite(e)}function N(e,t){var a="",r="-",n=[],i=[],o="",l="",s="";switch(t.toUpperCase()){case"EURO_LONG":case"EURO-LONG":a=e.substring(0,10),r=e.substring(2,3),n=E(a,r),s=n[0],l=n[1],o=n[2],i=e.length>8?e.substring(9).split(":"):null;break;case"UK":case"EURO":case"EURO_SHORT":case"EURO-SHORT":case"EUROPE":a=e.substring(0,8),r=e.substring(2,3),n=E(a,r),s=n[0],l=n[1],o=parseInt(n[2])<50?"20"+n[2]:"19"+n[2],i=e.length>8?e.substring(9).split(":"):null;break;case"US_LONG":case"US-LONG":a=e.substring(0,10),r=e.substring(2,3),n=E(a,r),l=n[0],s=n[1],o=n[2],i=e.length>8?e.substring(9).split(":"):null;break;case"US":case"US_SHORT":case"US-SHORT":a=e.substring(0,8),r=e.substring(2,3),n=E(a,r),l=n[0],s=n[1],o=parseInt(n[2])<50?"20"+n[2]:"19"+n[2],i=e.length>8?e.substring(9).split(":"):null;break;case"ISO":default:a=e.substring(0,10),r=e.substring(4,5),n=E(a,r),o=n[0],l=n[1],s=n[2],i=e.length>10?e.substring(11).split(":"):null}var p=i&&3===i.length?i[0]:0,m=i&&3===i.length?i[1]:0,d=i&&3===i.length?i[2]:0;return new Date(o,l-1,s,p,m,d)}function E(e,t){var a=[];switch(t){case"/":a=e.split("/");break;case".":a=e.split(".");break;case"-":default:a=e.split("-")}return a}function R(e,t,a){var r=!1;switch(e){case"<":r=a>t?!0:!1;break;case"<=":r=a>=t?!0:!1;break;case">":r=t>a?!0:!1;break;case">=":r=t>=a?!0:!1;break;case"!=":case"<>":r=t!=a?!0:!1;break;case"!==":r=t!==a?!0:!1;break;case"=":case"==":r=t==a?!0:!1;break;case"===":r=t===a?!0:!1;break;default:r=!1}return r}function V(){return this.replace(/^\s+|\s+$/g,"")}function w(){var e=Array.isArray(arguments[0])?arguments[0]:arguments;return this.replace(/{(\d+)}/g,function(t,a){return"undefined"!=typeof e[a]?e[a]:t})}function T(e){var t=Array.isArray(arguments[1])?arguments[1]:Array.prototype.slice.call(arguments,1);return e.replace(/{(\d+)}/g,function(e,a){return"undefined"!=typeof t[a]?t[a]:e})}var F=1e3,L=[],k={resetGlobalOptionsOnRouteChange:!0},U=[],q=[];e.$on("$routeChangeStart",function(){k.resetGlobalOptionsOnRouteChange&&(k={displayOnlyLastErrorMsg:!1,preValidateFormElements:!1,isolatedScope:null,scope:null,resetGlobalOptionsOnRouteChange:!0},L=[],q=[])});var C=function(e,t,a,r){this.bFieldRequired=!1,this.validators=[],this.typingLimit=F,this.scope=e,this.elm=t,this.ctrl=r,this.validatorAttrs=a,e&&e.$validationOptions&&(k=e.$validationOptions),e&&(k.isolatedScope||k.scope)&&(this.scope=k.isolatedScope||k.scope,k=m(e.$validationOptions,k)),"undefined"==typeof k.resetGlobalOptionsOnRouteChange&&(k.resetGlobalOptionsOnRouteChange=!0),this.elm&&this.validatorAttrs&&this.ctrl&&this.scope&&(h(this.elm,this.validatorAttrs,this.ctrl,this.scope),this.defineValidation())};return C.prototype.addToValidationSummary=r,C.prototype.arrayFindObject=b,C.prototype.defineValidation=n,C.prototype.getFormElementByName=i,C.prototype.getFormElements=o,C.prototype.getGlobalOptions=l,C.prototype.isFieldRequired=p,C.prototype.initialize=s,C.prototype.mergeObjects=m,C.prototype.removeFromValidationSummary=u,C.prototype.removeFromFormElementObjectList=d,C.prototype.setDisplayOnlyLastErrorMsg=c,C.prototype.setGlobalOptions=f,C.prototype.updateErrorMsg=g,C.prototype.validate=v,String.prototype.trim=V,String.prototype.format=w,String.format=T,C}]); -angular.module("ghiscoding.validation").factory("validationRules",[function(){function e(e){var a="undefined"!=typeof e.altText?e.altText.replace("alt=",""):null,t=e.hasOwnProperty("customRegEx")?e.customRegEx:null,s=e.hasOwnProperty("rule")?e.rule:null,n=e.hasOwnProperty("ruleParams")?e.ruleParams:null,r={};switch(s){case"accepted":r={pattern:/^(yes|on|1|true)$/i,message:"INVALID_ACCEPTED",type:"regex"};break;case"alpha":r={pattern:/^([a-zа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ])+$/i,message:"INVALID_ALPHA",type:"regex"};break;case"alphaSpaces":case"alpha_spaces":r={pattern:/^([a-zа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ\s])+$/i,message:"INVALID_ALPHA_SPACE",type:"regex"};break;case"alphaNum":case"alpha_num":r={pattern:/^([a-zа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9])+$/i,message:"INVALID_ALPHA_NUM",type:"regex"};break;case"alphaNumSpaces":case"alpha_num_spaces":r={pattern:/^([a-zа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9\s])+$/i,message:"INVALID_ALPHA_NUM_SPACE",type:"regex"};break;case"alphaDash":case"alpha_dash":r={pattern:/^([a-zа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9_-])+$/i,message:"INVALID_ALPHA_DASH",type:"regex"};break;case"alphaDashSpaces":case"alpha_dash_spaces":r={pattern:/^([a-zа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9\s_-])+$/i,message:"INVALID_ALPHA_DASH_SPACE",type:"regex"};break;case"between":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between:1,5";r={patternLength:"^(.|[\\r\\n]){"+_[0]+","+_[1]+"}$",messageLength:"INVALID_BETWEEN_CHAR",conditionNum:[">=","<="],messageNum:"INVALID_BETWEEN_NUM",params:[_[0],_[1]],type:"autoDetect"};break;case"betweenLen":case"between_len":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_len:1,5";r={pattern:"^(.|[\\r\\n]){"+_[0]+","+_[1]+"}$",message:"INVALID_BETWEEN_CHAR",params:[_[0],_[1]],type:"regex"};break;case"betweenNum":case"between_num":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_num:1,5";r={condition:[">=","<="],message:"INVALID_BETWEEN_NUM",params:[_[0],_[1]],type:"conditionalNumber"};break;case"boolean":r={pattern:/^(true|false|0|1)$/i,message:"INVALID_BOOLEAN",type:"regex"};break;case"checked":r={pattern:/^true$/i,message:"INVALID_CHECKBOX_SELECTED",type:"regex"};break;case"creditCard":case"credit_card":r={pattern:/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11})$/,message:"INVALID_CREDIT_CARD",type:"regex"};break;case"dateEuroLong":case"date_euro_long":r={pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_EURO_LONG",type:"regex"};break;case"dateEuroLongBetween":case"date_euro_long_between":case"betweenDateEuroLong":case"between_date_euro_long":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_euro_long:01-01-1990,31-12-2015";r={condition:[">=","<="],dateType:"EURO_LONG",params:[_[0],_[1]],pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_EURO_LONG_BETWEEN",type:"conditionalDate"};break;case"dateEuroLongMax":case"date_euro_long_max":case"maxDateEuroLong":case"max_date_euro_long":r={condition:"<=",dateType:"EURO_LONG",params:[n],pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_EURO_LONG_MAX",type:"conditionalDate"};break;case"dateEuroLongMin":case"date_euro_long_min":case"minDateEuroLong":case"min_date_euro_long":r={condition:">=",dateType:"EURO_LONG",params:[n],pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_EURO_LONG_MIN",type:"conditionalDate"};break;case"dateEuroShort":case"date_euro_short":r={pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.]\d\d$/,message:"INVALID_DATE_EURO_SHORT",type:"regex"};break;case"dateEuroShortBetween":case"date_euro_short_between":case"betweenDateEuroShort":case"between_date_euro_short":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_euro_short:01-01-90,31-12-15";r={condition:[">=","<="],dateType:"EURO_SHORT",params:[_[0],_[1]],pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.]\d\d$/,message:"INVALID_DATE_EURO_SHORT_BETWEEN",type:"conditionalDate"};break;case"dateEuroShortMax":case"date_euro_short_max":case"maxDateEuroShort":case"max_date_euro_short":r={condition:"<=",dateType:"EURO_SHORT",params:[n],pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.]\d\d$/,message:"INVALID_DATE_EURO_SHORT_MAX",type:"conditionalDate"};break;case"dateEuroShortMin":case"date_euro_short_min":case"minDateEuroShort":case"min_date_euro_short":r={condition:">=",dateType:"EURO_SHORT",params:[n],pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.]\d\d$/,message:"INVALID_DATE_EURO_SHORT_MIN",type:"conditionalDate"};break;case"dateIso":case"date_iso":r={pattern:/^(19|20)\d\d([-])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$/,message:"INVALID_DATE_ISO",type:"regex"};break;case"dateIsoBetween":case"date_iso_between":case"betweenDateIso":case"between_date_iso":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_iso:1990-01-01,2000-12-31";r={condition:[">=","<="],dateType:"ISO",params:[_[0],_[1]],pattern:/^(19|20)\d\d([-])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$/,message:"INVALID_DATE_ISO_BETWEEN",type:"conditionalDate"};break;case"dateIsoMax":case"date_iso_max":case"maxDateIso":case"max_date_iso":r={condition:"<=",dateType:"ISO",params:[n],pattern:/^(19|20)\d\d([-])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$/,message:"INVALID_DATE_ISO_MAX",type:"conditionalDate"};break;case"dateIsoMin":case"date_iso_min":case"minDateIso":case"min_date_iso":r={condition:">=",dateType:"ISO",params:[n],pattern:/^(19|20)\d\d([-])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$/,message:"INVALID_DATE_ISO_MIN",type:"conditionalDate"};break;case"dateUsLong":case"date_us_long":r={pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_US_LONG",type:"regex"};break;case"dateUsLongBetween":case"date_us_long_between":case"betweenDateUsLong":case"between_date_us_long":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_us_long:01/01/1990,12/31/2015";r={condition:[">=","<="],dateType:"US_LONG",params:[_[0],_[1]],pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_US_LONG_BETWEEN",type:"conditionalDate"};break;case"dateUsLongMax":case"date_us_long_max":case"maxDateUsLong":case"max_date_us_long":r={condition:"<=",dateType:"US_LONG",params:[n],pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_US_LONG_MAX",type:"conditionalDate"};break;case"dateUsLongMin":case"date_us_long_min":case"minDateUsLong":case"min_date_us_long":r={condition:">=",dateType:"US_LONG",params:[n],pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_US_LONG_MIN",type:"conditionalDate"};break;case"dateUsShort":case"date_us_short":r={pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.]\d\d$/,message:"INVALID_DATE_US_SHORT",type:"regex"};break;case"dateUsShortBetween":case"date_us_short_between":case"betweenDateUsShort":case"between_date_us_short":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_us_short:01/01/90,12/31/15";r={condition:[">=","<="],dateType:"US_SHORT",params:[_[0],_[1]],pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.]\d\d$/,message:"INVALID_DATE_US_SHORT_BETWEEN",type:"conditionalDate"};break;case"dateUsShortMax":case"date_us_short_max":case"maxDateUsShort":case"max_date_us_short":r={condition:"<=",dateType:"US_SHORT",params:[n],pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.]\d\d$/,message:"INVALID_DATE_US_SHORT_MAX",type:"conditionalDate"};break;case"dateUsShortMin":case"date_us_short_min":case"minDateUsShort":case"min_date_us_short":r={condition:">=",dateType:"US_SHORT",params:[n],pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.]\d\d$/,message:"INVALID_DATE_US_SHORT_MIN",type:"conditionalDate"};break;case"different":case"differentInput":case"different_input":var e=n.split(",");r={condition:"!=",message:"INVALID_INPUT_DIFFERENT",params:e,type:"matching"};break;case"digits":r={pattern:"^\\d{"+n+"}$",message:"INVALID_DIGITS",params:[n],type:"regex"};break;case"digitsBetween":case"digits_between":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: digits_between:1,5";r={pattern:"^\\d{"+_[0]+","+_[1]+"}$",message:"INVALID_DIGITS_BETWEEN",params:[_[0],_[1]],type:"regex"};break;case"email":r={pattern:/^[-\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9#~!$%^&*_=+\/`\|}{\'?]+(\.[-\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9#~!$%^&*_=+\/`\|}{\'?]+)*@([\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9_][-\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9_]*(\.[-\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9_]+)*([\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ]+)|(\.[\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ]{2,6})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i,message:"INVALID_EMAIL",type:"regex"};break;case"exactLen":case"exact_len":r={pattern:"^(.|[\\r\\n]){"+n+"}$",message:"INVALID_EXACT_LEN",params:[n],type:"regex"};break;case"float":r={pattern:/^\d*\.{1}\d+$/,message:"INVALID_FLOAT",type:"regex"};break;case"floatSigned":case"float_signed":r={pattern:/^[-+]?\d*\.{1}\d+$/,message:"INVALID_FLOAT_SIGNED",type:"regex"};break;case"iban":r={pattern:/^[a-zA-Z]{2}\d{2}\s?([0-9a-zA-Z]{4}\s?){4}[0-9a-zA-Z]{2}$/i,message:"INVALID_IBAN",type:"regex"};break;case"in":case"inList":case"in_list":var c=n.replace(/,/g,"|");r={pattern:"^(\\b("+c+")\\b)$",patternFlag:"i",message:"INVALID_IN_LIST",params:[n],type:"regex"};break;case"int":case"integer":r={pattern:/^\d+$/,message:"INVALID_INTEGER",type:"regex"};break;case"intSigned":case"integerSigned":case"int_signed":case"integer_signed":r={pattern:/^[+-]?\d+$/,message:"INVALID_INTEGER_SIGNED",type:"regex"};break;case"ip":case"ipv4":r={pattern:/^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$/,message:"INVALID_IPV4",type:"regex"};break;case"ipv6":r={pattern:/^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/i,message:"INVALID_IPV6",type:"regex"};break;case"match":case"matchInput":case"match_input":case"same":var e=n.split(",");r={condition:"===",message:"INVALID_INPUT_MATCH",params:e,type:"matching"};break;case"max":r={patternLength:"^(.|[\\r\\n]){0,"+n+"}$",messageLength:"INVALID_MAX_CHAR",conditionNum:"<=",messageNum:"INVALID_MAX_NUM",params:[n],type:"autoDetect"};break;case"maxLen":case"max_len":r={pattern:"^(.|[\\r\\n]){0,"+n+"}$",message:"INVALID_MAX_CHAR",params:[n],type:"regex"};break;case"maxNum":case"max_num":r={condition:"<=",message:"INVALID_MAX_NUM",params:[n],type:"conditionalNumber"};break;case"min":r={patternLength:"^(.|[\\r\\n]){"+n+",}$",messageLength:"INVALID_MIN_CHAR",conditionNum:">=",messageNum:"INVALID_MIN_NUM",params:[n],type:"autoDetect"};break;case"minLen":case"min_len":r={pattern:"^(.|[\\r\\n]){"+n+",}$",message:"INVALID_MIN_CHAR",params:[n],type:"regex"};break;case"minNum":case"min_num":r={condition:">=",message:"INVALID_MIN_NUM",params:[n],type:"conditionalNumber"};break;case"notIn":case"not_in":case"notInList":case"not_in_list":var c=n.replace(/,/g,"|");r={pattern:"^((?!\\b("+c+")\\b).)+$",patternFlag:"i",message:"INVALID_NOT_IN_LIST",params:[n],type:"regex"};break;case"numeric":r={pattern:/^\d*\.?\d+$/,message:"INVALID_NUMERIC",type:"regex"};break;case"numericSigned":case"numeric_signed":r={pattern:/^[-+]?\d*\.?\d+$/,message:"INVALID_NUMERIC_SIGNED",type:"regex"};break;case"pattern":case"regex":r={pattern:t.pattern,message:"INVALID_PATTERN",params:[t.message],type:"regex"};break;case"remote":r={message:"",params:[n],type:"remote"};break;case"required":r={pattern:/\S+/,message:"INVALID_REQUIRED",type:"regex"};break;case"size":r={patternLength:"^(.|[\\r\\n]){"+n+"}$",messageLength:"INVALID_EXACT_LEN",conditionNum:"==",messageNum:"INVALID_EXACT_NUM",params:[n],type:"autoDetect"};break;case"url":r={pattern:/^(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?/i,message:"INVALID_URL",type:"regex"};break;case"time":r={pattern:/^([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/,message:"INVALID_TIME",type:"regex"}}return r.altText=a,r}var a={getElementValidators:e};return a}]); -angular.module("ghiscoding.validation").service("validationService",["$interpolate","$timeout","validationCommon",function(e,o,t){function n(t,n,a){var i=this,m={};if("string"==typeof t&&"string"==typeof n?(m.elmName=t,m.rules=n,m.friendlyName="string"==typeof a?a:""):m=t,"object"!=typeof m||!m.hasOwnProperty("elmName")||!m.hasOwnProperty("rules")||!m.hasOwnProperty("scope")&&"undefined"==typeof i.validationAttrs.scope)throw"Angular-Validation-Service requires at least the following 3 attributes: {elmName, rules, scope}";var r=m.scope?m.scope:i.validationAttrs.scope;if(m.elm=angular.element(document.querySelector('[name="'+m.elmName+'"]')),"object"!=typeof m.elm||0===m.elm.length)return i;if(new RegExp("{{(.*?)}}").test(m.elmName)&&(m.elmName=e(m.elmName)(r)),m.name=m.elmName,i.validationAttrs.isolatedScope){var l=r.$validationOptions||null;r=i.validationAttrs.isolatedScope,l&&(r.$validationOptions=l)}m.elm.bind("blur",b=function(e){var o=i.commonObj.getFormElementByName(m.elmName);o&&!o.isValidationCancelled&&(i.commonObj.initialize(r,m.elm,m,m.ctrl),d(i,e.target.value,10))}),m=i.commonObj.mergeObjects(i.validationAttrs,m),y(i,r,m),m.elm.on("$destroy",function(){var e=i.commonObj.getFormElementByName(i.commonObj.ctrl.$name);e&&(s(i,e),i.commonObj.removeFromValidationSummary(m.name))});var c=r.$watch(function(){return m.ctrl=angular.element(m.elm).controller("ngModel"),f(i,m.elmName)?{badInput:!0}:m.ctrl.$modelValue},function(e,t){if(e&&e.badInput){var n=i.commonObj.getFormElementByName(m.elmName);return v(i,n),u(i,m.name)}return void 0!==e||void 0===t||isNaN(t)?(m.ctrl=angular.element(m.elm).controller("ngModel"),m.value=e,i.commonObj.initialize(r,m.elm,m,m.ctrl),void d(i,e)):(o.cancel(i.timer),void i.commonObj.ctrl.$setValidity("validation",i.commonObj.validate("",!0)))},!0);return O.push({elmName:m.elmName,watcherHandler:c}),i}function a(e){var o=this,t="",n=!0;if("undefined"==typeof e||"undefined"==typeof e.$validationSummary)throw"checkFormValidity() requires a valid Angular Form or $scope/vm object passed as argument to work properly, for example:: fn($scope) OR fn($scope.form1) OR fn(vm) OR fn(vm.form1)";for(var a=0,i=e.$validationSummary.length;i>a;a++)if(n=!1,t=e.$validationSummary[a].field){var m=o.commonObj.getFormElementByName(t);m&&m.elm&&m.elm.length>0&&("function"==typeof m.ctrl.$setTouched&&m.ctrl.$setTouched(),o.commonObj.updateErrorMsg(e.$validationSummary[a].message,{isSubmitted:!0,isValid:m.isValid,obj:m}))}return n}function i(e){var o=this;if("undefined"==typeof e||"undefined"==typeof e.$validationSummary)throw"clearInvalidValidatorsInSummary() requires a valid Angular Form or $scope/vm object passed as argument to work properly, for example:: fn($scope) OR fn($scope.form1) OR fn(vm) OR fn(vm.form1)";for(var t=[],n=0,a=e.$validationSummary.length;a>n;n++)t.push(e.$validationSummary[n].field);for(n=0,a=t.length;a>n;n++)t[n]&&(o.commonObj.removeFromFormElementObjectList(t[n]),o.commonObj.removeFromValidationSummary(t[n],e.$validationSummary))}function m(e,o){var t,n=this;if("undefined"==typeof e||"undefined"==typeof e.$validationSummary)throw"removeValidator() only works with Validation that were defined by the Service (not by the Directive) and requires a valid Angular Form or $scope/vm object passed as argument to work properly, for example:: fn($scope) OR fn($scope.form1) OR fn(vm) OR fn(vm.form1)";if(o instanceof Array)for(var a=0,i=o.length;i>a;a++)t=n.commonObj.getFormElementByName(o[a]),t.elm.removeAttr("validation"),p(n,t,e.$validationSummary);else o instanceof Object&&o.formElmObj?(t=o.formElmObj,t.elm.removeAttr("validation"),p(o.self,t,e.$validationSummary)):(t=n.commonObj.getFormElementByName(o),t.elm.removeAttr("validation"),p(n,t,e.$validationSummary));return n}function r(e,o){var t,n=this,o=o||{},a="undefined"!=typeof o.removeAllValidators?o.removeAllValidators:!1,i="undefined"!=typeof o.emptyAllInputValues?o.emptyAllInputValues:!1;if("undefined"==typeof e||"undefined"==typeof e.$name)throw"resetForm() requires a valid Angular Form object passed as argument to work properly (ex.: $scope.form1).";var r=n.commonObj.getFormElements(e.$name);if(r instanceof Array)for(var l=0,c=r.length;c>l;l++)t=r[l],i&&t.elm.val(null),a?m(e,{self:n,formElmObj:t}):("function"==typeof t.ctrl.$setUntouched&&t.ctrl.$setUntouched(),t.ctrl.$setPristine(),n.commonObj.updateErrorMsg("",{isValid:!1,obj:t}))}function l(e){var o=this,t="boolean"==typeof e?e:!0;o.commonObj.setDisplayOnlyLastErrorMsg(t)}function c(e){var o=this;return o.validationAttrs=e,o.commonObj.setGlobalOptions(e),o}function d(e,t,n){var a="undefined"!=typeof n?n:e.commonObj.typingLimit,i=e.commonObj.getFormElementByName(e.commonObj.ctrl.$name);return t&&t.badInput?u(e,attrs.name):(e.commonObj.validate(t,!1),e.commonObj.isFieldRequired()||""!==t&&null!==t&&"undefined"!=typeof t?(i.isValidationCancelled=!1,(e.commonObj.isFieldRequired()||t)&&e.commonObj.ctrl.$setValidity("validation",!1),""!==t&&"undefined"!=typeof t||"NUMBER"!==e.commonObj.elm.prop("type").toUpperCase()?"SELECT"===e.commonObj.elm.prop("tagName").toUpperCase()?(e.commonObj.ctrl.$setValidity("validation",e.commonObj.validate(t,!0)),t):("undefined"!=typeof t&&(e.commonObj.updateErrorMsg(""),o.cancel(e.timer),e.timer=o(function(){e.commonObj.scope.$evalAsync(e.commonObj.ctrl.$setValidity("validation",e.commonObj.validate(t,!0)))},a)),t):(o.cancel(e.timer),e.commonObj.ctrl.$setValidity("validation",e.commonObj.validate(t,!0)),t)):(s(e,i),t))}function s(e,t){var n=t&&t.ctrl?t.ctrl:e.commonObj.ctrl;t&&(t.isValidationCancelled=!0),o.cancel(self.timer),n.$setValidity("validation",!0),e.commonObj.updateErrorMsg("",{isValid:!0,obj:t}),v(e,t)}function u(e,t){o.cancel(e.timer);var n=e.commonObj.getFormElementByName(t);e.commonObj.updateErrorMsg("INVALID_KEY_CHAR",{isValid:!1,translate:!0,obj:n}),e.commonObj.addToValidationSummary(n,"INVALID_KEY_CHAR",!0)}function f(e,o){var t=e.commonObj.getFormElementByName(o);return!!t&&!!t.elm.prop("validity")&&t.elm.prop("validity").badInput===!0}function p(e,o,t){var n=e.commonObj.scope?e.commonObj.scope:o.scope?o.scope:null;if("undefined"==typeof n)throw"removeValidator() requires a valid $scope object passed but unfortunately could not find it.";var a=e.commonObj.arrayFindObject(O,"elmName",o.fieldName);a&&a.watcherHandler(),o.isValidationCancelled=!0,o.isValid=!0,o.attrs.validation="",s(e,o),"function"==typeof o.ctrl.$setUntouched&&o.ctrl.$setUntouched(),e.commonObj.scope=n,o.ctrl.$setPristine(),e.commonObj.removeFromValidationSummary(o.fieldName,t)}function v(e,o){if(o.isValidationCancelled=!0,"function"==typeof b){var t=o&&o.elm?o.elm:e.commonObj.elm;t.unbind("blur",b)}}function y(e,t,n){t.$watch(function(){return"undefined"==typeof n.elm.attr("ng-disabled")?null:t.$eval(n.elm.attr("ng-disabled"))},function(a){if("undefined"==typeof a||null===a)return null;n.ctrl=angular.element(n.elm).controller("ngModel"),e.commonObj.initialize(t,n.elm,n,n.ctrl);var i=e.commonObj.getFormElementByName(n.name);o(function(){if(a)n.ctrl.$setValidity("validation",!0),e.commonObj.updateErrorMsg("",{isValid:!0,obj:i}),e.commonObj.removeFromValidationSummary(n.name);else{var o=n.ctrl.$viewValue||"";e.commonObj.initialize(t,n.elm,n,n.ctrl),n.ctrl.$setValidity("validation",e.commonObj.validate(o,!1)),i&&(i.isValidationCancelled=!1),n.elm.bind("blur",b=function(o){i&&!i.isValidationCancelled&&d(e,o.target.value,10)})}},0,!1),a&&("function"==typeof n.ctrl.$setUntouched&&n.ctrl.$setUntouched(),n.ctrl.$setValidity("validation",!0),e.commonObj.removeFromValidationSummary(n.name))})}var b,O=[],j=function(e){this.isValidationCancelled=!1,this.timer=null,this.validationAttrs={},this.commonObj=new t,e&&this.setGlobalOptions(e)};return j.prototype.addValidator=n,j.prototype.checkFormValidity=a,j.prototype.removeValidator=m,j.prototype.resetForm=r,j.prototype.setDisplayOnlyLastErrorMsg=l,j.prototype.setGlobalOptions=c,j.prototype.clearInvalidValidatorsInSummary=i,j}]); \ No newline at end of file +angular.module("ghiscoding.validation",["pascalprecht.translate"]).directive("validation",["$q","$timeout","validationCommon",function(a,e,i){return{restrict:"A",require:"ngModel",link:function(t,n,r,l){function o(i,r){var o=a.defer(),d=!1,m="undefined"!=typeof r?r:b.typingLimit,s=b.getFormElementByName(l.$name);if(Array.isArray(i)){if(E=[],$="",m=0,i.length>0)return"function"==typeof s.ctrl.$setTouched&&s.ctrl.$setTouched(),u(i,typeof i);m=0}return i&&i.badInput?v():(b.validate(i,!1),b.isFieldRequired()||""!==i&&null!==i&&"undefined"!=typeof i?(s&&(s.isValidationCancelled=!1),(i||b.isFieldRequired())&&l.$setValidity("validation",!1),"SELECT"===n.prop("tagName").toUpperCase()?(d=b.validate(i,!0),l.$setValidity("validation",d),o.resolve({isFieldValid:d,formElmObj:s,value:i}),o.promise):("undefined"!=typeof i&&(0===r?(d=b.validate(i,!0),t.$evalAsync(l.$setValidity("validation",d)),o.resolve({isFieldValid:d,formElmObj:s,value:i})):(b.updateErrorMsg(""),e.cancel(V),V=e(function(){d=b.validate(i,!0),t.$evalAsync(l.$setValidity("validation",d)),o.resolve({isFieldValid:d,formElmObj:s,value:i})},m))),o.promise)):(f(),o.resolve({isFieldValid:!0,formElmObj:s,value:i}),o.promise))}function d(a,e,i){var t=o(a,0);t&&"function"==typeof t.then&&(E.push(t),parseInt(e)===i-1&&E.forEach(function(a){a.then(function(a){switch(O){case"all":if(a.isFieldValid===!1){var e=b.getGlobalOptions();a.formElmObj.translatePromise.then(function(i){$.length>0&&e.displayOnlyLastErrorMsg?$="["+a.value+"] :: "+(a.formElmObj.validator&&a.formElmObj.validator.params?String.format(i,a.formElmObj.validator.params):i):$+=" ["+a.value+"] :: "+(a.formElmObj.validator&&a.formElmObj.validator.params?String.format(i,a.formElmObj.validator.params):i),b.updateErrorMsg($,{isValid:!1}),b.addToValidationSummary(a.formElmObj,$)})}break;case"one":default:a.isFieldValid===!0&&(l.$setValidity("validation",!0),f())}})}))}function m(a){var e=b.getFormElementByName(l.$name),i="undefined"!=typeof l.$modelValue?l.$modelValue:a.target.value;e.isValidationCancelled?l.$setValidity("validation",!0):o(i,10)}function u(a,e){var i=a.length;if("string"===e)for(var t in a)d(a[t],t,i);else if("object"===e)for(var t in a)if(a.hasOwnProperty(t)){var n=a[t];for(var r in n)if(n.hasOwnProperty(r)){if(j&&r!==j)continue;d(n[r],t,i)}}}function s(){f(),b.removeFromValidationSummary(h);var a=b.arrayFindObject(g,"elmName",l.$name);a&&a.watcherHandler()}function f(){var a=b.getFormElementByName(l.$name);a&&(a.isValidationCancelled=!0),e.cancel(V),b.updateErrorMsg(""),l.$setValidity("validation",!0),p()}function v(){e.cancel(V);var a=b.getFormElementByName(l.$name);b.updateErrorMsg("INVALID_KEY_CHAR",{isValid:!1,translate:!0}),b.addToValidationSummary(a,"INVALID_KEY_CHAR",!0)}function c(){return!!n.prop("validity")&&n.prop("validity").badInput===!0}function y(){var a=l.$modelValue||"";Array.isArray(a)||l.$setValidity("validation",b.validate(a,!1));var e=b.getFormElementByName(l.$name);e&&(e.isValidationCancelled=!1),p(),n.bind("blur",m)}function p(){"function"==typeof m&&n.unbind("blur",m)}var V,b=new i(t,n,r,l),$="",E=[],g=[],h=r.name,O=r.hasOwnProperty("validArrayRequireHowMany")?r.validArrayRequireHowMany:"one",j=r.hasOwnProperty("validationArrayObjprop")?r.validationArrayObjprop:null,F=t.$watch(function(){return c()?{badInput:!0}:l.$modelValue},function(a){return a&&a.badInput?(p(),v()):void o(a)},!0);g.push({elmName:h,watcherHandler:F}),r.$observe("disabled",function(a){a?(f(),b.removeFromValidationSummary(h)):y()}),n.on("$destroy",function(){s()}),t.$watch(function(){return n.attr("validation")},function(a){"undefined"==typeof a||""===a?s():(b.defineValidation(),y())}),n.bind("blur",m)}}}]); +angular.module("ghiscoding.validation").factory("validationCommon",["$rootScope","$timeout","$translate","validationRules",function(e,t,a,r){function n(e,t,r){if("undefined"!=typeof e&&null!=e){var n=e.ctrl&&e.ctrl.$name?e.ctrl.$name:e.attrs&&e.attrs.name?e.attrs.name:e.elm.attr("name"),i=A(n,e),o=S(H,"field",n);if(o>=0&&""===t)H.splice(o,1);else if(""!==t){r&&(t=a.instant(t));var s=e.attrs&&e.friendlyName?a.instant(e.friendlyName):"",l={field:n,friendlyName:s,message:t,formName:i?i.$name:null};o>=0?H[o]=l:H.push(l)}if(e.scope.$validationSummary=H,i&&(i.$validationSummary=O(H,"formName",i.$name)),P&&P.controllerAs&&(P.controllerAs.$validationSummary=H,i)){var m=i.$name.indexOf(".")>=0?i.$name.split(".")[1]:i.$name,u=P.controllerAs[m]?P.controllerAs[m]:e.elm.controller()[m];u.$validationSummary=O(H,"formName",i.$name)}return H}}function i(){var e=this,t={};e.validators=[],e.typingLimit=D,e.validatorAttrs.hasOwnProperty("debounce")?e.typingLimit=parseInt(e.validatorAttrs.debounce,10):e.validatorAttrs.hasOwnProperty("typingLimit")?e.typingLimit=parseInt(e.validatorAttrs.typingLimit,10):P&&P.hasOwnProperty("debounce")&&(e.typingLimit=parseInt(P.debounce,10));var a=e.validatorAttrs.rules||e.validatorAttrs.validation;if(a.indexOf("pattern=/")>=0){var n=a.match(/pattern=(\/.*\/[igm]*)(:alt=(.*))?/);if(!n||n.length<3)throw'Regex validator within the validation needs to be define with an opening "/" and a closing "/", please review your validator.';var i=n[1],o=n[2]?n[2].replace(/\|(.*)/,""):"",s=i.match(new RegExp("^/(.*?)/([gimy]*)$")),l=new RegExp(s[1],s[2]);t={altMsg:o,message:o.replace(/:alt=/,""),pattern:l},a=a.replace("pattern="+i,"pattern")}else if(a.indexOf("regex:")>=0){var n=a.match("regex:(.*?):regex");if(n.length<2)throw'Regex validator within the validation needs to be define with an opening "regex:" and a closing ":regex", please review your validator.';var m=n[1].split(":=");t={message:m[0],pattern:m[1]},a=a.replace(n[0],"regex:")}var u=a.split("|");if(u){e.bFieldRequired=a.indexOf("required")>=0?!0:!1;for(var p=0,d=u.length;d>p;p++){var c=u[p].split(":"),f=u[p].indexOf("alt=")>=0?!0:!1;e.validators[p]=r.getElementValidators({altText:f===!0?2===c.length?c[1]:c[2]:"",customRegEx:t,rule:c[0],ruleParams:f&&2===c.length?null:c[1]})}}return e}function o(e){return $(M,"fieldName",e)}function s(e){return e?O(M,"formName",e):M}function l(){return P}function m(e,t,a,r){this.scope=e,this.elm=t,this.ctrl=r,this.validatorAttrs=a,y(t,a,r,e),this.defineValidation()}function u(){var e=this;return e.bFieldRequired}function p(e,t){var a={};for(var r in e)a[r]=e[r];for(var r in t)a[r]=t[r];return a}function d(e){var t=S(M,"fieldName",e);t>=0&&M.splice(t,1)}function c(e,t){var a=this,r=A(e,a),n=t||H,i=S(n,"field",e);if(i>=0&&n.splice(i,1),i=S(H,"field",e),i>=0&&H.splice(i,1),a.scope.$validationSummary=H,r&&(r.$validationSummary=O(H,"formName",r.$name)),P&&P.controllerAs&&(P.controllerAs.$validationSummary=H,r)){var o=r.$name.indexOf(".")>=0?r.$name.split(".")[1]:r.$name;P.controllerAs[o]&&(P.controllerAs[o].$validationSummary=O(H,"formName",r.$name))}return H}function f(e){P.displayOnlyLastErrorMsg=e}function g(e){var t=this;return P=p(P,e),t}function v(e,t){var r=this;t&&t.obj&&(r=t.obj,r.validatorAttrs=t.obj.attrs);var n=t&&t.elm?t.elm:r.elm,i=n&&n.attr("name")?n.attr("name"):null;if("undefined"==typeof i||null===i){var o=n?n.attr("ng-model"):"unknown";throw'Angular-Validation Service requires you to have a (name="") attribute on the element to validate... Your element is: ng-model="'+o+'"'}var s=t&&t.translate?a.instant(e):e,l=i.replace(/[|&;$%@"<>()+,\[\]\{\}]/g,""),m=null;if(r.validatorAttrs&&r.validatorAttrs.hasOwnProperty("validationErrorTo")){var u=r.validatorAttrs.validationErrorTo.charAt(0),p="."===u||"#"===u?r.validatorAttrs.validationErrorTo:"#"+r.validatorAttrs.validationErrorTo;m=angular.element(document.querySelector(p))}m&&0!==m.length||(m=angular.element(document.querySelector(".validation-"+l)));var d=t&&t.isSubmitted?t.isSubmitted:!1;t&&!t.isValid&&(d||r.ctrl.$dirty||r.ctrl.$touched)?m.length>0?m.html(s):n.after(''+s+""):m.html("")}function h(e,t){var r,i=this,s=!0,l=!0,m={message:""};"undefined"==typeof e&&(e="");for(var u=i.ctrl&&i.ctrl.$name?i.ctrl.$name:i.attrs&&i.attrs.name?i.attrs.name:i.elm.attr("name"),p=o(u),d=i.validatorAttrs.rules||i.validatorAttrs.validation,c=0,f=i.validators.length;f>c;c++){r=i.validators[c],"autoDetect"===r.type&&(r=G(r));var g=i.attrs?i.attrs.ngDisabled:i.validatorAttrs.ngDisabled;switch(r.type){case"conditionalDate":s=k(e,r,d);break;case"conditionalNumber":s=L(e,r);break;case"javascript":s=q(e,r,i,p,t,m);break;case"matching":s=C(e,r,i,m);break;case"remote":s=U(e,r,i,p,t,m);break;default:s=j(e,r,d,i)}(!i.bFieldRequired&&!e||i.elm.prop("disabled")||i.scope.$eval(g))&&(s=!0),s||(l=!1,function(e,r,n){var o=n.message;n.altText&&n.altText.length>0&&(o=n.altText.replace("alt=",""));var s=a(o);e.translatePromise=s,e.validator=n,s.then(function(a){m.message.length>0&&P.displayOnlyLastErrorMsg?m.message=" "+(n&&n.params?String.format(a,n.params):a):m.message+=" "+(n&&n.params?String.format(a,n.params):a),b(i,e,m.message,l,t)})["catch"](function(){n.altText&&n.altText.length>0&&(m.message.length>0&&P.displayOnlyLastErrorMsg?m.message=" "+o:m.message+=" "+o,b(i,e,m.message,l,t))})}(p,s,r))}return s&&(n(i,""),i.updateErrorMsg("",{isValid:s})),p&&(p.isValid=l,l&&(p.message="")),l}function y(e,t,r,n){var i=t.name?t.name:e.attr("name"),o=A(i,{scope:n}),s=t&&t.friendlyName?a.instant(t.friendlyName):"",l={fieldName:i,friendlyName:s,elm:e,attrs:t,ctrl:r,scope:n,isValid:!1,message:"",formName:o?o.$name:null},m=S(M,"fieldName",e.attr("name"));return m>=0?M[m]=l:M.push(l),M}function b(e,t,a,r,i){a=a.trim(),t&&t.isValidationCancelled===!0&&(a=""),n(t,a),(e.validatorAttrs.preValidateFormElements||P.preValidateFormElements)&&(t&&"function"==typeof e.ctrl.$setTouched&&t.ctrl.$setTouched(),e.ctrl.$dirty===!1&&v(a,{isSubmitted:!0,isValid:r,obj:t})),i&&t&&!t.isValid?e.updateErrorMsg(a,{isValid:r,obj:t}):t&&t.isValid&&n(t,"")}function $(e,t,a){if(e)for(var r=0;rr;r++)t[a[r]]&&(t=t[a[r]]);return t}function A(e,t){if(P&&P.formName){var a=document.querySelector('[name="'+P.formName+'"]');if(a)return a.$name=P.formName,a}for(var r=document.getElementsByName(e),a=null,n=0;n=0?x(i.name,t.scope):t.scope[i.name]))return"undefined"==typeof a.$name&&(a.$name=i.name),a}if(i&&i.name){var o={$name:i.name,specialNote:"Created by Angular-Validation for Isolated Scope usage"};if(P&&P.controllerAs&&i.name.indexOf(".")>=0){var s=i.name.split(".");return t.scope[s[0]][s[1]]=o}return t.scope[i.name]=o}return null}function V(e){return!isNaN(parseFloat(e))&&isFinite(e)}function w(e,t){var a="",r="-",n=[],i=[],o="",s="",l="";switch(t.toUpperCase()){case"EURO_LONG":case"EURO-LONG":a=e.substring(0,10),r=e.substring(2,3),n=N(a,r),l=n[0],s=n[1],o=n[2],i=e.length>8?e.substring(9).split(":"):null;break;case"UK":case"EURO":case"EURO_SHORT":case"EURO-SHORT":case"EUROPE":a=e.substring(0,8),r=e.substring(2,3),n=N(a,r),l=n[0],s=n[1],o=parseInt(n[2])<50?"20"+n[2]:"19"+n[2],i=e.length>8?e.substring(9).split(":"):null;break;case"US_LONG":case"US-LONG":a=e.substring(0,10),r=e.substring(2,3),n=N(a,r),s=n[0],l=n[1],o=n[2],i=e.length>8?e.substring(9).split(":"):null;break;case"US":case"US_SHORT":case"US-SHORT":a=e.substring(0,8),r=e.substring(2,3),n=N(a,r),s=n[0],l=n[1],o=parseInt(n[2])<50?"20"+n[2]:"19"+n[2],i=e.length>8?e.substring(9).split(":"):null;break;case"ISO":default:a=e.substring(0,10),r=e.substring(4,5),n=N(a,r),o=n[0],s=n[1],l=n[2],i=e.length>10?e.substring(11).split(":"):null}var m=i&&3===i.length?i[0]:0,u=i&&3===i.length?i[1]:0,p=i&&3===i.length?i[2]:0;return new Date(o,s-1,l,m,u,p)}function N(e,t){var a=[];switch(t){case"/":a=e.split("/");break;case".":a=e.split(".");break;case"-":default:a=e.split("-")}return a}function E(e,t,a){var r=!1;switch(e){case"<":r=a>t?!0:!1;break;case"<=":r=a>=t?!0:!1;break;case">":r=t>a?!0:!1;break;case">=":r=t>=a?!0:!1;break;case"!=":case"<>":r=t!=a?!0:!1;break;case"!==":r=t!==a?!0:!1;break;case"=":case"==":r=t==a?!0:!1;break;case"===":r=t===a?!0:!1;break;default:r=!1}return r}function R(){return this.replace(/^\s+|\s+$/g,"")}function T(){var e=Array.isArray(arguments[0])?arguments[0]:arguments;return this.replace(/{(\d+)}/g,function(t,a){return"undefined"!=typeof e[a]?e[a]:t})}function F(e){var t=Array.isArray(arguments[1])?arguments[1]:Array.prototype.slice.call(arguments,1);return e.replace(/{(\d+)}/g,function(e,a){return"undefined"!=typeof t[a]?t[a]:e})}function k(e,t,a){var r=!0,n=r=!1;if(e instanceof Date?n=!0:(regex=new RegExp(t.pattern),n=(!t.pattern||"/\\S+/"===t.pattern.toString()||a&&"required"===t.pattern)&&null===e?!1:regex.test(e)),n){var i=t.dateType,o=e instanceof Date?e:w(e,i).getTime();if(2==t.params.length){var s=w(t.params[0],i).getTime(),l=w(t.params[1],i).getTime(),m=E(t.condition[0],o,s),u=E(t.condition[1],o,l);r=m&&u?!0:!1}else{var p=w(t.params[0],i).getTime();r=E(t.condition,o,p)}}return r}function L(e,t){var a=!0;if(2==t.params.length){var r=E(t.condition[0],parseFloat(e),parseFloat(t.params[0])),n=E(t.condition[1],parseFloat(e),parseFloat(t.params[1]));a=r&&n?!0:!1}else a=E(t.condition,parseFloat(e),parseFloat(t.params[0]));return a}function q(e,a,r,n,i,o){var s=!0,l="Custom Javascript Validation requires an error message defined as 'alt=' in your validator or defined in your custom javascript function as { isValid: bool, message: 'your error' }",m="Custom Javascript Validation requires a declared function (in your Controller), please review your code.";if(e){var u=null,p=a.params[0];if(-1===p.indexOf("."))u=r.scope[p];else{var d=p.split(".");u=r.scope;for(var c=0,f=d.length;f>c;c++)u=u[d[c]]}var g="function"==typeof u?u():null;if("boolean"==typeof g)s=g?!0:!1;else{if("object"!=typeof g)throw m;s=g.isValid?!0:!1}if(s===!1?(n.isValid=!1,t(function(){var e=o.message+" ";if(g.message&&(e+=g.message)," "===e)throw l;b(r,n,e,!1,i)})):s===!0&&(n.isValid=!0,b(r,n,"",!0,i)),"undefined"==typeof g)throw m}return s}function C(e,t,r,n){var i=!0,s=t.params[0],l=r.scope.$eval(s),m=angular.element(document.querySelector('[name="'+s+'"]')),u=t,p=r.ctrl,d=o(r.ctrl.$name);return i=E(t.condition,e,l)&&!!e,m&&m.attr("friendly-name")?t.params[1]=m.attr("friendly-name"):t.params.length>1&&(t.params[1]=t.params[1]),r.scope.$watch(s,function(e,t){var i=E(u.condition,p.$viewValue,e);if(e!==t){if(i)b(r,d,"",!0,!0);else{d.isValid=!1;var o=u.message;u.altText&&u.altText.length>0&&(o=u.altText.replace("alt=","")),a(o).then(function(e){n.message=" "+(u&&u.params?String.format(e,u.params):e),b(r,d,n.message,i,!0)})}p.$setValidity("validation",i)}},!0),i}function U(e,t,a,r,n,i){var o=!0,s="Remote Javascript Validation requires an error message defined as 'alt=' in your validator or defined in your custom remote function as { isValid: bool, message: 'your error' }",l="Remote Validation requires a declared function (in your Controller) which also needs to return a Promise, please review your code.";if(e&&n){a.ctrl.$processing=!0;var m=null,u=t.params[0];if(-1===u.indexOf("."))m=a.scope[u];else{var p=u.split(".");m=a.scope;for(var d=0,c=p.length;c>d;d++)m=m[p[d]]}var f="function"==typeof m?m():null;if(I.length>1)for(;I.length>0;){var g=I.pop();"function"==typeof g.abort&&g.abort()}if(I.push(f),!f||"function"!=typeof f.then)throw l;a.ctrl.$setValidity("remote",!1),function(e){f.then(function(t){t=t.data||t,I.pop(),a.ctrl.$processing=!1;var m=i.message+" ";if("boolean"==typeof t)o=t?!0:!1;else{if("object"!=typeof t)throw l;o=t.isValid?!0:!1}if(o===!1){if(r.isValid=!1,m+=t.message||e," "===m)throw s;b(a,r,m,!1,n)}else o===!0&&(r.isValid=!0,a.ctrl.$setValidity("remote",!0),b(a,r,"",!0,n))})}(t.altText)}return o}function j(e,t,a,r){var n=!0,i=r.attrs?r.attrs.ngDisabled:r.validatorAttrs.ngDisabled;return r.elm.prop("disabled")||r.scope.$eval(i)?n=!0:"string"==typeof e&&""===e&&r.elm.prop("type")&&"NUMBER"===r.elm.prop("type").toUpperCase()?n=!1:(regex=new RegExp(t.pattern,t.patternFlag),n=(!t.pattern||"/\\S+/"===t.pattern.toString()||a&&"required"===t.pattern)&&null===e?!1:regex.test(e)),n}function G(e){return V(strValue)?{condition:e.conditionNum,message:e.messageNum,params:e.params,type:"conditionalNumber"}:{pattern:e.patternLength,message:e.messageLength,params:e.params,type:"regex"}}var D=1e3,M=[],P={resetGlobalOptionsOnRouteChange:!0},I=[],H=[];e.$on("$routeChangeStart",function(){P.resetGlobalOptionsOnRouteChange&&(P={displayOnlyLastErrorMsg:!1,preValidateFormElements:!1,isolatedScope:null,scope:null,resetGlobalOptionsOnRouteChange:!0},M=[],H=[])});var _=function(e,t,a,r){this.bFieldRequired=!1,this.validators=[],this.typingLimit=D,this.scope=e,this.elm=t,this.ctrl=r,this.validatorAttrs=a,e&&e.$validationOptions&&(P=e.$validationOptions),e&&(P.isolatedScope||P.scope)&&(this.scope=P.isolatedScope||P.scope,P=p(e.$validationOptions,P)),"undefined"==typeof P.resetGlobalOptionsOnRouteChange&&(P.resetGlobalOptionsOnRouteChange=!0),this.elm&&this.validatorAttrs&&this.ctrl&&this.scope&&(y(this.elm,this.validatorAttrs,this.ctrl,this.scope),this.defineValidation())};return _.prototype.addToValidationSummary=n,_.prototype.arrayFindObject=$,_.prototype.defineValidation=i,_.prototype.getFormElementByName=o,_.prototype.getFormElements=s,_.prototype.getGlobalOptions=l,_.prototype.isFieldRequired=u,_.prototype.initialize=m,_.prototype.mergeObjects=p,_.prototype.removeFromValidationSummary=c,_.prototype.removeFromFormElementObjectList=d,_.prototype.setDisplayOnlyLastErrorMsg=f,_.prototype.setGlobalOptions=g,_.prototype.updateErrorMsg=v,_.prototype.validate=h,String.prototype.trim=R,String.prototype.format=T,String.format=F,_}]); +angular.module("ghiscoding.validation").factory("validationRules",[function(){function e(e){var a="undefined"!=typeof e.altText?e.altText.replace("alt=",""):null,t=e.hasOwnProperty("customRegEx")?e.customRegEx:null,s=e.hasOwnProperty("rule")?e.rule:null,n=e.hasOwnProperty("ruleParams")?e.ruleParams:null,r={};switch(s){case"accepted":r={pattern:/^(yes|on|1|true)$/i,message:"INVALID_ACCEPTED",type:"regex"};break;case"alpha":r={pattern:/^([a-zа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ])+$/i,message:"INVALID_ALPHA",type:"regex"};break;case"alphaSpaces":case"alpha_spaces":r={pattern:/^([a-zа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ\s])+$/i,message:"INVALID_ALPHA_SPACE",type:"regex"};break;case"alphaNum":case"alpha_num":r={pattern:/^([a-zа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9])+$/i,message:"INVALID_ALPHA_NUM",type:"regex"};break;case"alphaNumSpaces":case"alpha_num_spaces":r={pattern:/^([a-zа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9\s])+$/i,message:"INVALID_ALPHA_NUM_SPACE",type:"regex"};break;case"alphaDash":case"alpha_dash":r={pattern:/^([a-zа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9_-])+$/i,message:"INVALID_ALPHA_DASH",type:"regex"};break;case"alphaDashSpaces":case"alpha_dash_spaces":r={pattern:/^([a-zа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9\s_-])+$/i,message:"INVALID_ALPHA_DASH_SPACE",type:"regex"};break;case"between":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between:1,5";r={patternLength:"^(.|[\\r\\n]){"+_[0]+","+_[1]+"}$",messageLength:"INVALID_BETWEEN_CHAR",conditionNum:[">=","<="],messageNum:"INVALID_BETWEEN_NUM",params:[_[0],_[1]],type:"autoDetect"};break;case"betweenLen":case"between_len":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_len:1,5";r={pattern:"^(.|[\\r\\n]){"+_[0]+","+_[1]+"}$",message:"INVALID_BETWEEN_CHAR",params:[_[0],_[1]],type:"regex"};break;case"betweenNum":case"between_num":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_num:1,5";r={condition:[">=","<="],message:"INVALID_BETWEEN_NUM",params:[_[0],_[1]],type:"conditionalNumber"};break;case"boolean":r={pattern:/^(true|false|0|1)$/i,message:"INVALID_BOOLEAN",type:"regex"};break;case"checked":r={pattern:/^true$/i,message:"INVALID_CHECKBOX_SELECTED",type:"regex"};break;case"creditCard":case"credit_card":r={pattern:/^(?:4[0-9]{12}(?:[0-9]{3})?|5[1-5][0-9]{14}|3[47][0-9]{13}|3(?:0[0-5]|[68][0-9])[0-9]{11}|6(?:011|5[0-9]{2})[0-9]{12}|(?:2131|1800|35\d{3})\d{11})$/,message:"INVALID_CREDIT_CARD",type:"regex"};break;case"custom":case"javascript":r={message:"",params:[n],type:"javascript"};break;case"dateEuroLong":case"date_euro_long":r={pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_EURO_LONG",type:"regex"};break;case"dateEuroLongBetween":case"date_euro_long_between":case"betweenDateEuroLong":case"between_date_euro_long":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_euro_long:01-01-1990,31-12-2015";r={condition:[">=","<="],dateType:"EURO_LONG",params:[_[0],_[1]],pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_EURO_LONG_BETWEEN",type:"conditionalDate"};break;case"dateEuroLongMax":case"date_euro_long_max":case"maxDateEuroLong":case"max_date_euro_long":r={condition:"<=",dateType:"EURO_LONG",params:[n],pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_EURO_LONG_MAX",type:"conditionalDate"};break;case"dateEuroLongMin":case"date_euro_long_min":case"minDateEuroLong":case"min_date_euro_long":r={condition:">=",dateType:"EURO_LONG",params:[n],pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_EURO_LONG_MIN",type:"conditionalDate"};break;case"dateEuroShort":case"date_euro_short":r={pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.]\d\d$/,message:"INVALID_DATE_EURO_SHORT",type:"regex"};break;case"dateEuroShortBetween":case"date_euro_short_between":case"betweenDateEuroShort":case"between_date_euro_short":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_euro_short:01-01-90,31-12-15";r={condition:[">=","<="],dateType:"EURO_SHORT",params:[_[0],_[1]],pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.]\d\d$/,message:"INVALID_DATE_EURO_SHORT_BETWEEN",type:"conditionalDate"};break;case"dateEuroShortMax":case"date_euro_short_max":case"maxDateEuroShort":case"max_date_euro_short":r={condition:"<=",dateType:"EURO_SHORT",params:[n],pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.]\d\d$/,message:"INVALID_DATE_EURO_SHORT_MAX",type:"conditionalDate"};break;case"dateEuroShortMin":case"date_euro_short_min":case"minDateEuroShort":case"min_date_euro_short":r={condition:">=",dateType:"EURO_SHORT",params:[n],pattern:/^(0[1-9]|[12][0-9]|3[01])[-\/\.](0[1-9]|1[012])[-\/\.]\d\d$/,message:"INVALID_DATE_EURO_SHORT_MIN",type:"conditionalDate"};break;case"dateIso":case"date_iso":r={pattern:/^(19|20)\d\d([-])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$/,message:"INVALID_DATE_ISO",type:"regex"};break;case"dateIsoBetween":case"date_iso_between":case"betweenDateIso":case"between_date_iso":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_iso:1990-01-01,2000-12-31";r={condition:[">=","<="],dateType:"ISO",params:[_[0],_[1]],pattern:/^(19|20)\d\d([-])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$/,message:"INVALID_DATE_ISO_BETWEEN",type:"conditionalDate"};break;case"dateIsoMax":case"date_iso_max":case"maxDateIso":case"max_date_iso":r={condition:"<=",dateType:"ISO",params:[n],pattern:/^(19|20)\d\d([-])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$/,message:"INVALID_DATE_ISO_MAX",type:"conditionalDate"};break;case"dateIsoMin":case"date_iso_min":case"minDateIso":case"min_date_iso":r={condition:">=",dateType:"ISO",params:[n],pattern:/^(19|20)\d\d([-])(0[1-9]|1[012])\2(0[1-9]|[12][0-9]|3[01])$/,message:"INVALID_DATE_ISO_MIN",type:"conditionalDate"};break;case"dateUsLong":case"date_us_long":r={pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_US_LONG",type:"regex"};break;case"dateUsLongBetween":case"date_us_long_between":case"betweenDateUsLong":case"between_date_us_long":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_us_long:01/01/1990,12/31/2015";r={condition:[">=","<="],dateType:"US_LONG",params:[_[0],_[1]],pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_US_LONG_BETWEEN",type:"conditionalDate"};break;case"dateUsLongMax":case"date_us_long_max":case"maxDateUsLong":case"max_date_us_long":r={condition:"<=",dateType:"US_LONG",params:[n],pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_US_LONG_MAX",type:"conditionalDate"};break;case"dateUsLongMin":case"date_us_long_min":case"minDateUsLong":case"min_date_us_long":r={condition:">=",dateType:"US_LONG",params:[n],pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.](19|20)\d\d$/,message:"INVALID_DATE_US_LONG_MIN",type:"conditionalDate"};break;case"dateUsShort":case"date_us_short":r={pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.]\d\d$/,message:"INVALID_DATE_US_SHORT",type:"regex"};break;case"dateUsShortBetween":case"date_us_short_between":case"betweenDateUsShort":case"between_date_us_short":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_us_short:01/01/90,12/31/15";r={condition:[">=","<="],dateType:"US_SHORT",params:[_[0],_[1]],pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.]\d\d$/,message:"INVALID_DATE_US_SHORT_BETWEEN",type:"conditionalDate"};break;case"dateUsShortMax":case"date_us_short_max":case"maxDateUsShort":case"max_date_us_short":r={condition:"<=",dateType:"US_SHORT",params:[n],pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.]\d\d$/,message:"INVALID_DATE_US_SHORT_MAX",type:"conditionalDate"};break;case"dateUsShortMin":case"date_us_short_min":case"minDateUsShort":case"min_date_us_short":r={condition:">=",dateType:"US_SHORT",params:[n],pattern:/^(0[1-9]|1[012])[-\/\.](0[1-9]|[12][0-9]|3[01])[-\/\.]\d\d$/,message:"INVALID_DATE_US_SHORT_MIN",type:"conditionalDate"};break;case"different":case"differentInput":case"different_input":var e=n.split(",");r={condition:"!=",message:"INVALID_INPUT_DIFFERENT",params:e,type:"matching"};break;case"digits":r={pattern:"^\\d{"+n+"}$",message:"INVALID_DIGITS",params:[n],type:"regex"};break;case"digitsBetween":case"digits_between":var _=n.split(",");if(2!==_.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: digits_between:1,5";r={pattern:"^\\d{"+_[0]+","+_[1]+"}$",message:"INVALID_DIGITS_BETWEEN",params:[_[0],_[1]],type:"regex"};break;case"email":r={pattern:/^[-\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9#~!$%^&*_=+\/`\|}{\'?]+(\.[-\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9#~!$%^&*_=+\/`\|}{\'?]+)*@([\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9_][-\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9_]*(\.[-\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ0-9_]+)*([\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ]+)|(\.[\wа-яàáâãäåæçèéêëœìíïîðòóôõöøùúûñüýÿßÞďđ]{2,6})|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i,message:"INVALID_EMAIL",type:"regex"};break;case"exactLen":case"exact_len":r={pattern:"^(.|[\\r\\n]){"+n+"}$",message:"INVALID_EXACT_LEN",params:[n],type:"regex"};break;case"float":r={pattern:/^\d*\.{1}\d+$/,message:"INVALID_FLOAT",type:"regex"};break;case"floatSigned":case"float_signed":r={pattern:/^[-+]?\d*\.{1}\d+$/,message:"INVALID_FLOAT_SIGNED",type:"regex"};break;case"iban":r={pattern:/^[a-zA-Z]{2}\d{2}\s?([0-9a-zA-Z]{4}\s?){4}[0-9a-zA-Z]{2}$/i,message:"INVALID_IBAN",type:"regex"};break;case"in":case"inList":case"in_list":var c=n.replace(/,/g,"|");r={pattern:"^(\\b("+c+")\\b)$",patternFlag:"i",message:"INVALID_IN_LIST",params:[n],type:"regex"};break;case"int":case"integer":r={pattern:/^\d+$/,message:"INVALID_INTEGER",type:"regex"};break;case"intSigned":case"integerSigned":case"int_signed":case"integer_signed":r={pattern:/^[+-]?\d+$/,message:"INVALID_INTEGER_SIGNED",type:"regex"};break;case"ip":case"ipv4":r={pattern:/^(25[0-5]|2[0-4]\d|[0-1]?\d?\d)(\.(25[0-5]|2[0-4]\d|[0-1]?\d?\d)){3}$/,message:"INVALID_IPV4",type:"regex"};break;case"ipv6":r={pattern:/^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$/i,message:"INVALID_IPV6",type:"regex"};break;case"match":case"matchInput":case"match_input":case"same":var e=n.split(",");r={condition:"===",message:"INVALID_INPUT_MATCH",params:e,type:"matching"};break;case"max":r={patternLength:"^(.|[\\r\\n]){0,"+n+"}$",messageLength:"INVALID_MAX_CHAR",conditionNum:"<=",messageNum:"INVALID_MAX_NUM",params:[n],type:"autoDetect"};break;case"maxLen":case"max_len":r={pattern:"^(.|[\\r\\n]){0,"+n+"}$",message:"INVALID_MAX_CHAR",params:[n],type:"regex"};break;case"maxNum":case"max_num":r={condition:"<=",message:"INVALID_MAX_NUM",params:[n],type:"conditionalNumber"};break;case"min":r={patternLength:"^(.|[\\r\\n]){"+n+",}$",messageLength:"INVALID_MIN_CHAR",conditionNum:">=",messageNum:"INVALID_MIN_NUM",params:[n],type:"autoDetect"};break;case"minLen":case"min_len":r={pattern:"^(.|[\\r\\n]){"+n+",}$",message:"INVALID_MIN_CHAR",params:[n],type:"regex"};break;case"minNum":case"min_num":r={condition:">=",message:"INVALID_MIN_NUM",params:[n],type:"conditionalNumber"};break;case"notIn":case"not_in":case"notInList":case"not_in_list":var c=n.replace(/,/g,"|");r={pattern:"^((?!\\b("+c+")\\b).)+$",patternFlag:"i",message:"INVALID_NOT_IN_LIST",params:[n],type:"regex"};break;case"numeric":r={pattern:/^\d*\.?\d+$/,message:"INVALID_NUMERIC",type:"regex"};break;case"numericSigned":case"numeric_signed":r={pattern:/^[-+]?\d*\.?\d+$/,message:"INVALID_NUMERIC_SIGNED",type:"regex"};break;case"pattern":case"regex":r={pattern:t.pattern,message:"INVALID_PATTERN",params:[t.message],type:"regex"};break;case"remote":r={message:"",params:[n],type:"remote"};break;case"required":r={pattern:/\S+/,message:"INVALID_REQUIRED",type:"regex"};break;case"size":r={patternLength:"^(.|[\\r\\n]){"+n+"}$",messageLength:"INVALID_EXACT_LEN",conditionNum:"==",messageNum:"INVALID_EXACT_NUM",params:[n],type:"autoDetect"};break;case"url":r={pattern:/^(http|ftp|https):\/\/[\w\-_]+(\.[\w\-_]+)+([\w\-\.,@?^=%&:\/~\+#]*[\w\-\@?^=%&\/~\+#])?/i,message:"INVALID_URL",type:"regex"};break;case"time":r={pattern:/^([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$/,message:"INVALID_TIME",type:"regex"}}return r.altText=a,r}var a={getElementValidators:e};return a}]); +angular.module("ghiscoding.validation").service("validationService",["$interpolate","$timeout","validationCommon",function(e,o,t){function n(t,n,a){var i=this,m={};if("string"==typeof t&&"string"==typeof n?(m.elmName=t,m.rules=n,m.friendlyName="string"==typeof a?a:""):m=t,"object"!=typeof m||!m.hasOwnProperty("elmName")||!m.hasOwnProperty("rules")||!m.hasOwnProperty("scope")&&"undefined"==typeof i.validationAttrs.scope)throw"Angular-Validation-Service requires at least the following 3 attributes: {elmName, rules, scope}";var r=m.scope?m.scope:i.validationAttrs.scope;if(m.elm=angular.element(document.querySelector('[name="'+m.elmName+'"]')),"object"!=typeof m.elm||0===m.elm.length)return i;if(new RegExp("{{(.*?)}}").test(m.elmName)&&(m.elmName=e(m.elmName)(r)),m.name=m.elmName,i.validationAttrs.isolatedScope){var l=r.$validationOptions||null;r=i.validationAttrs.isolatedScope,l&&(r.$validationOptions=l)}m.elm.bind("blur",b=function(e){var o=i.commonObj.getFormElementByName(m.elmName);o&&!o.isValidationCancelled&&(i.commonObj.initialize(r,m.elm,m,m.ctrl),d(i,e.target.value,10))}),m=i.commonObj.mergeObjects(i.validationAttrs,m),y(i,r,m),m.elm.on("$destroy",function(){var e=i.commonObj.getFormElementByName(i.commonObj.ctrl.$name);e&&(s(i,e),i.commonObj.removeFromValidationSummary(m.name))});var c=r.$watch(function(){return m.ctrl=angular.element(m.elm).controller("ngModel"),f(i,m.elmName)?{badInput:!0}:m.ctrl.$modelValue},function(e,t){if(e&&e.badInput){var n=i.commonObj.getFormElementByName(m.elmName);return v(i,n),u(i,m.name)}if(void 0===e&&void 0!==t&&!isNaN(t))return o.cancel(i.timer),void i.commonObj.ctrl.$setValidity("validation",i.commonObj.validate("",!0));m.ctrl=angular.element(m.elm).controller("ngModel"),m.value=e,i.commonObj.initialize(r,m.elm,m,m.ctrl);var a="undefined"==typeof e||"number"==typeof e&&isNaN(e)?0:void 0;d(i,e,a)},!0);return O.push({elmName:m.elmName,watcherHandler:c}),i}function a(e){var o=this,t="",n=!0;if("undefined"==typeof e||"undefined"==typeof e.$validationSummary)throw"checkFormValidity() requires a valid Angular Form or $scope/vm object passed as argument to work properly, for example:: fn($scope) OR fn($scope.form1) OR fn(vm) OR fn(vm.form1)";for(var a=0,i=e.$validationSummary.length;i>a;a++)if(n=!1,t=e.$validationSummary[a].field){var m=o.commonObj.getFormElementByName(t);m&&m.elm&&m.elm.length>0&&("function"==typeof m.ctrl.$setTouched&&m.ctrl.$setTouched(),o.commonObj.updateErrorMsg(e.$validationSummary[a].message,{isSubmitted:!0,isValid:m.isValid,obj:m}))}return n}function i(e){var o=this;if("undefined"==typeof e||"undefined"==typeof e.$validationSummary)throw"clearInvalidValidatorsInSummary() requires a valid Angular Form or $scope/vm object passed as argument to work properly, for example:: fn($scope) OR fn($scope.form1) OR fn(vm) OR fn(vm.form1)";for(var t=[],n=0,a=e.$validationSummary.length;a>n;n++)t.push(e.$validationSummary[n].field);for(n=0,a=t.length;a>n;n++)t[n]&&(o.commonObj.removeFromFormElementObjectList(t[n]),o.commonObj.removeFromValidationSummary(t[n],e.$validationSummary))}function m(e,o){var t,n=this;if("undefined"==typeof e||"undefined"==typeof e.$validationSummary)throw"removeValidator() only works with Validation that were defined by the Service (not by the Directive) and requires a valid Angular Form or $scope/vm object passed as argument to work properly, for example:: fn($scope) OR fn($scope.form1) OR fn(vm) OR fn(vm.form1)";if(o instanceof Array)for(var a=0,i=o.length;i>a;a++)t=n.commonObj.getFormElementByName(o[a]),t.elm.removeAttr("validation"),p(n,t,e.$validationSummary);else o instanceof Object&&o.formElmObj?(t=o.formElmObj,t.elm.removeAttr("validation"),p(o.self,t,e.$validationSummary)):(t=n.commonObj.getFormElementByName(o),t.elm.removeAttr("validation"),p(n,t,e.$validationSummary));return n}function r(e,o){var t,n=this,o=o||{},a="undefined"!=typeof o.removeAllValidators?o.removeAllValidators:!1,i="undefined"!=typeof o.emptyAllInputValues?o.emptyAllInputValues:!1;if("undefined"==typeof e||"undefined"==typeof e.$name)throw"resetForm() requires a valid Angular Form object passed as argument to work properly (ex.: $scope.form1).";var r=n.commonObj.getFormElements(e.$name);if(r instanceof Array)for(var l=0,c=r.length;c>l;l++)t=r[l],i&&t.elm.val(null),a?m(e,{self:n,formElmObj:t}):("function"==typeof t.ctrl.$setUntouched&&t.ctrl.$setUntouched(),t.ctrl.$setPristine(),n.commonObj.updateErrorMsg("",{isValid:!1,obj:t}))}function l(e){var o=this,t="boolean"==typeof e?e:!0;o.commonObj.setDisplayOnlyLastErrorMsg(t)}function c(e){var o=this;return o.validationAttrs=e,o.commonObj.setGlobalOptions(e),o}function d(e,t,n){var a="undefined"!=typeof n?n:e.commonObj.typingLimit,i=e.commonObj.getFormElementByName(e.commonObj.ctrl.$name);return t&&t.badInput?u(e,attrs.name):(e.commonObj.validate(t,!1),e.commonObj.isFieldRequired()||""!==t&&null!==t&&"undefined"!=typeof t?(i.isValidationCancelled=!1,(e.commonObj.isFieldRequired()||t)&&e.commonObj.ctrl.$setValidity("validation",!1),""!==t&&"undefined"!=typeof t||"NUMBER"!==e.commonObj.elm.prop("type").toUpperCase()?"SELECT"===e.commonObj.elm.prop("tagName").toUpperCase()?(e.commonObj.ctrl.$setValidity("validation",e.commonObj.validate(t,!0)),t):("undefined"!=typeof t&&(0===n?e.commonObj.scope.$evalAsync(e.commonObj.ctrl.$setValidity("validation",e.commonObj.validate(t,!0))):(e.commonObj.updateErrorMsg(""),o.cancel(e.timer),e.timer=o(function(){e.commonObj.scope.$evalAsync(e.commonObj.ctrl.$setValidity("validation",e.commonObj.validate(t,!0)))},a))),t):(o.cancel(e.timer),e.commonObj.ctrl.$setValidity("validation",e.commonObj.validate(t,!0)),t)):(s(e,i),t))}function s(e,t){var n=t&&t.ctrl?t.ctrl:e.commonObj.ctrl;t&&(t.isValidationCancelled=!0),o.cancel(self.timer),n.$setValidity("validation",!0),e.commonObj.updateErrorMsg("",{isValid:!0,obj:t}),v(e,t)}function u(e,t){o.cancel(e.timer);var n=e.commonObj.getFormElementByName(t);e.commonObj.updateErrorMsg("INVALID_KEY_CHAR",{isValid:!1,translate:!0,obj:n}),e.commonObj.addToValidationSummary(n,"INVALID_KEY_CHAR",!0)}function f(e,o){var t=e.commonObj.getFormElementByName(o);return!!t&&!!t.elm.prop("validity")&&t.elm.prop("validity").badInput===!0}function p(e,o,t){var n=e.commonObj.scope?e.commonObj.scope:o.scope?o.scope:null;if("undefined"==typeof n)throw"removeValidator() requires a valid $scope object passed but unfortunately could not find it.";var a=e.commonObj.arrayFindObject(O,"elmName",o.fieldName);a&&a.watcherHandler(),o.isValidationCancelled=!0,o.isValid=!0,o.attrs.validation="",s(e,o),"function"==typeof o.ctrl.$setUntouched&&o.ctrl.$setUntouched(),e.commonObj.scope=n,o.ctrl.$setPristine(),e.commonObj.removeFromValidationSummary(o.fieldName,t)}function v(e,o){if(o.isValidationCancelled=!0,"function"==typeof b){var t=o&&o.elm?o.elm:e.commonObj.elm;t.unbind("blur",b)}}function y(e,t,n){t.$watch(function(){return"undefined"==typeof n.elm.attr("ng-disabled")?null:t.$eval(n.elm.attr("ng-disabled"))},function(a){if("undefined"==typeof a||null===a)return null;n.ctrl=angular.element(n.elm).controller("ngModel"),e.commonObj.initialize(t,n.elm,n,n.ctrl);var i=e.commonObj.getFormElementByName(n.name);o(function(){if(a)n.ctrl.$setValidity("validation",!0),e.commonObj.updateErrorMsg("",{isValid:!0,obj:i}),e.commonObj.removeFromValidationSummary(n.name);else{var o=n.ctrl.$viewValue||"";e.commonObj.initialize(t,n.elm,n,n.ctrl),n.ctrl.$setValidity("validation",e.commonObj.validate(o,!1)),i&&(i.isValidationCancelled=!1),n.elm.bind("blur",b=function(o){i&&!i.isValidationCancelled&&d(e,o.target.value,10)})}},0,!1),a&&("function"==typeof n.ctrl.$setUntouched&&n.ctrl.$setUntouched(),n.ctrl.$setValidity("validation",!0),e.commonObj.removeFromValidationSummary(n.name))})}var b,O=[],j=function(e){this.isValidationCancelled=!1,this.timer=null,this.validationAttrs={},this.commonObj=new t,e&&this.setGlobalOptions(e)};return j.prototype.addValidator=n,j.prototype.checkFormValidity=a,j.prototype.removeValidator=m,j.prototype.resetForm=r,j.prototype.setDisplayOnlyLastErrorMsg=l,j.prototype.setGlobalOptions=c,j.prototype.clearInvalidValidatorsInSummary=i,j}]); \ No newline at end of file diff --git a/more-examples/customJavascript/app.js b/more-examples/customJavascript/app.js new file mode 100644 index 0000000..6d2fc27 --- /dev/null +++ b/more-examples/customJavascript/app.js @@ -0,0 +1,78 @@ +'use strict'; + +var myApp = angular.module('myApp', ['ghiscoding.validation', 'pascalprecht.translate', 'ui.bootstrap']); +// -- +// configuration +myApp.config(['$compileProvider', function ($compileProvider) { + $compileProvider.debugInfoEnabled(false); + }]) + .config(['$translateProvider', function ($translateProvider) { + $translateProvider.useStaticFilesLoader({ + prefix: '../../locales/validation/', + suffix: '.json' + }); + // load English ('en') table on startup + $translateProvider.preferredLanguage('en').fallbackLanguage('en'); + $translateProvider.useSanitizeValueStrategy('escapeParameters'); + }]); + +// -- +// Directive +myApp.controller('CtrlDirective', ['validationService', function (validationService) { + var vmd = this; + vmd.model = {}; + + // use the validationService only to declare the controllerAs syntax + var vs = new validationService({ controllerAs: vmd }); + + vmd.myCustomValidation1 = function() { + // you can return a boolean for isValid or an objec (see the next function) + var isValid = (vmd.model.input1 === "abc"); + return isValid; + } + + vmd.myCustomValidation2 = function() { + // or you can return an object as { isValid: bool, message: msg } + var isValid = (vmd.model.input2 === "def"); + return { isValid: isValid, message: 'Returned error from custom function.'}; + } + + vmd.submitForm = function() { + if(vs.checkFormValidity(vmd.form1)) { + alert('All good, proceed with submit...'); + } + } +}]); + +// -- +// Service +myApp.controller('CtrlService', ['$scope', 'validationService', function ($scope, validationService) { + var vms = this; + vms.model = {}; + //vms.model.input3 = 'a'; + // use the validationService only to declare the controllerAs syntax + var vs = new validationService({ controllerAs: vms }); + + vs.setGlobalOptions({ scope: $scope }) + .addValidator('input3', 'alpha|min_len:2|custom:vms.myCustomValidation3:alt=Alternate error message.|required') + .addValidator('input4', 'alpha|min_len:2|custom:vms.myCustomValidation4|required'); + + vms.myCustomValidation3 = function() { + // you can return a boolean for isValid or an objec (see the next function) + var isValid = (vms.model.input3 === "abc"); + return isValid; + } + + vms.myCustomValidation4 = function() { + // or you can return an object as { isValid: bool, message: msg } + var isValid = (vms.model.input4 === "def"); + console.log(isValid); + return { isValid: isValid, message: 'Returned error from custom function.'}; + } + + vms.submitForm = function() { + if(new validationService().checkFormValidity(vms.form2)) { + alert('All good, proceed with submit...'); + } + } +}]); \ No newline at end of file diff --git a/more-examples/customJavascript/index.html b/more-examples/customJavascript/index.html new file mode 100644 index 0000000..3bd002d --- /dev/null +++ b/more-examples/customJavascript/index.html @@ -0,0 +1,117 @@ + + + + + Angular-Validation with Custom Javascript function + + + + + +
+
+

Example of Angular-Validation with Custom Javascript function

+ +

Directive

+
+ +

ERRORS!

+
    +
  • {{ item.field }}: {{item.message}}
  • +
+
+ +
+
+

Type 'abc' for a valid answer

+ + + +
+
+
+

Type 'def' for a valid answer

+ + + +
+
+ + +
+
+
+ +
+ +
+

Service

+
+ +

ERRORS!

+
    +
  • {{ item.field }}: {{item.message}}
  • +
+
+ +
+
+

Type 'abc' for a valid answer

+ + + +
+
+
+

Type 'def' for a valid answer

+ + + +
+
+ + +
+
+
+
+ + + + + + + + + + + + + + + + + + + + + diff --git a/package.json b/package.json index 40b4108..c8cfcc8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-validation-ghiscoding", - "version": "1.4.10", + "version": "1.4.11", "author": "Ghislain B.", "description": "Angular-Validation Directive and Service (ghiscoding)", "main": "app.js", diff --git a/protractor/conf.js b/protractor/conf.js index 79af1e9..5dba351 100644 --- a/protractor/conf.js +++ b/protractor/conf.js @@ -22,6 +22,7 @@ // Spec patterns are relative to the current working directory when protractor is called specs: [ 'badInput_spec.js', + 'custom_spec.js', 'mixed_validation_spec.js', 'angularUI_spec.js', 'dynamic_spec.js', @@ -33,9 +34,9 @@ ], jasmineNodeOpts: { showColors: true, - defaultTimeoutInterval: 800000 + defaultTimeoutInterval: 850000 }, - allScriptsTimeout: 800000, + allScriptsTimeout: 850000, seleniumAddress: 'http://localhost:4444/wd/hub', // format the output when tests are run with Team City diff --git a/protractor/custom_spec.js b/protractor/custom_spec.js new file mode 100644 index 0000000..efb3b23 --- /dev/null +++ b/protractor/custom_spec.js @@ -0,0 +1,132 @@ +describe('Angular-Validation Custom Javascript Validation Tests:', function () { + // global variables + var formElementNames = ['input1', 'input2', 'input3', 'input4']; + var errorMessages = [ + 'May only contain letters. Must be at least 2 characters. Field is required.', + 'May only contain letters. Must be at least 2 characters. Field is required.', + 'May only contain letters. Must be at least 2 characters. Field is required.', + 'May only contain letters. Must be at least 2 characters. Field is required.' + ]; + var errorTooShort = [ + 'Must be at least 2 characters. Alternate error message.', + 'Must be at least 2 characters. Returned error from custom function.', + 'Must be at least 2 characters. Alternate error message.', + 'Must be at least 2 characters. Returned error from custom function.' + ]; + var oneChar = ['a', 'd', 'a', 'd']; + var validInputTexts = ['abc', 'def', 'abc', 'def']; + + describe('When choosing `more-examples` custom javascript', function () { + it('Should navigate to home page', function () { + browser.get('http://localhost/Github/angular-validation/more-examples/customJavascript/'); + + // Find the title element + var titleElement = element(by.css('h2')); + expect(titleElement.getText()).toEqual('Example of Angular-Validation with Custom Javascript function'); + }); + + it('Should have multiple errors in Directive & Service validation summary', function () { + var itemRows = element.all(by.binding('message')); + var inputName; + + for (var i = 0, j = 0, ln = itemRows.length; i < ln; i++) { + expect(itemRows.get(i).getText()).toEqual(defaultErrorMessages[i]); + } + }); + + it('Should check that both submit buttons are disabled', function() { + var elmSubmit1 = $('[name=btn_ngDisabled1]'); + expect(elmSubmit1.isEnabled()).toBe(false); + + var elmSubmit2 = $('[name=btn_ngDisabled2]'); + expect(elmSubmit2.isEnabled()).toBe(false); + }); + + it('Should click, blur on each form elements and error message should display on each of them', function () { + for (var i = 0, ln = formElementNames.length; i < ln; i++) { + var elmInput = $('[name=' + formElementNames[i] + ']'); + elmInput.click(); + elmInput.sendKeys(protractor.Key.TAB); + + var elmError = $('.validation-' + formElementNames[i]); + expect(elmError.getText()).toEqual(errorMessages[i]); + } + }); + + it('Should enter 1 character in all inputs and display minChar error message', function() { + for (var i = 0, ln = formElementNames.length; i < ln; i++) { + var elmInput = $('[name=' + formElementNames[i] + ']'); + elmInput.click(); + elmInput.sendKeys('a'); + + var elmError = $('.validation-' + formElementNames[i]); + expect(elmError.getText()).toEqual(errorTooShort[i]); + } + }); + + it('Should enter valid text and make error go away', function () { + for (var i = 0, ln = formElementNames.length; i < ln; i++) { + var elmInput = $('[name=' + formElementNames[i] + ']'); + elmInput.click(); + clearInput(elmInput); + elmInput.sendKeys(validInputTexts[i]); + elmInput.sendKeys(protractor.Key.TAB); + + var elmError = $('.validation-' + formElementNames[i]); + expect(elmError.getText()).toEqual(''); + } + }); + + it('Should have both validation summary empty', function() { + var itemRows = element.all(by.binding('message')); + expect(itemRows.count()).toBe(0); + }); + + it('Should check that both submit buttons are now enabled', function() { + var elmSubmit1 = $('[name=btn_ngDisabled1]'); + expect(elmSubmit1.isEnabled()).toBe(true); + + var elmSubmit2 = $('[name=btn_ngDisabled2]'); + expect(elmSubmit2.isEnabled()).toBe(true); + }); + + it('Should navigate to home page', function () { + browser.get('http://localhost/Github/angular-validation/more-examples/customJavascript/'); + + // Find the title element + var titleElement = element(by.css('h2')); + expect(titleElement.getText()).toEqual('Example of Angular-Validation with Custom Javascript function'); + }); + + it('Should click on both ngSubmit buttons', function() { + var btnNgSubmit1 = $('[name=btn_ngSubmit1]'); + btnNgSubmit1.click(); + + var btnNgSubmit2 = $('[name=btn_ngSubmit2]'); + btnNgSubmit2.click(); + }); + + it('Should show error message on each inputs', function () { + for (var i = 0, ln = formElementNames.length; i < ln; i++) { + var elmInput = $('[name=' + formElementNames[i] + ']'); + elmInput.click(); + elmInput.sendKeys(protractor.Key.TAB); + + var elmError = $('.validation-' + formElementNames[i]); + expect(elmError.getText()).toEqual(errorMessages[i]); + } + }); + + }); +}); + +/** From a given input name, clear the input + * @param string input name + */ +function clearInput(elem) { + elem.getAttribute('value').then(function (text) { + var len = text.length + var backspaceSeries = Array(len+1).join(protractor.Key.BACK_SPACE); + elem.sendKeys(backspaceSeries); + }) +} \ No newline at end of file diff --git a/readme.md b/readme.md index 1429d23..00386a8 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,5 @@ #Angular Validation (Directive / Service) -`Version: 1.4.10` +`Version: 1.4.11` ### Form validation after user inactivity of default 1sec. (customizable timeout) Forms Validation with Angular made easy! Angular-Validation is an angular directive/service with locales (languages) with a very simple approach of defining your `validation=""` directly within your element to validate (input, textarea, etc) and...that's it!!! The directive/service will take care of the rest! @@ -80,6 +80,7 @@ All the documentation has been moved to the Wiki section, see the [github wiki]( * [DisplayErrorTo](https://github.com/ghiscoding/angular-validation/wiki/Bootstrap-Input-Groups-Wrapping) * [Isolated Scope](https://github.com/ghiscoding/angular-validation/wiki/Isolated-Scope) * [PreValidate Form (on page load)](https://github.com/ghiscoding/angular-validation/wiki/PreValidate-Form-(on-page-load)) + * [Custom Validation function](https://github.com/ghiscoding/angular-validation/wiki/Custom-Validation-functions) * [Remote Validation (AJAX)](https://github.com/ghiscoding/angular-validation/wiki/Remote-Validation-(AJAX)) * [Remove a Validator](https://github.com/ghiscoding/angular-validation/wiki/Remove-Validator-from-Element) * [Reset Form](https://github.com/ghiscoding/angular-validation/wiki/Reset-Form) diff --git a/src/validation-common.js b/src/validation-common.js index c1dcd70..ab78c9e 100644 --- a/src/validation-common.js +++ b/src/validation-common.js @@ -8,7 +8,7 @@ */ angular .module('ghiscoding.validation') - .factory('validationCommon', ['$rootScope', '$translate', 'validationRules', function ($rootScope, $translate, validationRules) { + .factory('validationCommon', ['$rootScope', '$timeout', '$translate', 'validationRules', function ($rootScope, $timeout, $translate, validationRules) { // global variables of our object (start with _var), these variables are shared between the Directive & Service var _bFieldRequired = false; // by default we'll consider our field not required, if validation attribute calls it, then we'll start validating var _INACTIVITY_LIMIT = 1000; // constant of maximum user inactivity time limit, this is the default cosntant but can be variable through typingLimit variable @@ -504,6 +504,9 @@ angular case "conditionalNumber": isConditionValid = validateConditionalNumber(strValue, validator); break; + case "javascript": + isConditionValid = validateCustomJavascript(strValue, validator, self, formElmObj, showError, validationElmObj); + break; case "matching": isConditionValid = validateMatching(strValue, validator, self, validationElmObj); break; @@ -994,10 +997,89 @@ angular return isValid; } + /** Make a Custom Javascript Validation, this should return a boolean or an object as { isValid: bool, message: msg } + * The argument of `validationElmObj` is mainly there only because it's passed by reference (pointer reference) and + * by the time the $translate promise is done with the translation then the promise in our function will have the latest error message. + * @param string value + * @param object validator + * @param object self + * @param object formElmObj + * @param bool showError + * @param object element validation object (passed by reference) + * @return bool isValid + */ + function validateCustomJavascript(strValue, validator, self, formElmObj, showError, validationElmObj) { + var isValid = true; + var missingErrorMsg = "Custom Javascript Validation requires an error message defined as 'alt=' in your validator or defined in your custom javascript function as { isValid: bool, message: 'your error' }" + var invalidResultErrorMsg = 'Custom Javascript Validation requires a declared function (in your Controller), please review your code.'; + + if (!!strValue) { + var fct = null; + var fname = validator.params[0]; + if (fname.indexOf(".") === -1) { + fct = self.scope[fname]; + } else { + // function name might also be declared with the Controller As alias, for example: vm.customJavascript() + // split the name and flatten it so that we can find it inside the scope + var split = fname.split('.'); + fct = self.scope; + for (var k = 0, kln = split.length; k < kln; k++) { + fct = fct[split[k]]; + } + } + var result = (typeof fct === "function") ? fct() : null; + + // analyze the result, could be a boolean or object type, anything else will throw an error + if (typeof result === "boolean") { + isValid = (!!result) ? true : false; + } + else if (typeof result === "object") { + isValid = (!!result.isValid) ? true : false; + } + else { + throw invalidResultErrorMsg; + } + + if (isValid === false) { + formElmObj.isValid = false; + + // is field is invalid and we have an error message given, then add it to validationSummary and display error + // use of $timeout to make sure we are always at the end of the $digest + // if user passed the error message from inside the custom js function, $translate would come and overwrite this error message and so being sure that we are at the end of the $digest removes this issue. + $timeout(function() { + var errorMsg = validationElmObj.message + ' '; + if(!!result.message) { + errorMsg += result.message; + } + if(errorMsg === ' ') { + throw missingErrorMsg; + } + + addToValidationAndDisplayError(self, formElmObj, errorMsg, false, showError); + }); + } + else if (isValid === true) { + // if field is valid from the remote check (isValid) and from the other validators check (isFieldValid) + // clear up the error message and make the field directly as Valid with $setValidity since remote check arrive after all other validators check + formElmObj.isValid = true; + addToValidationAndDisplayError(self, formElmObj, '', true, showError); + } + + if(typeof result === "undefined") { + throw invalidResultErrorMsg; + } + } + + return isValid; + } + /** Validating a match input checking, it could a check to be the same as another input or even being different. + * The argument of `validationElmObj` is mainly there only because it's passed by reference (pointer reference) and + * by the time the $translate promise is done with the translation then the promise in our function will have the latest error message. * @param string value * @param object validator * @param object self + * @param object element validation object (passed by reference) * @return bool isValid */ function validateMatching(strValue, validator, self, validationElmObj) { @@ -1052,15 +1134,21 @@ angular return isValid; } - /** Make an AJAX Remote Validation with a backend server, - * this should return a promise with the result as a boolean or a { isValid: bool, message: msg } + /** Make an AJAX Remote Validation with a backend server, this should return a promise with the result as a boolean or a { isValid: bool, message: msg } + * The argument of `validationElmObj` is mainly there only because it's passed by reference (pointer reference) and + * by the time the $translate promise is done with the translation then the promise in our function will have the latest error message. * @param string value * @param object validator * @param object self + * @param object formElmObj + * @param bool showError + * @param object element validation object (passed by reference) * @return bool isValid */ function validateRemote(strValue, validator, self, formElmObj, showError, validationElmObj) { var isValid = true; + var missingErrorMsg = "Remote Javascript Validation requires an error message defined as 'alt=' in your validator or defined in your custom remote function as { isValid: bool, message: 'your error' }" + var invalidResultErrorMsg = 'Remote Validation requires a declared function (in your Controller) which also needs to return a Promise, please review your code.'; if (!!strValue && !!showError) { self.ctrl.$processing = true; // $processing can be use in the DOM to display a remote processing message to the user @@ -1099,24 +1187,32 @@ angular promise.then(function (result) { result = result.data || result; _remotePromises.pop(); // remove the last promise from array list of promises - self.ctrl.$processing = false; // finished resolving, no more pending + var errorMsg = validationElmObj.message + ' '; + // analyze the result, could be a boolean or object type, anything else will throw an error if (typeof result === "boolean") { isValid = (!!result) ? true : false; - } else if (typeof result === "object") { + } + else if (typeof result === "object") { isValid = (!!result.isValid) ? true : false; } + else { + throw invalidResultErrorMsg; + } if (isValid === false) { formElmObj.isValid = false; errorMsg += result.message || altText; + if(errorMsg === ' ') { + throw missingErrorMsg; + } // is field is invalid and we have an error message given, then add it to validationSummary and display error addToValidationAndDisplayError(self, formElmObj, errorMsg, false, showError); } - if (isValid === true) { + else if (isValid === true) { // if field is valid from the remote check (isValid) and from the other validators check (isFieldValid) // clear up the error message and make the field directly as Valid with $setValidity since remote check arrive after all other validators check formElmObj.isValid = true; @@ -1126,7 +1222,7 @@ angular }); })(validator.altText); } else { - throw 'Remote Validation requires a declared function (in your Controller) which also needs to return a Promise, please review your code.' + throw invalidResultErrorMsg; } } diff --git a/src/validation-rules.js b/src/validation-rules.js index e7181db..ef77044 100644 --- a/src/validation-rules.js +++ b/src/validation-rules.js @@ -153,6 +153,14 @@ angular type: "regex" }; break; + case "custom" : + case "javascript" : + validator = { + message: '', // there is no error message defined on this one since user will provide his own error message via remote response or `alt=` + params: [ruleParams], + type: "javascript" + }; + break; case "dateEuroLong" : case "date_euro_long" : validator = { diff --git a/src/validation-service.js b/src/validation-service.js index 9ac5711..72e22e8 100644 --- a/src/validation-service.js +++ b/src/validation-service.js @@ -149,7 +149,9 @@ angular attrs.value = newValue; self.commonObj.initialize(scope, attrs.elm, attrs, attrs.ctrl); - attemptToValidate(self, newValue); + + var waitingTimer = (typeof newValue === "undefined" || (typeof newValue === "number" && isNaN(newValue))) ? 0 : undefined; + attemptToValidate(self, newValue, waitingTimer); }, true); // $watch() // save the watcher inside an array in case we want to deregister it when removing a validator @@ -375,13 +377,18 @@ angular // onKeyDown event is the default of Angular, no need to even bind it, it will fall under here anyway // in case the field is already pre-filled, we need to validate it without looking at the event binding if(typeof value !== "undefined") { - // Make the validation only after the user has stopped activity on a field - // everytime a new character is typed, it will cancel/restart the timer & we'll erase any error mmsg - self.commonObj.updateErrorMsg(''); - $timeout.cancel(self.timer); - self.timer = $timeout(function() { + // when no timer, validate right away without a $timeout. This seems quite important on the array input value check + if(typingLimit === 0) { self.commonObj.scope.$evalAsync(self.commonObj.ctrl.$setValidity('validation', self.commonObj.validate(value, true) )); - }, waitingLimit); + }else { + // Make the validation only after the user has stopped activity on a field + // everytime a new character is typed, it will cancel/restart the timer & we'll erase any error mmsg + self.commonObj.updateErrorMsg(''); + $timeout.cancel(self.timer); + self.timer = $timeout(function() { + self.commonObj.scope.$evalAsync(self.commonObj.ctrl.$setValidity('validation', self.commonObj.validate(value, true) )); + }, waitingLimit); + } } return value;