diff --git a/app.js b/app.js index d4851c8..ab4ebb3 100644 --- a/app.js +++ b/app.js @@ -50,7 +50,9 @@ myApp.controller('CtrlValidationDirective', ['$scope', 'validationService', func } } $scope.showValidationSummary = function () { - $scope.displayValidationSummary = true; + $translate.then(function() { + $scope.displayValidationSummary = true; + }); } }]); @@ -104,7 +106,9 @@ myApp.controller('CtrlValidationService', ['$scope', '$translate', 'validationSe }; $scope.showValidationSummary = function () { - $scope.displayValidationSummary = true; + $translate.then(function() { + $scope.displayValidationSummary = true; + }); } $scope.submitForm = function() { diff --git a/bower.json b/bower.json index 571a849..581ebd2 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "ghiscoding.angular-validation", - "version": "1.3.10", + "version": "1.3.11", "authors": [ "Ghislain B." ], diff --git a/changelog.txt b/changelog.txt index ffa3fa9..af185d2 100644 --- a/changelog.txt +++ b/changelog.txt @@ -11,4 +11,5 @@ Angular-Validation change logs 1.3.7 (2015-03-08): Complete rewrite (but same functionality) so that I could add an Angular-Validation Service which is similar implementation as the Directive. Also added `debounce` attribute which is an alias to `typingLimit`, validation rules are now defined as an external service for better maintainability and also created a common file for shared functions by both Validation Directive and Service. 1.3.8 (2015-03-15): Added between/min/max conditional validators on all Date types (ISO, EURO_LONG, EURO_SHORT, US_LONG, US_SHORT) 1.3.9 (2015-03-21): Added validation summary through 2 new and equivalent properties `$scope.$validationSummary` and `$scope.formName.$validationSummary`. Also added `bower` and `gulp` support, the Gulp script gives minified files. -1.3.10 (2015-03-28); Added new function of `checkFormValidity()` before submitting the form. Now use only 1 minified script instead of multiples. \ No newline at end of file +1.3.10 (2015-03-28): Added new function of `checkFormValidity()` before submitting the form. Now use only 1 minified script instead of multiples. +1.3.11 (2015-03-30): Accepted pull request #15 to fix form without name attribute. Also accepted pull request #18 to add Spanish locales. \ No newline at end of file diff --git a/dist/angular-validation.min.js b/dist/angular-validation.min.js index c39ae59..7d1af78 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.3.10 + * @version: 1.3.11 * @license: MIT - * @build: Sun Mar 29 2015 00:27:23 GMT-0400 (Eastern Daylight Time) + * @build: Mon Mar 30 2015 22:23:43 GMT-0400 (Eastern Daylight Time) */ angular.module("ghiscoding.validation",["pascalprecht.translate"]).directive("validation",["$timeout","validationCommon","validationRules",function(i,t){return{restrict:"A",require:"ngModel",link:function(a,e,n,l){function d(){i.cancel(r),u.updateErrorMsg(""),l.$setValidity("validation",!0),e.unbind("blur")}function o(t){return u.validate(t,!1),u.isFieldRequired()||""!==t&&null!==t&&"undefined"!=typeof t?((u.isFieldRequired()||t)&&l.$setValidity("validation",!1),e.bind("blur",function(){return a.$evalAsync(l.$setValidity("validation",u.validate(t,!0))),t}),"SELECT"===e.prop("tagName").toUpperCase()?(l.$setValidity("validation",u.validate(t,!0)),t):("undefined"!=typeof t&&(u.updateErrorMsg(""),i.cancel(r),r=i(function(){a.$evalAsync(l.$setValidity("validation",u.validate(t,!0)))},u.typingLimit)),t)):(d(),t)}var r,u=new t(a,e,n,l);l.$parsers.unshift(o),l.$formatters.unshift(o),n.$observe("disabled",function(i){i?l.$setValidity("validation",!0):l.$setValidity("validation",u.validate(l.$viewValue,!0))})}}}]); -angular.module("ghiscoding.validation").factory("validationCommon",["$timeout","$translate","validationRules",function(t,a,e){function r(){var t=this,a={};t.validators=[],t.typingLimit=c,t.validatorAttrs.hasOwnProperty("debounce")?t.typingLimit=parseInt(t.validatorAttrs.debounce,10):t.validatorAttrs.hasOwnProperty("typingLimit")&&(t.typingLimit=parseInt(t.validatorAttrs.typingLimit,10));var r=t.validatorAttrs.hasOwnProperty("rules")?t.validatorAttrs.rules:t.validatorAttrs.validation;if(r.indexOf("regex:")>=0){var i=r.match("regex:(.*?):regex");if(i.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 s=i[1].split(":=");a={message:s[0],pattern:s[1]},r=r.replace(i[0],"regex:")}var n=r.split("|");if(n){t.bFieldRequired=n.indexOf("required")>=0?!0:!1;for(var l=0,o=n.length;o>l;l++){var d=n[l].split(":");t.validators[l]=e.getElementValidators(d[0],d[1],a)}}return t}function i(t,a,e,r){this.scope=t,this.elm=a,this.ctrl=r,this.validatorAttrs=e,this.defineValidation()}function s(){var t=this;return t.bFieldRequired}function n(t,e){var r=this,i=e&&e.elm?e.elm:r.elm,s=i&&i.attr("name")?i.attr("name"):null;if("undefined"==typeof s||null===s)throw'Angular-Validation Service requires you to have a (name="") attribute on the element to validate... Your element is: ng-model="'+i.attr("ng-model")+'"';var n=e&&e.translate?a.instant(t):t,l=s.replace(/[|&;$%@"<>()+,\[\]\{\}]/g,""),o=null;if(r.validatorAttrs&&r.validatorAttrs.hasOwnProperty("validationErrorTo")){var d=r.validatorAttrs.validationErrorTo.charAt(0),v="."===d||"#"===d?r.validatorAttrs.validationErrorTo:"#"+r.validatorAttrs.validationErrorTo;o=angular.element(document.querySelector(v))}else o=angular.element(document.querySelector(".validation-"+l));var p=e&&e.submitted?e.submitted:!1;e&&!e.valid&&(p||r.ctrl.$dirty||r.ctrl.$touched)?o.length>0?o.text(n):i.after(''+n+""):o.text("")}function l(t,e){for(var r,i=this,s=!0,n=!0,l="",d=0,p=i.validators.length;p>d;d++){if("conditionalDate"===i.validators[d].type){if(r=new RegExp(i.validators[d].pattern,"i"),n="\\S+"!==i.validators[d].pattern||"undefined"!=typeof t&&null!==t?r.test(t):!1){var c=i.validators[d].dateType,g=v(t,c).getTime();if(2==i.validators[d].params.length){var m=v(i.validators[d].params[0],c).getTime(),h=v(i.validators[d].params[1],c).getTime(),f=u(i.validators[d].condition[0],g,m),b=u(i.validators[d].condition[1],g,h);n=f&&b?!0:!1}else{var y=v(i.validators[d].params[0],c).getTime();n=u(i.validators[d].condition,g,y)}}}else if("conditionalNumber"===i.validators[d].type)if(2==i.validators[d].params.length){var f=u(i.validators[d].condition[0],parseFloat(t),parseFloat(i.validators[d].params[0])),b=u(i.validators[d].condition[1],parseFloat(t),parseFloat(i.validators[d].params[1]));n=f&&b?!0:!1}else n=u(i.validators[d].condition,parseFloat(t),parseFloat(i.validators[d].params[0]));else if("match"===i.validators[d].type){var O=i.validators[d].params[0],R=i.scope.$eval(O);n=R===t}else i.elm.prop("disabled")?n=!0:"string"==typeof t&&""===t&&"NUMBER"===i.elm.prop("type").toUpperCase()?(l=a.instant("INVALID_KEY_CHAR"),n=!1):(r=new RegExp(i.validators[d].pattern,"i"),n="\\S+"!==i.validators[d].pattern||"undefined"!=typeof t&&null!==t?r.test(t):!1);if(!n&&(s=!1,l+=a.instant(i.validators[d].message),"undefined"!=typeof i.validators[d].params))for(var A=0,E=i.validators[d].params.length;E>A;A++)"match"===i.validators[d].type&&E>1&&0===A||(l=l.replace(":param",i.validators[d].params[A]))}return o(i,a.instant(l)),e&&i.updateErrorMsg(l,{valid:s}),s}function o(t,a){var e=t.elm.attr("name"),r=d(g,"field",e);if(r>=0&&""===a)g.splice(r,1);else if(""!==a){var i={field:e,message:a};r>=0?g[r]=i:g.push(i)}t.scope.$validationSummary=g;var s=angular.element(document.querySelector("form")).attr("name");s&&(t.scope[s].$validationSummary=g)}function d(t,a,e){for(var r=0;r8?t.substring(9).split(":"):null;break;case"UK":case"EURO":case"EURO_SHORT":case"EURO-SHORT":case"EUROPE":e=t.substring(0,8),r=t.substring(2,3),i=p(e,r),o=i[0],l=i[1],n=parseInt(i[2])<50?"20"+i[2]:"19"+i[2],s=t.length>8?t.substring(9).split(":"):null;break;case"US_LONG":case"US-LONG":e=t.substring(0,10),r=t.substring(2,3),i=p(e,r),l=i[0],o=i[1],n=i[2],s=t.length>8?t.substring(9).split(":"):null;break;case"US":case"US_SHORT":case"US-SHORT":e=t.substring(0,8),r=t.substring(2,3),i=p(e,r),l=i[0],o=i[1],n=parseInt(i[2])<50?"20"+i[2]:"19"+i[2],s=t.length>8?t.substring(9).split(":"):null;break;case"ISO":default:e=t.substring(0,10),r=t.substring(4,5),i=p(e,r),n=i[0],l=i[1],o=i[2],s=t.length>10?t.substring(11).split(":"):null}var d=s&&3===s.length?s[0]:0,v=s&&3===s.length?s[1]:0,u=s&&3===s.length?s[2]:0;return new Date(n,l-1,o,d,v,u)}function p(t,a){var e=[];switch(a){case"/":e=t.split("/");break;case".":e=t.split(".");break;case"-":default:e=t.split("-")}return e}function u(t,a,e){var r=!1;switch(t){case"<":r=e>a?!0:!1;break;case"<=":r=e>=a?!0:!1;break;case">":r=a>e?!0:!1;break;case">=":r=a>=e?!0:!1;break;case"!=":case"<>":r=a!=e?!0:!1;break;case"=":case"==":r=a==e?!0:!1;break;default:r=!1}return r}var c=1e3,g=[],m=function(t,a,e,r){this.timer=null,this.bFieldRequired=!1,this.validators=[],this.typingLimit=c,this.scope=t,this.elm=a,this.ctrl=r,this.validatorAttrs=e,t&&a&&e&&r&&this.defineValidation()};return m.prototype.defineValidation=r,m.prototype.isFieldRequired=s,m.prototype.initialize=i,m.prototype.updateErrorMsg=n,m.prototype.validate=l,m}]); +angular.module("ghiscoding.validation").factory("validationCommon",["$timeout","$translate","validationRules",function(t,a,e){function r(){var t=this,a={};t.validators=[],t.typingLimit=g,t.validatorAttrs.hasOwnProperty("debounce")?t.typingLimit=parseInt(t.validatorAttrs.debounce,10):t.validatorAttrs.hasOwnProperty("typingLimit")&&(t.typingLimit=parseInt(t.validatorAttrs.typingLimit,10));var r=t.validatorAttrs.hasOwnProperty("rules")?t.validatorAttrs.rules:t.validatorAttrs.validation;if(r.indexOf("regex:")>=0){var i=r.match("regex:(.*?):regex");if(i.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 s=i[1].split(":=");a={message:s[0],pattern:s[1]},r=r.replace(i[0],"regex:")}var n=r.split("|");if(n){t.bFieldRequired=n.indexOf("required")>=0?!0:!1;for(var l=0,o=n.length;o>l;l++){var d=n[l].split(":");t.validators[l]=e.getElementValidators(d[0],d[1],a)}}return t}function i(t,a,e,r){this.scope=t,this.elm=a,this.ctrl=r,this.validatorAttrs=e,this.defineValidation()}function s(){var t=this;return t.bFieldRequired}function n(t,e){var r=this,i=e&&e.elm?e.elm:r.elm,s=i&&i.attr("name")?i.attr("name"):null;if("undefined"==typeof s||null===s)throw'Angular-Validation Service requires you to have a (name="") attribute on the element to validate... Your element is: ng-model="'+i.attr("ng-model")+'"';var n=e&&e.translate?a.instant(t):t,l=s.replace(/[|&;$%@"<>()+,\[\]\{\}]/g,""),o=null;if(r.validatorAttrs&&r.validatorAttrs.hasOwnProperty("validationErrorTo")){var d=r.validatorAttrs.validationErrorTo.charAt(0),v="."===d||"#"===d?r.validatorAttrs.validationErrorTo:"#"+r.validatorAttrs.validationErrorTo;o=angular.element(document.querySelector(v))}else o=angular.element(document.querySelector(".validation-"+l));var p=e&&e.submitted?e.submitted:!1;e&&!e.valid&&(p||r.ctrl.$dirty||r.ctrl.$touched)?o.length>0?o.text(n):i.after(''+n+""):o.text("")}function l(t,e){for(var r,i=this,s=!0,n=!0,l="",d=0,v=i.validators.length;v>d;d++){if("conditionalDate"===i.validators[d].type){if(r=new RegExp(i.validators[d].pattern,"i"),n="\\S+"!==i.validators[d].pattern||"undefined"!=typeof t&&null!==t?r.test(t):!1){var u=i.validators[d].dateType,g=p(t,u).getTime();if(2==i.validators[d].params.length){var m=p(i.validators[d].params[0],u).getTime(),f=p(i.validators[d].params[1],u).getTime(),h=c(i.validators[d].condition[0],g,m),b=c(i.validators[d].condition[1],g,f);n=h&&b?!0:!1}else{var y=p(i.validators[d].params[0],u).getTime();n=c(i.validators[d].condition,g,y)}}}else if("conditionalNumber"===i.validators[d].type)if(2==i.validators[d].params.length){var h=c(i.validators[d].condition[0],parseFloat(t),parseFloat(i.validators[d].params[0])),b=c(i.validators[d].condition[1],parseFloat(t),parseFloat(i.validators[d].params[1]));n=h&&b?!0:!1}else n=c(i.validators[d].condition,parseFloat(t),parseFloat(i.validators[d].params[0]));else if("match"===i.validators[d].type){var O=i.validators[d].params[0],A=i.scope.$eval(O);n=A===t}else i.elm.prop("disabled")?n=!0:"string"==typeof t&&""===t&&"NUMBER"===i.elm.prop("type").toUpperCase()?(l=a.instant("INVALID_KEY_CHAR"),n=!1):(r=new RegExp(i.validators[d].pattern,"i"),n="\\S+"!==i.validators[d].pattern||"undefined"!=typeof t&&null!==t?r.test(t):!1);if(!n&&(s=!1,l+=a.instant(i.validators[d].message),"undefined"!=typeof i.validators[d].params))for(var R=0,S=i.validators[d].params.length;S>R;R++)"match"===i.validators[d].type&&S>1&&0===R||(l=l.replace(":param",i.validators[d].params[R]))}return o(i,a.instant(l)),e&&i.updateErrorMsg(l,{valid:s}),s}function o(t,a){var e=t.elm.attr("name"),r=v(m,"field",e);if(r>=0&&""===a)m.splice(r,1);else if(""!==a){var i={field:e,message:a};r>=0?m[r]=i:m.push(i)}t.scope.$validationSummary=m;var s=d(t);s&&(s.$validationSummary=m)}function d(t){for(var a=document.querySelectorAll("form"),e=0;e8?t.substring(9).split(":"):null;break;case"UK":case"EURO":case"EURO_SHORT":case"EURO-SHORT":case"EUROPE":e=t.substring(0,8),r=t.substring(2,3),i=u(e,r),o=i[0],l=i[1],n=parseInt(i[2])<50?"20"+i[2]:"19"+i[2],s=t.length>8?t.substring(9).split(":"):null;break;case"US_LONG":case"US-LONG":e=t.substring(0,10),r=t.substring(2,3),i=u(e,r),l=i[0],o=i[1],n=i[2],s=t.length>8?t.substring(9).split(":"):null;break;case"US":case"US_SHORT":case"US-SHORT":e=t.substring(0,8),r=t.substring(2,3),i=u(e,r),l=i[0],o=i[1],n=parseInt(i[2])<50?"20"+i[2]:"19"+i[2],s=t.length>8?t.substring(9).split(":"):null;break;case"ISO":default:e=t.substring(0,10),r=t.substring(4,5),i=u(e,r),n=i[0],l=i[1],o=i[2],s=t.length>10?t.substring(11).split(":"):null}var d=s&&3===s.length?s[0]:0,v=s&&3===s.length?s[1]:0,p=s&&3===s.length?s[2]:0;return new Date(n,l-1,o,d,v,p)}function u(t,a){var e=[];switch(a){case"/":e=t.split("/");break;case".":e=t.split(".");break;case"-":default:e=t.split("-")}return e}function c(t,a,e){var r=!1;switch(t){case"<":r=e>a?!0:!1;break;case"<=":r=e>=a?!0:!1;break;case">":r=a>e?!0:!1;break;case">=":r=a>=e?!0:!1;break;case"!=":case"<>":r=a!=e?!0:!1;break;case"=":case"==":r=a==e?!0:!1;break;default:r=!1}return r}var g=1e3,m=[],f=function(t,a,e,r){this.timer=null,this.bFieldRequired=!1,this.validators=[],this.typingLimit=g,this.scope=t,this.elm=a,this.ctrl=r,this.validatorAttrs=e,t&&a&&e&&r&&this.defineValidation()};return f.prototype.defineValidation=r,f.prototype.isFieldRequired=s,f.prototype.initialize=i,f.prototype.updateErrorMsg=n,f.prototype.validate=l,f}]); angular.module("ghiscoding.validation").factory("validationRules",[function(){function e(e,a,t){var s={};switch(e){case"alpha":s={pattern:"^([a-zÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ])+$",message:"INVALID_ALPHA",type:"regex"};break;case"alphaSpaces":case"alpha_spaces":s={pattern:"^([a-zÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ\\s])+$",message:"INVALID_ALPHA_SPACE",type:"regex"};break;case"alphaNum":case"alpha_num":s={pattern:"^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ])+$",message:"INVALID_ALPHA_NUM",type:"regex"};break;case"alphaNumSpaces":case"alpha_num_spaces":s={pattern:"^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ\\s])+$",message:"INVALID_ALPHA_NUM_SPACE",type:"regex"};break;case"alphaDash":case"alpha_dash":s={pattern:"^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ_-])+$",message:"INVALID_ALPHA_DASH",type:"regex"};break;case"alphaDashSpaces":case"alpha_dash_spaces":s={pattern:"^([a-z0-9ÀÁÂÃÄÅÇÈÉÊËÌÍÎÏÒÓÔÕÖÙÚÛÜÝàáâãäåçèéêëìíîïðòóôõöùúûüýÿ\\s_-])+$",message:"INVALID_ALPHA_DASH_SPACE",type:"regex"};break;case"betweenLen":case"between_len":var n=a.split(",");if(2!==n.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_len:1,5";s={pattern:"^.{"+n[0]+","+n[1]+"}$",message:"INVALID_BETWEEN_CHAR",params:[n[0],n[1]],type:"regex"};break;case"betweenNum":case"between_num":var n=a.split(",");if(2!==n.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_num:1,5";s={condition:[">=","<="],message:"INVALID_BETWEEN_NUM",params:[n[0],n[1]],type:"conditionalNumber"};break;case"creditCard":case"credit_card":s={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":s={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=a.split(",");if(2!==n.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_euro_long:01-01-1990,31-12-2015";s={condition:[">=","<="],dateType:"EURO_LONG",params:[n[0],n[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":s={condition:"<=",dateType:"EURO_LONG",params:[a],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":s={condition:">=",dateType:"EURO_LONG",params:[a],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":s={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=a.split(",");if(2!==n.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_euro_short:01-01-90,31-12-15";s={condition:[">=","<="],dateType:"EURO_SHORT",params:[n[0],n[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":s={condition:"<=",dateType:"EURO_SHORT",params:[a],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":s={condition:">=",dateType:"EURO_SHORT",params:[a],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":s={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=a.split(",");if(2!==n.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_iso:1990-01-01,2000-12-31";s={condition:[">=","<="],dateType:"ISO",params:[n[0],n[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":s={condition:"<=",dateType:"ISO",params:[a],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":s={condition:">=",dateType:"ISO",params:[a],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":s={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=a.split(",");if(2!==n.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_us_long:01/01/1990,12/31/2015";s={condition:[">=","<="],dateType:"US_LONG",params:[n[0],n[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":s={condition:"<=",dateType:"US_LONG",params:[a],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":s={condition:">=",dateType:"US_LONG",params:[a],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":s={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=a.split(",");if(2!==n.length)throw"This validation must include exactly 2 params separated by a comma (,) ex.: between_date_us_short:01/01/90,12/31/15";s={condition:[">=","<="],dateType:"US_SHORT",params:[n[0],n[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":s={condition:"<=",dateType:"US_SHORT",params:[a],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":s={condition:">=",dateType:"US_SHORT",params:[a],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"email":s={pattern:"^[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?$",message:"INVALID_EMAIL",type:"regex"};break;case"exactLen":case"exact_len":s={pattern:"^.{"+a+"}$",message:"INVALID_EXACT_LEN",params:[a],type:"regex"};break;case"float":s={pattern:"^\\d*\\.{1}\\d+$",message:"INVALID_FLOAT",type:"regex"};break;case"floatSigned":case"float_signed":s={pattern:"^[-+]?\\d*\\.{1}\\d+$",message:"INVALID_FLOAT_SIGNED",type:"regex"};break;case"iban":s={pattern:"[a-zA-Z]{2}[0-9]{2}[a-zA-Z0-9]{4}[0-9]{7}([a-zA-Z0-9]?){0,16}",message:"INVALID_IBAN",type:"regex"};break;case"int":case"integer":s={pattern:"^\\d+$",message:"INVALID_INTEGER",type:"regex"};break;case"intSigned":case"integerSigned":case"int_signed":case"integer_signed":s={pattern:"^[+-]?\\d+$",message:"INVALID_INTEGER_SIGNED",type:"regex"};break;case"ipv4":s={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":s={pattern:"^(?:[0-9a-fA-F]{1,4}:){7}[0-9a-fA-F]{1,4}$",message:"INVALID_IPV6",type:"regex"};break;case"ipv6_hex":s={pattern:"^((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)::((?:[0-9A-Fa-f]{1,4}(?::[0-9A-Fa-f]{1,4})*)?)$",message:"INVALID_IPV6_HEX",type:"regex"};break;case"match":var _=a.split(",");s={message:"INVALID_INPUT_MATCH",params:_,type:"match"};break;case"maxLen":case"max_len":s={pattern:"^.{0,"+a+"}$",message:"INVALID_MAX_CHAR",params:[a],type:"regex"};break;case"maxNum":case"max_num":s={condition:"<=",message:"INVALID_MAX_NUM",params:[a],type:"conditionalNumber"};break;case"minLen":case"min_len":s={pattern:"^.{"+a+",}$",message:"INVALID_MIN_CHAR",params:[a],type:"regex"};break;case"minNum":case"min_num":s={condition:">=",message:"INVALID_MIN_NUM",params:[a],type:"conditionalNumber"};break;case"numeric":s={pattern:"^\\d*\\.?\\d+$",message:"INVALID_NUMERIC",type:"regex"};break;case"numericSigned":case"numeric_signed":s={pattern:"^[-+]?\\d*\\.?\\d+$",message:"INVALID_NUMERIC_SIGNED",type:"regex"};break;case"regex":s={pattern:t.pattern,message:"INVALID_PATTERN",params:[t.message],type:"regex"};break;case"required":s={pattern:"\\S+",message:"INVALID_REQUIRED",type:"regex"};break;case"url":s={pattern:"(http|ftp|https):\\/\\/[\\w\\-_]+(\\.[\\w\\-_]+)+([\\w\\-\\.,@?^=%&:/~\\+#]*[\\w\\-\\@?^=%&/~\\+#])?",message:"INVALID_URL",type:"regex"};break;case"time":s={pattern:"^([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?$",message:"INVALID_TIME",type:"regex"}}return s}var a={getElementValidators:e};return a}]); -angular.module("ghiscoding.validation").service("validationService",["$timeout","validationCommon",function(e,o){function t(e,o){var t=this,n={};if("string"==typeof e&&"string"==typeof o?(n.elmName=e,n.rules=o):n=e,"object"!=typeof n||!n.hasOwnProperty("elmName")||!n.hasOwnProperty("rules")||!n.hasOwnProperty("scope")&&"undefined"==typeof t.validationAttrs.scope)throw"Angular-Validation-Service requires at least the following 3 attributes: {elmName, rules, scope}";return n.elm=angular.element(document.querySelector('[name="'+n.elmName+'"]:not([disabled]):not([ng-disabled]')),"object"!=typeof n.elm||0===n.elm.length?t:(n.elm.bind("blur",function(e){t.commonObj.initialize(n.scope,n.elm,n,n.ctrl),t.commonObj.typingLimit=0,r(t,e.target.value)}),n=m(t.validationAttrs,n),n.scope.$watch(n.elmName,function(e,o){return void 0===e&&void 0!==o?void t.commonObj.updateErrorMsg("INVALID_KEY_CHAR",{valid:!1,translate:!0}):(n.ctrl=angular.element(n.elm).controller("ngModel"),n.value=e,t.commonObj.initialize(n.scope,n.elm,n,n.ctrl),void r(t,e))},!0),t)}function n(e){var o,t,n=this,i="",a=!0;if("undefined"==typeof e)throw"Form validaty checking requires a valid form object passed as argument";for(var r=0,l=e.$validationSummary.length;l>r;r++)a=!1,i=e.$validationSummary[r].field,t=angular.element(document.querySelector('[name="'+i+'"]:not([disabled]):not([ng-disabled]')),o=angular.element(t).controller("ngModel"),t&&t.length>0&&(o.$setTouched(),n.commonObj.updateErrorMsg(e.$validationSummary[r].message,{valid:!1,elm:t,submitted:!0}));return a}function i(e){var o=this;if(e instanceof Array)for(var t=0,n=e.length;n>t;t++)c(o,e[t]);else c(o,e)}function a(e){var o=this;return o.validationAttrs=e,o}function r(o,t){return o.commonObj.validate(t,!1),o.commonObj.isFieldRequired()||""!==t&&null!==t&&"undefined"!=typeof t?((o.commonObj.isFieldRequired()||t)&&o.commonObj.ctrl.$setValidity("validation",!1),"SELECT"===o.commonObj.elm.prop("tagName").toUpperCase()?(o.commonObj.ctrl.$setValidity("validation",o.commonObj.validate(t,!0)),t):("undefined"!=typeof t&&(o.commonObj.updateErrorMsg(""),e.cancel(o.timer),o.timer=e(function(){o.commonObj.scope.$evalAsync(o.commonObj.ctrl.$setValidity("validation",o.commonObj.validate(t,!0)))},o.commonObj.typingLimit)),t)):(l(o),t)}function l(o){e.cancel(self.timer),o.commonObj.updateErrorMsg(""),o.commonObj.ctrl.$setValidity("validation",!0),o.commonObj.elm.unbind("blur")}function m(e,o){var t={};for(var n in e)t[n]=e[n];for(var n in o)t[n]=o[n];return t}function c(e,o){if("undefined"!=typeof e.commonObj.scope){var t=e.commonObj.scope.$watch(o,function(){});t();var n=angular.element(document.querySelector('[name="'+o+'"]'));n.unbind("blur")}}var d=function(){this.validationAttrs={},this.commonObj=new o};return d.prototype.addValidator=t,d.prototype.checkFormValidity=n,d.prototype.removeValidator=i,d.prototype.setGlobalOptions=a,d}]); \ No newline at end of file +angular.module("ghiscoding.validation").service("validationService",["$timeout","validationCommon",function(e,o){function t(e,o){var t=this,n={};if("string"==typeof e&&"string"==typeof o?(n.elmName=e,n.rules=o):n=e,"object"!=typeof n||!n.hasOwnProperty("elmName")||!n.hasOwnProperty("rules")||!n.hasOwnProperty("scope")&&"undefined"==typeof t.validationAttrs.scope)throw"Angular-Validation-Service requires at least the following 3 attributes: {elmName, rules, scope}";return n.elm=angular.element(document.querySelector('[name="'+n.elmName+'"]:not([disabled]):not([ng-disabled]')),"object"!=typeof n.elm||0===n.elm.length?t:(n.elm.bind("blur",function(e){t.commonObj.initialize(n.scope,n.elm,n,n.ctrl),t.commonObj.typingLimit=0,r(t,e.target.value)}),n=m(t.validationAttrs,n),n.scope.$watch(n.elmName,function(e,o){return void 0===e&&void 0!==o?void t.commonObj.updateErrorMsg("INVALID_KEY_CHAR",{valid:!1,translate:!0}):(n.ctrl=angular.element(n.elm).controller("ngModel"),n.value=e,t.commonObj.initialize(n.scope,n.elm,n,n.ctrl),void r(t,e))},!0),t)}function n(e){var o,t,n=this,i="",a=!0;if("undefined"==typeof e||"undefined"==typeof e.$validationSummary)throw"checkFormValidity() requires a valid Angular Form or $scope object passed as argument to function properly (ex.: $scope.form1 OR $scope).";for(var r=0,l=e.$validationSummary.length;l>r;r++)a=!1,i=e.$validationSummary[r].field,t=angular.element(document.querySelector('[name="'+i+'"]:not([disabled]):not([ng-disabled]')),o=angular.element(t).controller("ngModel"),t&&t.length>0&&(o.$setTouched(),n.commonObj.updateErrorMsg(e.$validationSummary[r].message,{valid:!1,elm:t,submitted:!0}));return a}function i(e){var o=this;if(e instanceof Array)for(var t=0,n=e.length;n>t;t++)c(o,e[t]);else c(o,e)}function a(e){var o=this;return o.validationAttrs=e,o}function r(o,t){return o.commonObj.validate(t,!1),o.commonObj.isFieldRequired()||""!==t&&null!==t&&"undefined"!=typeof t?((o.commonObj.isFieldRequired()||t)&&o.commonObj.ctrl.$setValidity("validation",!1),"SELECT"===o.commonObj.elm.prop("tagName").toUpperCase()?(o.commonObj.ctrl.$setValidity("validation",o.commonObj.validate(t,!0)),t):("undefined"!=typeof t&&(o.commonObj.updateErrorMsg(""),e.cancel(o.timer),o.timer=e(function(){o.commonObj.scope.$evalAsync(o.commonObj.ctrl.$setValidity("validation",o.commonObj.validate(t,!0)))},o.commonObj.typingLimit)),t)):(l(o),t)}function l(o){e.cancel(self.timer),o.commonObj.updateErrorMsg(""),o.commonObj.ctrl.$setValidity("validation",!0),o.commonObj.elm.unbind("blur")}function m(e,o){var t={};for(var n in e)t[n]=e[n];for(var n in o)t[n]=o[n];return t}function c(e,o){if("undefined"!=typeof e.commonObj.scope){var t=e.commonObj.scope.$watch(o,function(){});t();var n=angular.element(document.querySelector('[name="'+o+'"]'));n.unbind("blur")}}var d=function(){this.validationAttrs={},this.commonObj=new o};return d.prototype.addValidator=t,d.prototype.checkFormValidity=n,d.prototype.removeValidator=i,d.prototype.setGlobalOptions=a,d}]); \ No newline at end of file diff --git a/index.html b/index.html index 0ac2849..b254ec9 100644 --- a/index.html +++ b/index.html @@ -19,6 +19,7 @@

Angular-Validation Directive|Service (ghiscoding)

+
Type: diff --git a/locales/validation/en.json b/locales/validation/en.json index 619b43f..35c8e10 100644 --- a/locales/validation/en.json +++ b/locales/validation/en.json @@ -52,10 +52,9 @@ "INVALID_URL": "Must be a valid URL. ", "INVALID_TIME": "Must be a valid time format (hh:mm) OR (hh:mm:ss). ", - "AREA1": "TextArea: Alphanumeric + Minimum(15) + Required", "ERRORS": "Errors", - "CHANGE_LANGUAGE": "Change language.", + "CHANGE_LANGUAGE": "Change language", "INPUT2": "Number positive or negative -- input type=\"number\" -- Error on non-numeric characters ", "INPUT3": "Floating number range (integer excluded) -- between_num:x,y OR min_num:x|max_num:y ", "INPUT4": "Multiple Validations + Custom Regex of Date Code (YYWW)", diff --git a/locales/validation/es.json b/locales/validation/es.json new file mode 100644 index 0000000..34a9927 --- /dev/null +++ b/locales/validation/es.json @@ -0,0 +1,79 @@ +{ + "INVALID_ALPHA": "Unicamente puede contener letras. ", + "INVALID_ALPHA_SPACE": "Unicamente puede contener letras y espacios. ", + "INVALID_ALPHA_NUM": "Unicamente puede contener letras y números. ", + "INVALID_ALPHA_NUM_SPACE": "Unicamente puede contener letras, números y espacios. ", + "INVALID_ALPHA_DASH": "Unicamente puede contener letras, números y guiones. ", + "INVALID_ALPHA_DASH_SPACE": "Unicamente puede contener letras, números, guiones y espacios. ", + "INVALID_BETWEEN_CHAR": "El número de caracteres debe de estar entre :param y :param. ", + "INVALID_BETWEEN_NUM": "El valor debe ser númerico y estar entre :param y :param. ", + "INVALID_BOOLEAN": "Unicamente puede contener el texto verdadero ó falso. ", + "INVALID_CREDIT_CARD": "Debe contener un número de tarjeta de crédito valido. ", + "INVALID_DATE_EURO_LONG": "Debe contener una fecha valida con formato (dd-mm-yyyy) ó (dd/mm/yyyy). ", + "INVALID_DATE_EURO_LONG_BETWEEN": "Debe contener una fecha valida entre :param y :param con formato (dd-mm-yyyy) ó (dd/mm/yyyy). ", + "INVALID_DATE_EURO_LONG_MAX": "Debe contener una fecha valida igual ó menor que :param con formato (dd-mm-yyyy) ó (dd/mm/yyyy). ", + "INVALID_DATE_EURO_LONG_MIN": "Debe contener una fecha valida igual ó mayor que :param con formato (dd-mm-yyyy) ó (dd/mm/yyyy). ", + "INVALID_DATE_EURO_SHORT": "Debe contener una fecha valida con formato (dd-mm-yy) o (dd/mm/yy). ", + "INVALID_DATE_EURO_SHORT_BETWEEN": "Debe contener una fecha valida entre :param y :param con formato (dd-mm-yy) o (dd/mm/yy). ", + "INVALID_DATE_EURO_SHORT_MAX": "Debe contener una fecha valida igual ó menor que :param con formato (dd-mm-yy) ó (dd/mm/yy). ", + "INVALID_DATE_EURO_SHORT_MIN": "Debe contener una fecha valida igual ó mayor que :param con formato (dd-mm-yy) ó (dd/mm/yy). ", + "INVALID_DATE_ISO": "Debe contener una fecha valida con formato (yyyy-mm-dd). ", + "INVALID_DATE_ISO_BETWEEN": "Debe contener una fecha valida entre :param y :param con formato (yyyy-mm-dd). ", + "INVALID_DATE_ISO_MAX": "Debe contener una fecha valida igual ó menor que :param con formato (yyyy-mm-dd). ", + "INVALID_DATE_ISO_MIN": "Debe contener una fecha valida igual ó mayor que :param con formato (yyyy-mm-dd). ", + "INVALID_DATE_US_LONG": "Debe contener una fecha valida con formato (mm/dd/yyyy) ó (mm-dd-yyyy). ", + "INVALID_DATE_US_LONG_BETWEEN": "Debe contener una fecha valida entre :param y :param con formato (mm/dd/yyyy) ó (mm/dd/yyyy). ", + "INVALID_DATE_US_LONG_MAX": "Debe contener una fecha valida igual ó menor que :param con formato (mm/dd/yyyy) ó (mm/dd/yyyy). ", + "INVALID_DATE_US_LONG_MIN": "Debe contener una fecha valida igual ó mayor que :param con formato (mm/dd/yyyy) ó (mm/dd/yyyy). ", + "INVALID_DATE_US_SHORT": "Debe contener una fecha valida con formato (mm/dd/yy) ó (mm-dd-yy). ", + "INVALID_DATE_US_SHORT_BETWEEN": "Debe contener una fecha valida entre :param y :param con formato (mm/dd/yy) ó (mm/dd/yy). ", + "INVALID_DATE_US_SHORT_MAX": "Debe contener una fecha valida igual ó menor que :param con formato (mm/dd/yy) ó (mm/dd/yy). ", + "INVALID_DATE_US_SHORT_MIN": "Debe contener una fecha valida igual ó mayor que :param con formato (mm/dd/yy) ó (mm/dd/yy). ", + "INVALID_EMAIL": "Debe contener una dirección de correo electronico valida. ", + "INVALID_EXACT_LEN": "Debe contener exactamente :param caracteres. ", + "INVALID_FLOAT": "Debe contener un número decimal positivo (Los números enteros no son validos). ", + "INVALID_FLOAT_SIGNED": "Debe contener un número decimal positivo ó negativo (Los números enteros no son validos). ", + "INVALID_IBAN": "Debe contener un IBAN valido. ", + "INVALID_INPUT_MATCH": "El campo de confirnmación no coincide con el texto especificado \":param\". ", + "INVALID_INTEGER": "Debe contener un número entero positivo. ", + "INVALID_INTEGER_SIGNED": "Debe contener un número entero positivo ó negativo. ", + "INVALID_IPV4": "Debe contener una dirección IP valida (IPV4). ", + "INVALID_IPV6": "Debe contener una dirección IP valida (IPV6). ", + "INVALID_IPV6_HEX": "Debe contener una dirección IP valida (IPV6 Hex). ", + "INVALID_KEY_CHAR": "Entrada de teclado no valida en un campo de tipo \"number\". ", + "INVALID_MAX_CHAR": "No puede contener mas de :param caracteres. ", + "INVALID_MAX_NUM": "Debe contener un valor númerico igual o menor que :param. ", + "INVALID_MIN_CHAR": "Debe contener almenos :param caracteres. ", + "INVALID_MIN_NUM": "Debe contener un valor númerico igual o mayor que :param. ", + "INVALID_NUMERIC": "Debe contener un valor númerico positivo. ", + "INVALID_NUMERIC_SIGNED": "Debe contener un valor númerico positivo ó negativo. ", + "INVALID_PATTERN": "Debe contener un texto con el formato: :param. ", + "INVALID_REQUIRED": "El campo es requerido. ", + "INVALID_URL": "Debe contener una dirección URL valida. ", + "INVALID_TIME": "Debe contener un formato de tiempo valido (hh:mm) ó (hh:mm:ss). ", + + "AREA1": "Area de texto: Alfanúmerica + Minimo(15) + Requerido", + "ERRORS": "Errores", + "CHANGE_LANGUAGE": "Cambiar idioma", + "INPUT2": "Número positivo o negativo -- input type=\"number\" -- Error o caracteres no númericos ", + "INPUT3": "Rango decimal (Los números enteros no son validos) -- between_num:x,y ó min_num:x|max_num:y ", + "INPUT4": "Multiples validaciones + Código de fecha personalizado (YYWW)", + "INPUT5": "Email", + "INPUT6": "URL", + "INPUT7": "IP (IPV4)", + "INPUT8": "Tarjeta de cédito", + "INPUT9": "Entre(2,6) caracteres", + "INPUT10": "Fecha formato ISO (yyyy-mm-dd)", + "INPUT11": "Fecha formato US largo (mm/dd/yyyy)", + "INPUT12": "Tiempo (hh:mm ó hh:mm:ss) -- No Requerido", + "INPUT13": "AlphaDashSpaces + Requerido + Minimo(5) Caracteres -- Deben ser: validation-error-to=\" \"", + "INPUT14": "Alfanúmerico + Requerido -- NG-DISABLED", + "INPUT15": "Contraseña", + "INPUT16": "Confirmación de contraseña", + "INPUT17": "Alfanúmerico + Exactamente(3) + Requerido -- debounce(5sec)", + "INPUT18": "Fecha formato ISO (yyyy-mm-dd) -- Condición minima >= 2001-01-01 ", + "INPUT19": "Fecha formato US corto (mm/dd/yy) -- entre las fechas 12/01/99 and 12/31/15", + "SAVE": "Guardar", + "SELECT1": "Requerido (select) -- validación con (blur) EVENT", + "SHOW_VALIDATION_SUMMARY": "Mostar el resumén de validación" +} \ No newline at end of file diff --git a/locales/validation/fr.json b/locales/validation/fr.json index 11b68e4..dc4d574 100644 --- a/locales/validation/fr.json +++ b/locales/validation/fr.json @@ -52,10 +52,9 @@ "INVALID_URL": "Doit être un URL valide. ", "INVALID_TIME": "Doit être un format de date valide (hh:mm) OU (hh:mm:ss). ", - "AREA1": "TextArea: Alphanumérique + Minimum(15) + Required", "ERRORS": "Erreurs", - "CHANGE_LANGUAGE": "Changer de langue.", + "CHANGE_LANGUAGE": "Changer de langue", "INPUT2": "Nombre positif ou négatif -- input type=\"number\" -- Erreur sur caractères non-numérique", "INPUT3": "Intervalle de Nombre Flottant (entier exclu) -- between_num:x,y OU min_num:x|max_num:y", "INPUT4": "Multiple Validations + Regex Personnalisé d'un Code Date (AASS)", diff --git a/package.json b/package.json index 111ed51..8a63e08 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "ghiscoding.angular-validation", - "version": "1.3.10", + "version": "1.3.11", "author": "Ghislain B.", "description": "Angular-Validation Directive and Service (ghiscoding)", "main": "app.js", diff --git a/readme.md b/readme.md index 5364f30..2a5b3cd 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,5 @@ #Angular Validation (Directive / Service) -`Version: 1.3.10` +`Version: 1.3.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! @@ -20,12 +20,33 @@ Huge rewrite to have a better code separation and also adding support to Service ## Live Demo [Plunker](http://plnkr.co/jADq7H) + +## Index +* [Plunker Demo](#plunker) +* [Dependency](#dependencies) +* [Install (bower)](#install) +* [Include it in your app project](#project) +* [Requirements](#requirements) +* [Some Working Examples (Directive)](#examples-directive) +* [Some Working Examples (Service)](#examples-service) +* [Form Submit and Validation](#submit) +* [Validation summary](#validation-summary) +* [Bootstrap Input Groups Wrapping - HOWTO](#input-groups-wrapping) +* [Regular Expressions (Regex)](#regex) +* [Locales (languages)](#locales) +* [Available Validators](#validators) +* [Changelog](#changelog) + Install ----- Install with Bower -``` +```javascript +// You can install with +bower install angular-validation-ghiscoding + +// or as another name bower install ghiscoding.angular-validation ``` @@ -54,10 +75,10 @@ myApp.config(function ($translateProvider) { ``` ```html - + - + @@ -65,12 +86,13 @@ myApp.config(function ($translateProvider) { ``` + ## Requirements Angular-Validation requires the element which will use validation to have an html `name=""` attribute, so that in the background it can use this name to create and show an error into a `` which will directly follow your form input. For example: ``. *The necessity of `name=""` attribute is new since version 1.3.4+, prior to this change we were asking the user to create his own `` for error displaying. In other words, the `` is now optional, but the `name=""` attribute becomes mandatory and will throw an error if omitted* - + ## Some Working Examples (Directive) Let's start with a simple example and then let's get down to real business. @@ -162,7 +184,7 @@ P.S. For real live sample, see the [live demo](#plunker) or download the Github ``` -## Form Submitting and Validation +## Form Submit and Validation The Angular-Validation concept was first introduced with the use `ngDisabled` on the submit button, but this might not always be the best option so as a another feature we could simply leave the submit button available but run an extra function to check the form validation before proceeding with our submit (that function is available through the ValidationService). *You could also use the [Validation summary](#validation-summary) for displaying all errors as a header or even a footer* @@ -175,11 +197,19 @@ The Angular-Validation concept was first introduced with the use `ngDisabled` on ``` ```javascript // Option #2 will need to call the `checkFormValidity()` function checking the form before doing a real submit +// $validationSummary can be found in 2 variables (depending if your form as a name or not) +// you can use `checkFormValidity($scope.form1)` or this `checkFormValidity($scope)` +// If your form does not have a name attribute, your only choice is `checkFormValidity($scope)` $scope.submitForm = function() { var myValidation = new validationService(); if(myValidation.checkFormValidity($scope.form1)) { // proceed with submit } + + // or without a form name, use the $scope alone + if(myValidation.checkFormValidity($scope)) { + // proceed with submit + } } // Option #3 - You could also use the $validationSummary to be displayed after a Submit @@ -211,6 +241,7 @@ Display a validation summary of all the current form errors. Validation summary ``` + Bootstrap Input Groups Wrapping - HOWTO -------------------- Well let's face it, having the `` for error display right after the element to be validated is not always ideal and I encounter the problem myself when using Bootstrap on inputs with `input-group`, it had so much wrapping around the input that the next available element might not be the one we want. In these special occasions, we will add a `` or a `
` for displaying the possible error and give the this element an `id="someId"` or a `class="className"` and then reference it inside our input. We could actually move the error element anywhere we want with this method, just don't forget to name it with an `id` or a `className` and call the `validation-error-to` attribute. This attribute could be called in 3 different ways: with `'.'` (element error className) or with/without `'#'` (element error id) We could even do a validation summary with this...just saying hehe. @@ -250,7 +281,7 @@ From the example displayed, I introduce the custom regular expression, there is Regex validation is divided in 4 specific parts (Step #1-4). -Let's use the previous [Examples #5](#examples-directives) and extract the information out of it to see how it works. +Let's use the previous [Examples #5](#examples-directive) and extract the information out of it to see how it works. Step #1-4 are for explanation only, at the end we show the full regex (make sure there is no spaces). 1. Start & end the filter with the following `regex: :regex` which tells the directive where to extract it. @@ -263,12 +294,12 @@ Step #1-4 are for explanation only, at the end we show the full regex (make sure Final code (without spaces): `regex:YYWW:=^(0[9]|1[0-9]|2[0-9]|3[0-9])(5[0-2]|[0-4][0-9])$:regex` - + Locales (languages) -------------------- -Locales are simply sets of language defined in external JSON files, we can easily add any new language as extra files without affecting the behaviour of the angular directive. You could even change displayed language on the fly, well of course the error message will be reflected only after field value is re-evaluated. You of course have to include the `angular-translate` library and configure it, see section [Include it in your Project](#project) +Locales are simple sets of language defined in external JSON files, we can easily add any new language as extra files without affecting the behaviour of the angular directive. You could even change displayed language on the fly (note that the error message will be reflected only after field value is re-evaluated). Make sure to include the `angular-translate` library and configure it, see section [Include it in your Project](#project) -NOTE: To be fully localized, I should add the country code at the end of my JSON filename and then change the suffix on the `angular-translate` `loader` method, but then this would add an overhead and I prefer to keep it simple as validation messages often looks the same anyway. If you do want to be fully localized, then see the example in [Include it in your Project](#project) +NOTE: To be fully localized, I should add the country code at the end of my JSON filename and then change the suffix on the `angular-translate` `loader` method, but this would add an overhead and I prefer to keep it simple as validation messages often looks the same anyway (for example English from UK or US would most probably give similar error messages). If you really do want to be fully localized, then see the example in [Include it in your Project](#project) ```javascript // define a key, could be on the fly with a button or a menu link @@ -281,9 +312,9 @@ $scope.switchLanguage = function (key) { }); }; ``` - *P.S. If you define a new Language set, please make a pull request and I would be happy to add them in current project... It would be nice to have Spanish, German or even Chinese :) Thank you.* + Available Validators -------------------- All validators are written as `snake_case` but it's up to the user's taste and could also be written as `camelCase`. So for example `alpha_dash_spaces` and `alphaDashSpaces` are both equivalent. @@ -374,6 +405,7 @@ License * Add more validators... * Add more locale languages... I need your help on that one!!! + ## CHANGELOG * [1.3.0](https://github.com/ghiscoding/angular-validation/commit/d106996926bef86a0457c90fbb65fe6233f3928d) `2014-12-01` Added support to AngularJS 1.3 * [1.3.1](https://github.com/ghiscoding/angular-validation/commit/44fe9de050504a46bb0eb975c31bc4b0f3b6f516) `2015-01-02` Added Input Match/Confirmation Validator, ex: password confirmation. @@ -383,6 +415,7 @@ License * [1.3.5](https://github.com/ghiscoding/angular-validation/commit/679b24ca4daee8419731c45d1d65d63cb5ca74a5) `2015-01-26` Throw an error message when user did not provide a `name=""` property inside the element to validate. * [1.3.6](https://github.com/ghiscoding/angular-validation/commit/e47e91f45f93a3f191ab6849d06163563674e9e2) `2015-02-09` Added `ng-strict-di` for minification, renamed some files and folder lib to `/vendors`, moved directive into new `/src` folder for better separation. * [1.3.7](https://github.com/ghiscoding/angular-validation/commit/86c16f720d6687d3b5ca93e49a0a37824027e583) `2015-03-08` Complete rewrite (but same functionality) so that I could add an Angular-Validation Service which is similar implementation as the Directive. Also added `debounce` attribute which is an alias to `typingLimit`, validation rules are now defined as an external service for better maintainability and also created a common file for shared functions by both Validation Directive and Service. -* [1.3.8](https://github.com/ghiscoding/angular-validation/commit/492d1060a91fb8b49fc70a0c7a1a581d904e0db0) `2015-03-15` Added between/min/max conditional validators on all Date types (ISO, EURO_LONG, EURO_SHORT, US_LONG, US_SHORT) +* [1.3.8](https://github.com/ghiscoding/angular-validation/commit/492d1060a91fb8b49fc70a0c7a1a581d904e0db0) `2015-03-15` Added between/min/max conditional validators on all Date types (iso, euro_long, euro_short, us_long, us_short) * [1.3.9](https://github.com/ghiscoding/angular-validation/commit/931d3b04a00f0583612aefe28ad0bfcac326a38c) `2015-03-21` Added validation summary through 2 new and equivalent properties `$scope.$validationSummary` and `$scope.formName.$validationSummary`. Also added `bower` and `gulp` support, the Gulp script gives minified files. -* [1.3.10](https://github.com/ghiscoding/angular-validation/commit/18765a8dd986856a9fa176fc4835d90d25f663b2) `2015-03-29` Added new function of `checkFormValidity()` before submitting the form. Now use only 1 minified script instead of multiples. \ No newline at end of file +* [1.3.10](https://github.com/ghiscoding/angular-validation/commit/18765a8dd986856a9fa176fc4835d90d25f663b2) `2015-03-29` Added new function of `checkFormValidity()` before submitting the form. Now use only 1 minified script instead of multiples. +* [1.3.11](https://github.com/ghiscoding/angular-validation/commit/e807584f0bcdf0f28ef2ef905b6bc4e890926ac1) `2015-03-30` Accepted pull request #15 to fix form without name attribute. Also accepted pull request #18 to add Spanish locales. \ No newline at end of file diff --git a/src/validation-common.js b/src/validation-common.js index 74422cb..8877b3d 100644 --- a/src/validation-common.js +++ b/src/validation-common.js @@ -283,21 +283,7 @@ angular //---- // Private functions declaration //---------------------------------- - - /** Get form within scope (if found) - * @param self - */ - function getScopeForm(self) { - var forms = document.querySelectorAll('form'); - for (var i = 0; i < forms.length; i++) { - var form = document.querySelectorAll('form')[i]; - if (form && form.name && self.scope[form.name]) { - return self.scope[form.name]; - } - } - return null; - } - + /** Add the error to the validation summary * @param self * @param string elmName: element name (name attribute) @@ -329,6 +315,20 @@ angular } } + /** Get form within scope (if found) + * @param self + */ + function getScopeForm(self) { + var forms = document.querySelectorAll('form'); + for (var i = 0; i < forms.length; i++) { + var form = document.querySelectorAll('form')[i]; + if (form && form.name && self.scope[form.name]) { + return self.scope[form.name]; + } + } + return null; + } + /** Quick function to find an object inside an array by it's given field name and value, return the index found or -1 * @param Array sourceArray * @param string searchId: search property id diff --git a/src/validation-service.js b/src/validation-service.js index 722c814..4b1511a 100644 --- a/src/validation-service.js +++ b/src/validation-service.js @@ -90,26 +90,26 @@ angular } // addValidator() /** Is the Form all valid? Loop through Validation Summary to get the answer, if any errors are there then display them and return false - * @param object Angular Form Object + * @param object Angular Form or Scope Object * @return bool isFormValid */ - function checkFormValidity(form) { + function checkFormValidity(obj) { var self = this; var ctrl, elm, elmName = '', isValid = true; - if(typeof form === "undefined") { - throw 'Form validaty checking requires a valid form object passed as argument'; + if(typeof obj === "undefined" || typeof obj.$validationSummary === "undefined") { + throw 'checkFormValidity() requires a valid Angular Form or $scope object passed as argument to function properly (ex.: $scope.form1 OR $scope).'; } // loop through $validationSummary and display errors when found on each field - for(var i = 0, ln = form.$validationSummary.length; i < ln; i++) { + for(var i = 0, ln = obj.$validationSummary.length; i < ln; i++) { isValid = false; - elmName = form.$validationSummary[i].field; + elmName = obj.$validationSummary[i].field; elm = angular.element(document.querySelector('[name="'+elmName+'"]:not([disabled]):not([ng-disabled]')); ctrl = angular.element(elm).controller('ngModel'); if(!!elm && elm.length > 0) { ctrl.$setTouched(); // make the element as it was touched for CSS - self.commonObj.updateErrorMsg(form.$validationSummary[i].message, {valid: false, elm: elm, submitted: true}); + self.commonObj.updateErrorMsg(obj.$validationSummary[i].message, {valid: false, elm: elm, submitted: true}); } } return isValid;