From 1b74d9ef82fc8f0294c5b92f8f9aeb05ed359840 Mon Sep 17 00:00:00 2001 From: Ghislain B Date: Mon, 12 Oct 2015 23:24:25 -0400 Subject: [PATCH] Sanitized messages & fixed issue #69 - Added sanitize to the demo page - Fixed issue #69, display proper error message when user type invalid chars on an input[number] --- app.js | 3 +- bower.json | 2 +- changelog.txt | 2 + dist/angular-validation.min.js | 10 +- full-tests/index.html | 4 +- index.html | 5 +- locales/validation/en.json | 14 +- locales/validation/es.json | 13 +- locales/validation/fr.json | 14 +- locales/validation/no.json | 14 +- locales/validation/pl.json | 14 +- locales/validation/pt-br.json | 14 +- locales/validation/ru.json | 14 +- .../dynamic-modal-with-numeric-input/app.js | 62 ++++++++ .../index.html | 84 +++++++++++ package.json | 2 +- protractor/badInput_spec.js | 137 +++++++++++++++++ protractor/conf.js | 1 + protractor/mixed_validation_spec.js | 142 +++++++++--------- readme.md | 6 +- src/validation-common.js | 28 ++-- src/validation-directive.js | 57 ++++--- src/validation-service.js | 81 ++++++++-- templates/testing2Forms.html | 2 +- templates/testingFormDirective.html | 2 +- templates/testingFormNgRepeat.html | 2 +- templates/testingFormService.html | 2 +- ...gular-translate-loader-static-files.min.js | 8 +- .../angular-translate.min.js | 8 +- 29 files changed, 566 insertions(+), 181 deletions(-) create mode 100644 more-examples/dynamic-modal-with-numeric-input/app.js create mode 100644 more-examples/dynamic-modal-with-numeric-input/index.html create mode 100644 protractor/badInput_spec.js diff --git a/app.js b/app.js index f23bf9c..8e6543a 100644 --- a/app.js +++ b/app.js @@ -1,6 +1,6 @@ 'use strict'; -var myApp = angular.module('myApp', ['ngRoute', 'ghiscoding.validation', 'pascalprecht.translate']); +var myApp = angular.module('myApp', ['ngRoute', 'ngSanitize', 'ghiscoding.validation', 'pascalprecht.translate']); myApp.config(['$compileProvider', '$locationProvider', '$routeProvider', function ($compileProvider, $locationProvider, $routeProvider) { $compileProvider.debugInfoEnabled(false); @@ -19,6 +19,7 @@ myApp.config(['$compileProvider', '$locationProvider', '$routeProvider', functio // load English ('en') table on startup $translateProvider.preferredLanguage('en'); + $translateProvider.useSanitizeValueStrategy('escapeParameters'); }]); // -- Main page Controller diff --git a/bower.json b/bower.json index 644e4a8..601db91 100644 --- a/bower.json +++ b/bower.json @@ -1,6 +1,6 @@ { "name": "angular-validation-ghiscoding", - "version": "1.4.9", + "version": "1.4.10", "author": "Ghislain B.", "description": "Angular-Validation Directive and Service (ghiscoding)", "main": [ diff --git a/changelog.txt b/changelog.txt index 086d9b8..4cf59fc 100644 --- a/changelog.txt +++ b/changelog.txt @@ -1,5 +1,7 @@ Angular-Validation change logs +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). 1.4.7 (2015-09-08) Fixed issue #65 - invalid return value on function String.format() 1.4.6 (2015-09-04) Accepted pull #64 - Update Spanish `es.json` translation file. diff --git a/dist/angular-validation.min.js b/dist/angular-validation.min.js index 23a203f..adb4b95 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.9 + * @version: 1.4.10 * @license: MIT - * @build: Sun Oct 04 2015 22:42:40 GMT-0400 (Eastern Daylight Time) + * @build: Mon Oct 12 2015 22:47:06 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,r,n,l){function o(i,n){var o=a.defer(),d=!1,m="undefined"!=typeof n?n:p.typingLimit,s=p.getFormElementByName(l.$name);if(Array.isArray(i)){if(b=[],y="",m=0,i.length>0)return"function"==typeof s.ctrl.$setTouched&&s.ctrl.$setTouched(),u(i,typeof i);m=0}return p.validate(i,!1),p.isFieldRequired()||""!==i&&null!==i&&"undefined"!=typeof i?(s&&(s.isValidationCancelled=!1),(i||p.isFieldRequired())&&l.$setValidity("validation",!1),""!==i&&"undefined"!=typeof i||!r.prop("type")||"NUMBER"!==r.prop("type").toUpperCase()?"SELECT"===r.prop("tagName").toUpperCase()?(d=p.validate(i,!0),l.$setValidity("validation",d),o.resolve({isFieldValid:d,formElmObj:s,value:i}),o.promise):("undefined"!=typeof i&&(0===n?(d=p.validate(i,!0),t.$evalAsync(l.$setValidity("validation",d)),o.resolve({isFieldValid:d,formElmObj:s,value:i})):(p.updateErrorMsg(""),e.cancel(c),c=e(function(){d=p.validate(i,!0),t.$evalAsync(l.$setValidity("validation",d)),o.resolve({isFieldValid:d,formElmObj:s,value:i})},m))),o.promise):(e.cancel(c),d=p.validate(i,!0),l.$setValidity("validation",d),o.resolve({isFieldValid:d,formElmObj:s,value:i}),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&&(b.push(t),parseInt(e)===i-1&&b.forEach(function(a){a.then(function(a){switch(E){case"all":if(a.isFieldValid===!1){var e=p.getGlobalOptions();a.formElmObj.translatePromise.then(function(i){y.length>0&&e.displayOnlyLastErrorMsg?y="["+a.value+"] :: "+(a.formElmObj.validator&&a.formElmObj.validator.params?String.format(i,a.formElmObj.validator.params):i):y+=" ["+a.value+"] :: "+(a.formElmObj.validator&&a.formElmObj.validator.params?String.format(i,a.formElmObj.validator.params):i),p.updateErrorMsg(y,{isValid:!1}),p.addToValidationSummary(a.formElmObj,y)})}break;case"one":default:a.isFieldValid===!0&&(l.$setValidity("validation",!0),f())}})}))}function m(a){var e=p.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 r=a[t];for(var n in r)if(r.hasOwnProperty(n)){if(g&&n!==g)continue;d(r[n],t,i)}}}function s(){f(),p.removeFromValidationSummary($);var a=p.arrayFindObject(V,"elmName",l.$name);a&&a.watcherHandler()}function f(){var a=p.getFormElementByName(l.$name);a&&(a.isValidationCancelled=!0),e.cancel(c),p.updateErrorMsg(""),l.$setValidity("validation",!0),"function"==typeof m&&r.unbind("blur",m)}function v(){var a=l.$viewValue||"";Array.isArray(a)||l.$setValidity("validation",p.validate(a,!1));var e=p.getFormElementByName(l.$name);e&&(e.isValidationCancelled=!1),"function"==typeof m&&r.unbind("blur",m),r.bind("blur",m)}var c,p=new i(t,r,n,l),y="",b=[],V=[],$=n.name,E=n.hasOwnProperty("validArrayRequireHowMany")?n.validArrayRequireHowMany:"one",g=n.hasOwnProperty("validationArrayObjprop")?n.validationArrayObjprop:null,h=t.$watch(function(){return l.$modelValue},function(a){o(a)},!0);V.push({elmName:$,watcherHandler:h}),n.$observe("disabled",function(a){a?(f(),p.removeFromValidationSummary($)):v()}),r.on("$destroy",function(){s()}),t.$watch(function(){return r.attr("validation")},function(a){"undefined"==typeof a||""===a?s():(p.defineValidation(),v())}),r.bind("blur",m)}}}]); -angular.module("ghiscoding.validation").factory("validationCommon",["$rootScope","$translate","validationRules",function(e,t,a){function r(e,a){if("undefined"!=typeof e&&null!=e){var r=e.ctrl&&e.ctrl.$name?e.ctrl.$name:e.attrs&&e.attrs.name?e.attrs.name:e.elm.attr("name"),n=A(r,e),i=O(q,"field",r);if(i>=0&&""===a)q.splice(i,1);else if(""!==a){var o=e.attrs&&e.friendlyName?t.instant(e.friendlyName):"",l={field:r,friendlyName:o,message:a,formName:n?n.$name:null};i>=0?q[i]=l:q.push(l)}if(e.scope.$validationSummary=q,n&&(n.$validationSummary=$(q,"formName",n.$name)),k&&k.controllerAs&&(k.controllerAs.$validationSummary=q,n)){var s=n.$name.indexOf(".")>=0?n.$name.split(".")[1]:n.$name,p=k.controllerAs[s]?k.controllerAs[s]:e.elm.controller()[s];p.$validationSummary=$(q,"formName",n.$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+'"]');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",["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",p=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),f(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(m.elmName,function(e,t){return void 0===e&&void 0!==t?(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),void d(i,e))},!0);return v.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"),u(n,t,e.$validationSummary);else o instanceof Object&&o.formElmObj?(t=o.formElmObj,t.elm.removeAttr("validation"),u(o.self,t,e.$validationSummary)):(t=n.commonObj.getFormElementByName(o),t.elm.removeAttr("validation"),u(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 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;if(t&&(t.isValidationCancelled=!0),o.cancel(self.timer),n.$setValidity("validation",!0),e.commonObj.updateErrorMsg("",{isValid:!0,obj:t}),"function"==typeof p){var a=t&&t.elm?t.elm:e.commonObj.elm;a.unbind("blur",p)}}function u(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(v,"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 f(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",p=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 p,v=[],y=function(e){this.isValidationCancelled=!1,this.timer=null,this.validationAttrs={},this.commonObj=new t,e&&this.setGlobalOptions(e)};return y.prototype.addValidator=n,y.prototype.checkFormValidity=a,y.prototype.removeValidator=m,y.prototype.resetForm=r,y.prototype.setDisplayOnlyLastErrorMsg=l,y.prototype.setGlobalOptions=c,y.prototype.clearInvalidValidatorsInSummary=i,y}]); \ No newline at end of file +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 diff --git a/full-tests/index.html b/full-tests/index.html index 6b536dd..761677c 100644 --- a/full-tests/index.html +++ b/full-tests/index.html @@ -35,8 +35,8 @@

Angular-Validation Directive|Service (ghiscoding)

- - + + diff --git a/index.html b/index.html index c871113..aebf16e 100644 --- a/index.html +++ b/index.html @@ -40,8 +40,9 @@

Angular-Validation Directive|Service (ghiscoding)

- - + + + diff --git a/locales/validation/en.json b/locales/validation/en.json index 0d56415..a64c587 100644 --- a/locales/validation/en.json +++ b/locales/validation/en.json @@ -39,14 +39,14 @@ "INVALID_FLOAT_SIGNED": "May only contain a positive or negative float value (integer excluded). ", "INVALID_IBAN": "Must be a valid IBAN. ", "INVALID_IN_LIST": "Must be a choice inside this list: ({0}). ", - "INVALID_INPUT_DIFFERENT": "Field must be different from specified field \"{1}\". ", - "INVALID_INPUT_MATCH": "Confirmation field does not match specified field \"{1}\". ", + "INVALID_INPUT_DIFFERENT": "Field must be different from specified field [{1}]. ", + "INVALID_INPUT_MATCH": "Confirmation field does not match specified field [{1}]. ", "INVALID_INTEGER": "Must be a positive integer. ", "INVALID_INTEGER_SIGNED": "Must be a positive or negative integer. ", "INVALID_IPV4": "Must be a valid IP (IPV4). ", "INVALID_IPV6": "Must be a valid IP (IPV6). ", "INVALID_IPV6_HEX": "Must be a valid IP (IPV6 Hex). ", - "INVALID_KEY_CHAR": "Invalid keyboard entry on a field of type \"number\". ", + "INVALID_KEY_CHAR": "Invalid keyboard entry on a field of type 'number'. ", "INVALID_MAX_CHAR": "May not be greater than {0} characters. ", "INVALID_MAX_NUM": "Needs to be a numeric value, equal to, or lower than {0}. ", "INVALID_MIN_CHAR": "Must be at least {0} characters. ", @@ -55,7 +55,7 @@ "INVALID_NUMERIC": "Must be a positive number. ", "INVALID_NUMERIC_SIGNED": "Must be a positive or negative number. ", "INVALID_PATTERN": "Must be following this format: {0}. ", - "INVALID_PATTERN_DATA": "Must be following this format \"{{data}}\". ", + "INVALID_PATTERN_DATA": "Must be following this format {{data}}. ", "INVALID_REQUIRED": "Field is required. ", "INVALID_URL": "Must be a valid URL. ", "INVALID_TIME": "Must be a valid time format (hh:mm) OR (hh:mm:ss). ", @@ -65,8 +65,8 @@ "ERRORS": "Errors", "CHANGE_LANGUAGE": "Change language", "FORM_PREVALIDATED": "Form is pre-validated", - "INPUT1": "Remote validation - Type \"abc\" for a valid answer ", - "INPUT2": "Number positive or negative -- input type=\"number\" -- Error on non-numeric characters ", + "INPUT1": "Remote validation - Type 'abc' for a valid answer ", + "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)", "INPUT5": "Email", @@ -77,7 +77,7 @@ "INPUT10": "Date ISO (yyyy-mm-dd)", "INPUT11": "Date US LONG (mm/dd/yyyy)", "INPUT12": "Time (hh:mm OR hh:mm:ss) -- NOT Required", - "INPUT13": "AlphaDashSpaces + Required + Minimum(5) Characters -- MUST USE: validation-error-to=\" \"", + "INPUT13": "AlphaDashSpaces + Required + Minimum(5) Characters -- MUST USE: validation-error-to=' '", "INPUT14": "Alphanumeric + Required -- NG-DISABLED", "INPUT15": "Password", "INPUT16": "Password Confirmation", diff --git a/locales/validation/es.json b/locales/validation/es.json index 2efe689..b397514 100644 --- a/locales/validation/es.json +++ b/locales/validation/es.json @@ -39,14 +39,14 @@ "INVALID_FLOAT_SIGNED": "Debe contener un número decimal positivo ó negativo (Los números enteros no son válidos). ", "INVALID_IBAN": "Debe contener un IBAN válido. ", "INVALID_IN_LIST": "Debe ser una opción dentro de esta lista: ({0}). ", - "INVALID_INPUT_DIFFERENT": "El campo debe ser diferente del campo \"{1}\" especificado. ", - "INVALID_INPUT_MATCH": "El campo de confirmación no coincide con el texto especificado en \"{1}\". ", + "INVALID_INPUT_DIFFERENT": "El campo debe ser diferente del campo [{1}] especificado. ", + "INVALID_INPUT_MATCH": "El campo de confirmación no coincide con el texto especificado en [{1}]. ", "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 válida (IPV4). ", "INVALID_IPV6": "Debe contener una dirección IP válida (IPV6). ", "INVALID_IPV6_HEX": "Debe contener una dirección IP válida (IPV6 Hex). ", - "INVALID_KEY_CHAR": "Entrada de teclado no válida en un campo de tipo \"number\". ", + "INVALID_KEY_CHAR": "Entrada de teclado no válida en un campo de tipo 'number'. ", "INVALID_MAX_CHAR": "No puede contener más de {0} caracteres. ", "INVALID_MAX_NUM": "Debe contener un valor númerico igual o menor que {0}. ", "INVALID_MIN_CHAR": "Debe contener al menos {0} caracteres. ", @@ -55,6 +55,7 @@ "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: {0}. ", + "INVALID_PATTERN_DATA": "Debe contener un texto con el formato {{data}}. ", "INVALID_REQUIRED": "Campo requerido. ", "INVALID_URL": "Debe contener una dirección URL válida. ", "INVALID_TIME": "Debe contener un formato de tiempo válido (hh:mm) ó (hh:mm:ss). ", @@ -64,8 +65,8 @@ "ERRORS": "Errores", "CHANGE_LANGUAGE": "Cambiar idioma", "FORM_PREVALIDATED": "El formulario es pre-validado", - "INPUT1": "Validación Remota - Escriba \"abc\" para una respuesta válida ", - "INPUT2": "Número positivo o negativo -- input type=\"number\" -- Error o caracteres no númericos ", + "INPUT1": "Validación Remota - Escriba 'abc' para una respuesta válida ", + "INPUT2": "Número positivo o negativo -- input type='number' -- Error o caracteres no númericos ", "INPUT3": "Rango decimal (Los números enteros no son válidos) -- between_num:x,y ó min_num:x|max_num:y ", "INPUT4": "Multiples validaciones + Código de fecha personalizado (YYWW)", "INPUT5": "Email", @@ -76,7 +77,7 @@ "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 + Mínimo(5) Caracteres -- Deben ser: validation-error-to=\" \"", + "INPUT13": "AlphaDashSpaces + Requerido + Mínimo(5) Caracteres -- Deben ser: validation-error-to=' '", "INPUT14": "Alfanúmerico + Requerido -- NG-DISABLED", "INPUT15": "Contraseña", "INPUT16": "Confirmación de Contraseña", diff --git a/locales/validation/fr.json b/locales/validation/fr.json index 89d9d17..058eb4b 100644 --- a/locales/validation/fr.json +++ b/locales/validation/fr.json @@ -39,14 +39,14 @@ "INVALID_FLOAT_SIGNED": "Doit être obligatoirement un nombre flottant positif ou négatif (nombre entier exclu). ", "INVALID_IBAN": "Doit être un IBAN valide. ", "INVALID_IN_LIST": "Doit être un choix dans cette liste: ({0}). ", - "INVALID_INPUT_DIFFERENT": "Le champ doit être différente du champ spécifié \"{1}\". ", - "INVALID_INPUT_MATCH": "Le champ de confirmation ne correspond pas au champs spécifié \"{1}\". ", + "INVALID_INPUT_DIFFERENT": "Le champ doit être différente du champ spécifié [{1}]. ", + "INVALID_INPUT_MATCH": "Le champ de confirmation ne correspond pas au champs spécifié [{1}]. ", "INVALID_INTEGER": "Doit être un nombre entier positif. ", "INVALID_INTEGER_SIGNED": "Doit être un nombre entier positif ou négatif. ", "INVALID_IPV4": "Doit être un IP valide (IPV4). ", "INVALID_IPV6": "Doit être un IP valide (IPV6). ", "INVALID_IPV6_HEX": "Doit être un IP valide (IPV6 Hex). ", - "INVALID_KEY_CHAR": "Entrée clavier invalide sur un champs de type \"nombre\". ", + "INVALID_KEY_CHAR": "Entrée clavier invalide sur un champs de type 'nombre'. ", "INVALID_MAX_CHAR": "Doit être plus petit que {0} caractères. ", "INVALID_MAX_NUM": "Doit être une valeur numérique, égale ou inférieure à {0}. ", "INVALID_MIN_CHAR": "Doit avoir au moins {0} caractères. ", @@ -55,7 +55,7 @@ "INVALID_NUMERIC": "Doit être un nombre positif. ", "INVALID_NUMERIC_SIGNED": "Doit être un nombre positif ou négatif. ", "INVALID_PATTERN": "Doit suivre le format: {0}. ", - "INVALID_PATTERN_DATA": "Doit suivre le format \"{{data}}\". ", + "INVALID_PATTERN_DATA": "Doit suivre le format {{data}}. ", "INVALID_REQUIRED": "Le champ est requis. ", "INVALID_URL": "Doit être un URL valide. ", "INVALID_TIME": "Doit être un format de temps valide (hh:mm) OU (hh:mm:ss). ", @@ -65,8 +65,8 @@ "ERRORS": "Erreurs", "CHANGE_LANGUAGE": "Changer de langue", "FORM_PREVALIDATED": "Formulaire est pré-validé", - "INPUT1": "Validation à Distance - Taper \"abc\" pour une réponse valide ", - "INPUT2": "Nombre positif ou négatif -- input type=\"number\" -- Erreur sur caractères non-numérique", + "INPUT1": "Validation à Distance - Taper 'abc' pour une réponse valide ", + "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)", "INPUT5": "Courriel", @@ -77,7 +77,7 @@ "INPUT10": "Date ISO (aaaa-mm-jj)", "INPUT11": "Date US LONG (mm/jj/aaaa)", "INPUT12": "Time (hh:mm OU hh:mm:ss) -- NON Requis", - "INPUT13": "AlphaDashSpaces + Requis + Minimum(5) Caractères -- DOIT UTILISER: validation-error-to=\" \"", + "INPUT13": "AlphaDashSpaces + Requis + Minimum(5) Caractères -- DOIT UTILISER: validation-error-to=' '", "INPUT14": "Alphanumérique + Requis -- NG-DISABLED", "INPUT15": "Mot de Passe", "INPUT16": "Mot de Passe (Confirmation)", diff --git a/locales/validation/no.json b/locales/validation/no.json index 8e900fc..252302c 100644 --- a/locales/validation/no.json +++ b/locales/validation/no.json @@ -39,14 +39,14 @@ "INVALID_FLOAT_SIGNED": "Kan bare inneholde en positiv eller negativ flyttalsverdi (heltall ekskludert). ", "INVALID_IBAN": "Må være en gyldig IBAN. ", "INVALID_IN_LIST": "Må være et valg inne i denne listen: ({0}). ", - "INVALID_INPUT_DIFFERENT": "Feltet skal være forskjellig fra den angitte felt \"{1}\". ", - "INVALID_INPUT_MATCH": "Bekreftelsesfeltet er ikke likt spesifisert felt \"{1}\". ", + "INVALID_INPUT_DIFFERENT": "Feltet skal være forskjellig fra den angitte felt [{1}]. ", + "INVALID_INPUT_MATCH": "Bekreftelsesfeltet er ikke likt spesifisert felt [{1}]. ", "INVALID_INTEGER": "Må være et positivt heltall. ", "INVALID_INTEGER_SIGNED": "Må være et positivt eller negativt heltall. ", "INVALID_IPV4": "Må være en gyldig IP-adresse (IPV4). ", "INVALID_IPV6": "Må være en gyldig IP-adresse (IPV6). ", "INVALID_IPV6_HEX": "Må være en gyldig IP-adresse (IPV6 Hex). ", - "INVALID_KEY_CHAR": "Ugyldig tastaturoppføring på felt av type \"number\". ", + "INVALID_KEY_CHAR": "Ugyldig tastaturoppføring på felt av type 'number'. ", "INVALID_MAX_CHAR": "Kan ikke være større enn {0} characters. ", "INVALID_MAX_NUM": "Må være en numerisk verdi, lik, eller mindre enn {0}. ", "INVALID_MIN_CHAR": "Må være minst {0} tegn. ", @@ -55,7 +55,7 @@ "INVALID_NUMERIC": "Må være et positivt tall. ", "INVALID_NUMERIC_SIGNED": "Må være et positivt eller negativt tall. ", "INVALID_PATTERN": "Må være på følgende format: {0}. ", - "INVALID_PATTERN_DATA": "Må være på følgende format \"{{data}}\". ", + "INVALID_PATTERN_DATA": "Må være på følgende format {{data}}. ", "INVALID_REQUIRED": "Feltet er påkrevd. ", "INVALID_URL": "Må være en gyldig URL. ", "INVALID_TIME": "Må være et gyldig tidsformat (tt:mm) OR (tt:mm:ss). ", @@ -65,8 +65,8 @@ "ERRORS": "Feil", "CHANGE_LANGUAGE": "Endre språk.", "FORM_PREVALIDATED": "Form er pre-godkjent", - "INPUT1": "Ekstern Validering - Type \"abc\" for et gyldig svar ", - "INPUT2": "Positivt eller negativt nummer -- input type=\"number\" -- Feil på ikke-numeriske tegn ", + "INPUT1": "Ekstern Validering - Type 'abc' for et gyldig svar ", + "INPUT2": "Positivt eller negativt nummer -- input type='number' -- Feil på ikke-numeriske tegn ", "INPUT3": "Flyttalssutvalg (heltall ekskludert) -- between_num:x,y eller min_num:x|max_num:y ", "INPUT4": "Multiple Valideringer + Tilpasset Regex av dato kode (YYWW)", "INPUT5": "Epost", @@ -77,7 +77,7 @@ "INPUT10": "ISO dato (yyyy-mm-dd)", "INPUT11": "US LONG dato (mm/dd/yyyy)", "INPUT12": "Tid (hh:mm eller hh:mm:ss) -- IKKE Påkrevd", - "INPUT13": "AlphaDashSpaces + Påkrevd + Minimum(5) Tegn -- MÅ BRUKE: validation-error-to=\" \"", + "INPUT13": "AlphaDashSpaces + Påkrevd + Minimum(5) Tegn -- MÅ BRUKE: validation-error-to=' '", "INPUT14": "Alfanumerisk + Påkrevd -- NG-DISABLED", "INPUT15": "Passord", "INPUT16": "Passord bekreftelse", diff --git a/locales/validation/pl.json b/locales/validation/pl.json index c8d376c..96843e4 100644 --- a/locales/validation/pl.json +++ b/locales/validation/pl.json @@ -39,14 +39,14 @@ "INVALID_FLOAT_SIGNED": "Może zawierać tylko dodatnie lub ujemne liczby zmiennoprzecinkowe (bez liczb całkowitych). ", "INVALID_IBAN": "Musi być poprawnym numerem IBAN. ", "INVALID_IN_LIST": "Wybór musi byćw środku tej listy: ({0}). ", - "INVALID_INPUT_DIFFERENT": "Pole musi być inny od podanego pola \"{1}\". ", - "INVALID_INPUT_MATCH": "Pole potwierdzenia nie zgadza się z polem \"{1}\". ", + "INVALID_INPUT_DIFFERENT": "Pole musi być inny od podanego pola [{1}]. ", + "INVALID_INPUT_MATCH": "Pole potwierdzenia nie zgadza się z polem [{1}]. ", "INVALID_INTEGER": "Musi być dodatnią liczbą całkowitą. ", "INVALID_INTEGER_SIGNED": "Musi być dodatnią lub ujemną liczbą całkowitą. ", "INVALID_IPV4": "Musi być poprawnym adresem IP (IPV4). ", "INVALID_IPV6": "Musi być poprawnym adresem IP (IPV6). ", "INVALID_IPV6_HEX": "Musi być poprawnym adresem IP (IPV6 Hex). ", - "INVALID_KEY_CHAR": "Niepoprawny wpis na polu typu \"liczba\". ", + "INVALID_KEY_CHAR": "Niepoprawny wpis na polu typu 'liczba'. ", "INVALID_MAX_CHAR": "Nie może być dłuższe niż {0} znaków. ", "INVALID_MAX_NUM": "Musi być wartością numeryczną równą lub mniejszą od {0}. ", "INVALID_MIN_CHAR": "Musi być długości co najmniej {0} znaków. ", @@ -55,7 +55,7 @@ "INVALID_NUMERIC": "Musi być liczbą dodatnią. ", "INVALID_NUMERIC_SIGNED": "Musi być liczbą dodatnią lub ujemną. ", "INVALID_PATTERN": "Musi być zgodne z formatem: {0}. ", - "INVALID_PATTERN_DATA": "Musi być zgodne z formatem \"{{data}}\". ", + "INVALID_PATTERN_DATA": "Musi być zgodne z formatem {{data}}. ", "INVALID_REQUIRED": "Pole jest wymagane. ", "INVALID_URL": "Musi być poprawnym adresem URL. ", "INVALID_TIME": "Musi być poprawną godziną w formacie (gg:mm) OR (gg:mm:ss). ", @@ -65,8 +65,8 @@ "ERRORS": "Błędy", "CHANGE_LANGUAGE": "Zmień język", "FORM_PREVALIDATED": "Formularz jest wstępnie zatwierdzony", - "INPUT1": "Zdalna walidacja - Typ \"abc\" dla poprawnej odpowiedzi ", - "INPUT2": "Dodatnia lub ujemna liczba -- typ wejścia=\"liczba\" -- Błąd dla nienumerycznych wartości ", + "INPUT1": "Zdalna walidacja - Typ 'abc' dla poprawnej odpowiedzi ", + "INPUT2": "Dodatnia lub ujemna liczba -- typ wejścia='liczba' -- Błąd dla nienumerycznych wartości ", "INPUT3": "Zakres liczb zmiennoprzecinkowych (włącznie z liczbami całkowitymi) -- between_num:x,y bądź min_num:x|max_num:y ", "INPUT4": "Wielokrotne walidacje + Własne wyrażenie regularne dla kodu daty (YYWW)", "INPUT5": "Email", @@ -77,7 +77,7 @@ "INPUT10": "Data w formacie ISO (rrrr-mm-dd)", "INPUT11": "Data w formacie US LONG (mm/dd/rrrr)", "INPUT12": "Godzina w formacie (gg:mm bądź gg:mm:ss) -- NIEwymagana", - "INPUT13": "AlfaMyślnikiOdstępy + Wymagane + Minimum(5) znaków -- MUSISZ UŻYĆ: validation-error-to=\" \"", + "INPUT13": "AlfaMyślnikiOdstępy + Wymagane + Minimum(5) znaków -- MUSISZ UŻYĆ: validation-error-to=' '", "INPUT14": "Alfanumeryczne + Wymagane -- NG-DISABLED", "INPUT15": "Hasło", "INPUT16": "Potwierdzenie hasła", diff --git a/locales/validation/pt-br.json b/locales/validation/pt-br.json index dcc8d54..3a3b5bc 100644 --- a/locales/validation/pt-br.json +++ b/locales/validation/pt-br.json @@ -39,14 +39,14 @@ "INVALID_FLOAT_SIGNED": "Deve conter um valor decimal positivo ou negativo (excluindo inteiros). ", "INVALID_IBAN": "Deve ser um IBAN válido. ", "INVALID_IN_LIST": "Deve ser uma escolha dentro dessa lista: ({0}). ", - "INVALID_INPUT_DIFFERENT": "O campo deve ser diferente do \"{1}\" campo especificado. ", - "INVALID_INPUT_MATCH": "Campo de confirmação não corresponde ao campo \"{1}\" especificado. ", + "INVALID_INPUT_DIFFERENT": "O campo deve ser diferente do [{1}] campo especificado. ", + "INVALID_INPUT_MATCH": "Campo de confirmação não corresponde ao campo [{1}] especificado. ", "INVALID_INTEGER": "Deve ser um inteiro positivo. ", "INVALID_INTEGER_SIGNED": "Deve ser um inteiro positivo ou negativo. ", "INVALID_IPV4": "Deve ser um IP válido (IPV4). ", "INVALID_IPV6": "Deve ser um IP válido (IPV6). ", "INVALID_IPV6_HEX": "Deve ser um IP válido (IPV6 Hex). ", - "INVALID_KEY_CHAR": "Entrada inválida no campo do campo de tipo \"number\". ", + "INVALID_KEY_CHAR": "Entrada inválida no campo do campo de tipo 'number'. ", "INVALID_MAX_CHAR": "Não deve conter mais do que {0} caracteres. ", "INVALID_MAX_NUM": "Deve ser um valor númerico, igual ou menor que {0}. ", "INVALID_MIN_CHAR": "Deve conter pelo menos {0} caracteres. ", @@ -55,7 +55,7 @@ "INVALID_NUMERIC": "Deve ser um número positivo. ", "INVALID_NUMERIC_SIGNED": "Deve ser um número positivo ou negativo. ", "INVALID_PATTERN": "Deve seguir o seguinte formato: {0}. ", - "INVALID_PATTERN_DATA": "Deve seguir o seguinte formato \"{{data}}\". ", + "INVALID_PATTERN_DATA": "Deve seguir o seguinte formato {{data}}. ", "INVALID_REQUIRED": "Campo obrigatório. ", "INVALID_URL": "Deve ser uma URL válida. ", "INVALID_TIME": "Deve ser um formato de hora válido (hh:mm) ou (hh:mm:ss). ", @@ -65,8 +65,8 @@ "ERRORS": "Erros", "CHANGE_LANGUAGE": "Selecione o idioma", "FORM_PREVALIDATED": "Formulário pré-validado", - "INPUT1": "Validação remota - Digite \"abc\" para uma resposta válida ", - "INPUT2": "Número positivo ou negativo -- campo com o type=\"number\" -- Erro de caracteres não-numéricos", + "INPUT1": "Validação remota - Digite 'abc' para uma resposta válida ", + "INPUT2": "Número positivo ou negativo -- campo com o type='number' -- Erro de caracteres não-numéricos", "INPUT3": "Faixa de números decimais (excluindo inteiros) -- between_num:x,y ou min_num:x|max_num:y ", "INPUT4": "Validações múltiplas + Expressão regular personalizada de formato de data (YYWW)", "INPUT5": "Email", @@ -77,7 +77,7 @@ "INPUT10": "Data ISO (yyyy-mm-dd)", "INPUT11": "Data completa (mm/dd/yyyy)", "INPUT12": "Hora (hh:mm ou hh:mm:ss) -- Não obrigatório", - "INPUT13": "AlphaDashSpaces + obrigatório + Mínimo(5) caracteres -- DEVE USAR: validation-error-to=\" \"", + "INPUT13": "AlphaDashSpaces + obrigatório + Mínimo(5) caracteres -- DEVE USAR: validation-error-to=' '", "INPUT14": "Alphanumeric + Required -- NG-DISABLED", "INPUT15": "Senha", "INPUT16": "Confirmação de Senha", diff --git a/locales/validation/ru.json b/locales/validation/ru.json index 6ada5ec..8f74834 100644 --- a/locales/validation/ru.json +++ b/locales/validation/ru.json @@ -39,14 +39,14 @@ "INVALID_FLOAT_SIGNED": "Может содержать только положительное или отрицательное дробное или целое число. ", "INVALID_IBAN": "Должно быть действительным международным номером банковского счёта (IBAN). ", "INVALID_IN_LIST": "Должно бытьвыбор в этом списке: ({0}). ", - "INVALID_INPUT_DIFFERENT": "Поле должно отличаться от указанного поля \"{1}\". ", - "INVALID_INPUT_MATCH": "Подтверждающее поле не совпадает с указанным полем \"{1}\". ", + "INVALID_INPUT_DIFFERENT": "Поле должно отличаться от указанного поля [{1}]. ", + "INVALID_INPUT_MATCH": "Подтверждающее поле не совпадает с указанным полем [{1}]. ", "INVALID_INTEGER": "Должно быть положительным целым числом. ", "INVALID_INTEGER_SIGNED": "Должно быть положительным или отрицательным целым числом. ", "INVALID_IPV4": "Должно быть действительным ip адресом (IPV4). ", "INVALID_IPV6": "Должно быть действительным ip адресом (IPV6). ", "INVALID_IPV6_HEX": "Должно быть действительным ip адресом (IPV6 Hex). ", - "INVALID_KEY_CHAR": "Неверный ввод с клавиатуры в поле типа \"число\". ", + "INVALID_KEY_CHAR": "Неверный ввод с клавиатуры в поле типа 'число'. ", "INVALID_MAX_CHAR": "Должно быть размером не большим, чем {0} символов. ", "INVALID_MAX_NUM": "Должно быть числовым значением, равное или меньшее чем {0}. ", "INVALID_MIN_CHAR": "Должно быть размером не меньшим, чем {0} символов. ", @@ -55,7 +55,7 @@ "INVALID_NUMERIC": "Должно быть положительным числом. ", "INVALID_NUMERIC_SIGNED": "Должно быть положительным или отрицательным числом. ", "INVALID_PATTERN": "Должно соответствовать этому формату: {0}. ", - "INVALID_PATTERN_DATA": "Должно соответствовать этому формату \"{{data}}\". ", + "INVALID_PATTERN_DATA": "Должно соответствовать этому формату {{data}}. ", "INVALID_REQUIRED": "Поле обязательно для заполнения. ", "INVALID_URL": "Должно быть действительным URL адресом. ", "INVALID_TIME": "Должно быть допустимым форматом времени (hh:mm) или (hh:mm:ss). ", @@ -65,8 +65,8 @@ "ERRORS": "Ошибки", "CHANGE_LANGUAGE": "Изменить язык", "FORM_PREVALIDATED": "Форма предварительно подтверждено", - "INPUT1": "дистанционное проверки - введите \"abc\" для действительного ответа ", - "INPUT2": "Число положительное или отрицательное -- input type=\"number\" -- Ошибка на не числовых значениях ", + "INPUT1": "дистанционное проверки - введите 'abc' для действительного ответа ", + "INPUT2": "Число положительное или отрицательное -- input type='number' -- Ошибка на не числовых значениях ", "INPUT3": "Диапазон дробного числа (включая целые) -- between_num:x,y или min_num:x|max_num:y ", "INPUT4": "Множественная проверка + Пользовательское регулярное выражение формата даты (YYWW)", "INPUT5": "Электронная почта", @@ -77,7 +77,7 @@ "INPUT10": "Дата в формате ISO (yyyy-mm-dd)", "INPUT11": "Дата в формате US LONG (mm/dd/yyyy)", "INPUT12": "Время (hh:mm или hh:mm:ss) -- НЕ обязательное поле", - "INPUT13": "СимволыДефисыПробелы + Обязательное + Минимум(5) символов -- НЕОБХОДИМО ИСПОЛЬЗОВАТЬ: validation-error-to=\" \"", + "INPUT13": "СимволыДефисыПробелы + Обязательное + Минимум(5) символов -- НЕОБХОДИМО ИСПОЛЬЗОВАТЬ: validation-error-to=' '", "INPUT14": "Буквенно-цифровой + Обязательно -- NG-DISABLED", "INPUT15": "Пароль", "INPUT16": "Подтверждение пароля", diff --git a/more-examples/dynamic-modal-with-numeric-input/app.js b/more-examples/dynamic-modal-with-numeric-input/app.js new file mode 100644 index 0000000..f1644f8 --- /dev/null +++ b/more-examples/dynamic-modal-with-numeric-input/app.js @@ -0,0 +1,62 @@ +'use strict'; + +var app = angular.module('myApp', ['ngSanitize', 'ghiscoding.validation', 'pascalprecht.translate', 'ui.bootstrap']); + +app.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('sanitize'); + }]); + +app.directive("dynamicName", function ($compile) { + "use strict"; + + return { + restrict: "A", + terminal: true, + priority: 1000, + link: function (scope, element, attrs) { + element.attr('name', scope.$eval(attrs.dynamicName)); + element.removeAttr("dynamic-name"); + $compile(element)(scope); + } + }; +}); + +app.controller('ListController',['$scope', function($scope) { + $scope.items = [{"id": 1},{"id": 2}]; +}]); + +app.controller('ModalController', ['$scope', '$modal', 'validationService', function ($scope, $modal, validationService) { + "use strict"; + + var myValidation = new validationService({ formName: 'itemsEdit' }); + + $scope.animationsEnabled = true; + + $scope.open = function (size) { + + var modalInstance = $modal.open({ + animation: $scope.animationsEnabled, + templateUrl: 'myModalContent.html', + backdrop: 'static', + controller: 'ModalInstanceController', + size: size, + scope: $scope + }); + }; +}]); + +app.controller('ModalInstanceController', ['$scope', '$modalInstance', '$log', function ($scope, $modalInstance, $log) { + "use strict"; + $scope.cancel = function () { + $modalInstance.dismiss('cancel'); + }; +}]); \ No newline at end of file diff --git a/more-examples/dynamic-modal-with-numeric-input/index.html b/more-examples/dynamic-modal-with-numeric-input/index.html new file mode 100644 index 0000000..6e15329 --- /dev/null +++ b/more-examples/dynamic-modal-with-numeric-input/index.html @@ -0,0 +1,84 @@ + + + + + Angular-Validation Example with Interpolation + + + + + +
+ + +
+
+ {{items}} +
+
+ +
+ + +
+
+ + + + + + + + + + + + + + + + + + + + + + + diff --git a/package.json b/package.json index a47c597..40b4108 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "angular-validation-ghiscoding", - "version": "1.4.9", + "version": "1.4.10", "author": "Ghislain B.", "description": "Angular-Validation Directive and Service (ghiscoding)", "main": "app.js", diff --git a/protractor/badInput_spec.js b/protractor/badInput_spec.js new file mode 100644 index 0000000..266bff0 --- /dev/null +++ b/protractor/badInput_spec.js @@ -0,0 +1,137 @@ +describe('Angular-Validation Tests:', function () { + // global variables + var input2error = "Must be a positive or negative number. Field is required."; + var input2invalidChar = "Invalid keyboard entry on a field of type 'number'."; + var types = ['Directive', 'Service']; + + for(var k = 0, kln = types.length; k < kln; k++) { + // because we are dealing with promises, we better use closures to pass certain variables + (function(types, k) { + describe('When clicking on top menu Angular-Validation >> ' + types[k], function () { + it('Should navigate to Angular-Validation home page', function () { + browser.get('http://localhost/Github/angular-validation'); + + // Find the title element + var titleElement = element(by.css('h1')); + expect(titleElement.getText()).toEqual('Angular-Validation Directive|Service (ghiscoding)'); + }); + + it('Should navigate to TestingForm' + types[k] + ' page', function () { + browser.get('http://localhost/Github/angular-validation'); + + var anchorLink = $('[name=btn_goto_' + types[k] +']'); + anchorLink.click(); + browser.waitForAngular(); + + // Find the sub-title element + var titleElement = element(by.css('h3')); + expect(titleElement.getText()).toEqual(types[k]); + }); + + it('Should display invalid character error message when user type invalid characters in an input[number]', function() { + // scroll back to top + browser.executeScript('window.scrollTo(0,0);').then(function () { + // make input3 invalid, remove text + var elmInput2 = $('[name=input2]'); + elmInput2.click(); + elmInput2.sendKeys('2.5.'); + + // error should appear on input2 + var elmError2 = $('.validation-input2'); + expect(elmError2.getText()).toEqual(input2invalidChar); + }); + }); + + it('Should display same invalid character error message even after a Tab', function() { + // make input3 invalid, remove text + var elmInput2 = $('[name=input2]'); + elmInput2.sendKeys(protractor.Key.TAB); + + // error should appear on input2 + var elmError2 = $('.validation-input2'); + expect(elmError2.getText()).toEqual(input2invalidChar); + }); + + it('Should show ValidationSummary after clicking on show checkbox', function() { + var btnShowSummary = $('[name=btn_showValidation]'); + btnShowSummary.click(); + browser.waitForAngular(); + + // showValidation checkbox should be false at first but true after + var elmCheckboxShowSummary = element(by.model('displayValidationSummary')); + expect(elmCheckboxShowSummary.isSelected()).toBeTruthy(); + }); + + it('Should show same invalid character in ValidationSummary', function() { + // scroll back to top + browser.executeScript('window.scrollTo(0,0);').then(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('input2: ' + input2invalidChar); + } + }); + }); + + it('Should hide ValidationSummary after clicking on checkbox', function() { + var btnShowSummary = $('[name=btn_showValidation]'); + btnShowSummary.click(); + browser.waitForAngular(); + + // showValidation checkbox should be false at first but true after + var elmCheckboxShowSummary = element(by.model('displayValidationSummary')); + //expect(elmCheckboxShowSummary.isSelected()).toBeFalsy(); + }); + + it('Should display default input2 error message after clearing the input', function() { + // make input3 invalid, remove text + var elmInput2 = $('[name=input2]'); + elmInput2.click(); + clearInput(elmInput2, 4); + elmInput2.sendKeys(protractor.Key.TAB); + + // error should appear on input2 + var elmError2 = $('.validation-input2'); + expect(elmError2.getText()).toEqual(input2error); + }); + + it('Should show ValidationSummary after clicking on show checkbox', function() { + var btnShowSummary = $('[name=btn_showValidation]'); + btnShowSummary.click(); + browser.waitForAngular(); + + // showValidation checkbox should be false at first but true after + var elmCheckboxShowSummary = element(by.model('displayValidationSummary')); + expect(elmCheckboxShowSummary.isSelected()).toBeTruthy(); + }); + + it('Should display default input2 error message in ValidationSummary', function() { + // scroll back to top + browser.executeScript('window.scrollTo(0,0);').then(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('input2: ' + input2error); + } + }); + }); + + }); // Directive() + })(types, k); // closure + } // for() + +}); // describe Angular-Validation tests + + +/** From a given input name, clear the input + * @param string input name + */ +function clearInput(elem, ln) { + elem.getAttribute('value').then(function (text) { + var len = (!!ln) ? ln : text.length + var backspaceSeries = Array(len+1).join(protractor.Key.BACK_SPACE); + elem.sendKeys(backspaceSeries); + }) +} \ No newline at end of file diff --git a/protractor/conf.js b/protractor/conf.js index c31fcfd..79af1e9 100644 --- a/protractor/conf.js +++ b/protractor/conf.js @@ -21,6 +21,7 @@ // Spec patterns are relative to the current working directory when protractor is called specs: [ + 'badInput_spec.js', 'mixed_validation_spec.js', 'angularUI_spec.js', 'dynamic_spec.js', diff --git a/protractor/mixed_validation_spec.js b/protractor/mixed_validation_spec.js index 8dd6d79..3537517 100644 --- a/protractor/mixed_validation_spec.js +++ b/protractor/mixed_validation_spec.js @@ -3,77 +3,77 @@ var formElementNames = ['input2', 'input3', 'input4', 'input5', 'input6', 'input7', 'input8', 'input9', 'input10', 'input11', 'input12', 'select1', 'input13', 'input14', 'input15', 'input16', 'input17', 'input18', 'input19', 'input20', 'input21', 'area1']; var formElementSummaryNames = ['input2', 'input3', 'input4', 'Email', 'input6', 'input7', 'Credit Card', 'input9', 'input10', 'input11', 'select1', 'input13', 'input15', 'input16', 'input17', 'input18', 'input19', 'input20', 'input21', 'area1']; var formElementTexts = [ - 'Number positive or negative -- input type="number" -- Error on non-numeric characters', - 'Floating number range (integer excluded) -- between_num:x,y OR min_num:x|max_num:y', - 'Multiple Validations + Custom Regex of Date Code (YYWW)', - 'Email', - 'URL', - 'IP (IPV4)', - 'Credit Card', - 'Between(2,6) Characters', - 'Date ISO (yyyy-mm-dd)', - 'Date US LONG (mm/dd/yyyy)', - 'Time (hh:mm OR hh:mm:ss) -- NOT Required', - 'Required (select) -- validation with (blur) EVENT', - 'AlphaDashSpaces + Required + Minimum(5) Characters -- MUST USE: validation-error-to=" "', - 'Alphanumeric + Required -- NG-DISABLED', - 'Password', - 'Password Confirmation', - 'Different Password', - 'Alphanumeric + Exactly(3) + Required -- debounce(3sec)', - 'Date ISO (yyyy-mm-dd) -- minimum condition >= 2001-01-01', - 'Date US SHORT (mm/dd/yy) -- between the dates 12/01/99 and 12/31/15', - 'Choice IN this list (banana,orange,ice cream)', - 'TextArea: Alphanumeric + Minimum(15) + Required', - 'Input22 - ngDisabled =>' + "Number positive or negative -- input type='number' -- Error on non-numeric characters", + "Floating number range (integer excluded) -- between_num:x,y OR min_num:x|max_num:y", + "Multiple Validations + Custom Regex of Date Code (YYWW)", + "Email", + "URL", + "IP (IPV4)", + "Credit Card", + "Between(2,6) Characters", + "Date ISO (yyyy-mm-dd)", + "Date US LONG (mm/dd/yyyy)", + "Time (hh:mm OR hh:mm:ss) -- NOT Required", + "Required (select) -- validation with (blur) EVENT", + "AlphaDashSpaces + Required + Minimum(5) Characters -- MUST USE: validation-error-to=' '", + "Alphanumeric + Required -- NG-DISABLED", + "Password", + "Password Confirmation", + "Different Password", + "Alphanumeric + Exactly(3) + Required -- debounce(3sec)", + "Date ISO (yyyy-mm-dd) -- minimum condition >= 2001-01-01", + "Date US SHORT (mm/dd/yy) -- between the dates 12/01/99 and 12/31/15", + "Choice IN this list (banana,orange,ice cream)", + "TextArea: Alphanumeric + Minimum(15) + Required", + "Input22 - ngDisabled =>" ]; var errorMessages = [ - 'Must be a positive or negative number. Field is required.', - 'May only contain a positive or negative float value (integer excluded). Needs to be a numeric value, between -0.6 and 99.5. Field is required.', - 'Must have a length of exactly 4 characters. Field is required. Must be a positive integer. Must be following this format "YYWW".', - 'Must be a valid email address. Field is required. Must be at least 6 characters.', - 'Must be a valid URL. Field is required.', - 'Must be a valid IP (IPV4). Field is required.', - 'Must be a valid credit card number. Field is required.', - 'Text must be between 2 and 6 characters in length. Field is required.', - 'Must be a valid date format (yyyy-mm-dd). Field is required.', - 'Must be a valid date format (mm/dd/yyyy) OR (mm-dd-yyyy). Field is required.', - 'Must be a valid time format (hh:mm) OR (hh:mm:ss).', - 'May only contain letters. Change language', - 'Must be at least 5 characters. May only contain letters, numbers, dashes and spaces. Field is required.', - '', - 'May only contain letters. Must be at least 3 characters. Field is required.', - 'Confirmation field does not match specified field "Password". Field is required.', - 'Field must be different from specified field "Password". Field is required.', - 'May only contain letters and spaces. Must have a length of exactly 3 characters. Field is required.', - 'Needs to be a valid date format (yyyy-mm-dd), equal to, or higher than 2001-01-01. Field is required.', - 'Needs to be a valid date format (mm/dd/yy) OR (mm-dd-yy) between 11/28/99 and 12/31/15. Field is required.', - 'Must be a choice inside this list: (banana,orange,ice cream). Field is required.', - 'May only contain letters, numbers, dashes and spaces. Must be at least 15 characters. Field is required.' + "Must be a positive or negative number. Field is required.", + "May only contain a positive or negative float value (integer excluded). Needs to be a numeric value, between -0.6 and 99.5. Field is required.", + "Must have a length of exactly 4 characters. Field is required. Must be a positive integer. Must be following this format YYWW.", + "Must be a valid email address. Field is required. Must be at least 6 characters.", + "Must be a valid URL. Field is required.", + "Must be a valid IP (IPV4). Field is required.", + "Must be a valid credit card number. Field is required.", + "Text must be between 2 and 6 characters in length. Field is required.", + "Must be a valid date format (yyyy-mm-dd). Field is required.", + "Must be a valid date format (mm/dd/yyyy) OR (mm-dd-yyyy). Field is required.", + "Must be a valid time format (hh:mm) OR (hh:mm:ss).", + "May only contain letters. Change language", + "Must be at least 5 characters. May only contain letters, numbers, dashes and spaces. Field is required.", + "", + "May only contain letters. Must be at least 3 characters. Field is required.", + "Confirmation field does not match specified field [Password]. Field is required.", + "Field must be different from specified field [Password]. Field is required.", + "May only contain letters and spaces. Must have a length of exactly 3 characters. Field is required.", + "Needs to be a valid date format (yyyy-mm-dd), equal to, or higher than 2001-01-01. Field is required.", + "Needs to be a valid date format (mm/dd/yy) OR (mm-dd-yy) between 11/28/99 and 12/31/15. Field is required.", + "Must be a choice inside this list: (banana,orange,ice cream). Field is required.", + "May only contain letters, numbers, dashes and spaces. Must be at least 15 characters. Field is required." ]; var validInputTexts = [ - '10', - '2.5', - '1212', - 'g@g.com', - 'http://ww.com', - '192.10.10.10', - '4538121220024545', - 'text', - '2010-01-01', - '02/02/2012', - '10:10', - 'en', - 'qwerty', - '', - 'pass', - 'pass', - 'diff', - 'abc', - '2001-01-01', - '01/01/12', - 'ice cream', - 'This is a great tool' + "10", + "2.5", + "1212", + "g@g.com", + "http://ww.com", + "192.10.10.10", + "4538121220024545", + "text", + "2010-01-01", + "02/02/2012", + "10:10", + "en", + "qwerty", + "", + "pass", + "pass", + "diff", + "abc", + "2001-01-01", + "01/01/12", + "ice cream", + "This is a great tool" ]; var types = ['Directive', 'Service']; @@ -227,8 +227,8 @@ //$('[for=input3]').click(); // click on label to blur away // error should appear on input3 - var elmError2 = $('.validation-input3'); - expect(elmError2.getText()).toEqual(input3error); + var elmError3 = $('.validation-input3'); + expect(elmError3.getText()).toEqual(input3error); }); }); @@ -624,6 +624,10 @@ }); // describe 2forms }); // describe Angular-Validation tests + +/** 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 diff --git a/readme.md b/readme.md index 78c017a..1429d23 100644 --- a/readme.md +++ b/readme.md @@ -1,5 +1,5 @@ #Angular Validation (Directive / Service) -`Version: 1.4.9` +`Version: 1.4.10` ### 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! @@ -58,7 +58,9 @@ The Angular-Validation will create, by itself, the necessary error message. Now Let's not forget the [Validation Summary](https://github.com/ghiscoding/angular-validation/wiki/Validation-Summary) which is also a great and useful way of displaying your errors to the user. -Another awesome feature recently added is the [Remote Validation (AJAX)](https://github.com/ghiscoding/angular-validation/wiki/Remote-Validation-(AJAX)) which is so convenient. +Another awesome feature recently added is the [Wiki - Remote Validation (AJAX)](https://github.com/ghiscoding/angular-validation/wiki/Remote-Validation-(AJAX)) which is useful for backend server validation. + +Again another recently added feature, external 3rd party addon validation (like ngTagsInput or Angular Multi-Select), take a look at the [Wiki - 3rd party addon validation](https://github.com/ghiscoding/angular-validation/wiki/3rd-Party-Addons) ## Angular-Validation Wiki diff --git a/src/validation-common.js b/src/validation-common.js index 403fa95..125738a 100644 --- a/src/validation-common.js +++ b/src/validation-common.js @@ -99,8 +99,9 @@ angular /** Add the error to the validation summary * @param object self * @param string message: error message + * @param bool need to translate: false by default */ - function addToValidationSummary(self, message) { + function addToValidationSummary(self, message, needToTranslate) { if (typeof self === "undefined" || self == null) { return; } @@ -119,6 +120,9 @@ angular if (index >= 0 && message === '') { _validationSummary.splice(index, 1); } else if (message !== '') { + if(!!needToTranslate) { + message = $translate.instant(message); + } var friendlyName = (!!self.attrs && !!self.friendlyName) ? $translate.instant(self.friendlyName) : ''; var errorObj = { field: elmName, friendlyName: friendlyName, message: message, formName: (!!form) ? form.$name : null }; @@ -245,6 +249,7 @@ angular } // defineValidation() /** Return a Form element object by it's name + * @param string element input name * @return array object elements */ function getFormElementByName(elmName) { @@ -252,6 +257,7 @@ angular } /** Return all Form elements + * @param string form name * @return array object elements */ function getFormElements(formName) { @@ -262,8 +268,7 @@ angular } /** Get global options used by all validators - * @param object attrs: global options - * @return object self + * @return object global options */ function getGlobalOptions() { return _globalOptions; @@ -307,7 +312,7 @@ angular } /** Remove objects from FormElement list. - * @param elementName to remove + * @param element input name to remove */ function removeFromFormElementObjectList(elmName) { var index = arrayFindObjectIndex(_formElements, 'fieldName', elmName); // find index of object in our array @@ -317,8 +322,8 @@ angular } /** Remove an element from the $validationSummary array - * @param object validationSummary * @param string elmName: element name + * @param object validationSummary */ function removeFromValidationSummary(elmName, validationSummaryObj) { var self = this; @@ -387,7 +392,7 @@ angular /** in general we will display error message at the next element after our input as * but in some cases user might want to define which DOM id to display error (as validation attribute) * @param string message: error message to display - * @param object attributes + * @param object arguments that could be passed to the function */ function updateErrorMsg(message, attrs) { var self = this; @@ -457,7 +462,7 @@ angular var validator; // to make proper validation, our element value cannot be an undefined variable (we will at minimum make it an empty string) - // For example, in some particular cases "undefined" returns always True on regex.test() which is incorrect especiall on max_len:x + // For example, in some particular cases "undefined" returns always True on regex.test() which is incorrect especially on max_len:x if (typeof strValue === "undefined") { strValue = ''; } @@ -754,6 +759,7 @@ angular * @param object elm * @param object attrs * @param object ctrl + * @param object scope */ function addToFormElementObjectList(elm, attrs, ctrl, scope) { var elmName = (!!attrs.name) ? attrs.name : elm.attr('name'); @@ -773,6 +779,7 @@ angular * @param object self * @param object formElmObj * @param string message: error message + * @param bool is field valid? * @param bool showError */ function addToValidationAndDisplayError(self, formElmObj, message, isFieldValid, showError) { @@ -882,6 +889,7 @@ angular } /** Get the element's parent Angular form (if found) + * @param string: element input name * @param object self * @return object scope form */ @@ -889,8 +897,10 @@ angular // get the parentForm directly by it's formName if it was passed in the global options if(!!_globalOptions && !!_globalOptions.formName) { var parentForm = document.querySelector('[name="'+_globalOptions.formName+'"]'); - parentForm.$name = _globalOptions.formName; // make sure it has a $name, since we use that variable later on - return parentForm; + if(!!parentForm) { + parentForm.$name = _globalOptions.formName; // make sure the parentForm as a $name for later usage + return parentForm; + } } // from the element passed, get his parent form diff --git a/src/validation-directive.js b/src/validation-directive.js index 5831fe7..36ec5e9 100644 --- a/src/validation-directive.js +++ b/src/validation-directive.js @@ -41,9 +41,16 @@ // watch the element for any value change, validate it once that happen var validationWatcher = scope.$watch(function() { - return ctrl.$modelValue; + if(isKeyTypedBadInput()) { + return { badInput: true }; + } + return ctrl.$modelValue; }, function(newValue, oldValue) { - attemptToValidate(newValue); + if(!!newValue && !!newValue.badInput) { + unbindBlurHandler(); + return invalidateBadInputField(); + } + attemptToValidate(newValue); }, true); // save the watcher inside an array in case we want to deregister it when removing a validator @@ -130,6 +137,12 @@ } } + // if a field holds invalid characters which are not numbers inside an `input type="number"`, then it's automatically invalid + // we will still call the `.validate()` function so that it shows also the possible other error messages + if(!!value && !!value.badInput) { + return invalidateBadInputField(); + } + // pre-validate without any events just to pre-fill our validationSummary with all field errors // passing False as the 2nd argument to hide errors from being displayed on screen commonObj.validate(value, false); @@ -148,16 +161,6 @@ ctrl.$setValidity('validation', false); } - // if a field holds invalid characters which are not numbers inside an `input type="number"`, then it's automatically invalid - // we will still call the `.validate()` function so that it shows also the possible other error messages - if((value === "" || typeof value === "undefined") && !!elm.prop('type') && elm.prop('type').toUpperCase() === "NUMBER") { - $timeout.cancel(_timer); - isValid = commonObj.validate(value, true); - ctrl.$setValidity('validation', isValid); - deferred.resolve({ isFieldValid: isValid, formElmObj: formElmObj, value: value }); - return deferred.promise; - } - // select(options) will be validated on the spot if(elm.prop('tagName').toUpperCase() === "SELECT") { isValid = commonObj.validate(value, true); @@ -317,15 +320,30 @@ ctrl.$setValidity('validation', true); // unbind onBlur handler (if found) so that it does not fail on a non-required element that is now dirty & empty - if(typeof blurHandler === "function") { - elm.unbind('blur', blurHandler); - } + unbindBlurHandler(); + } + + /** Invalidate the field that was tagged as bad input, cancel the timer validation, + * display an invalid key error and add it as well to the validation summary. + */ + function invalidateBadInputField() { + $timeout.cancel(_timer); + var formElmObj = commonObj.getFormElementByName(ctrl.$name); + commonObj.updateErrorMsg('INVALID_KEY_CHAR', { isValid: false, translate: true }); + commonObj.addToValidationSummary(formElmObj, 'INVALID_KEY_CHAR', true); + } + + /** Was the characters typed by the user bad input or not? + * @return bool + */ + function isKeyTypedBadInput() { + return (!!elm.prop('validity') && elm.prop('validity').badInput === true); } /** Re-evaluate the element and revalidate it, also re-attach the onBlur event on the element */ function revalidateAndAttachOnBlur() { // Revalidate the input when enabled (without displaying the error) - var value = ctrl.$viewValue || ''; + var value = ctrl.$modelValue || ''; if(!Array.isArray(value)) { ctrl.$setValidity('validation', commonObj.validate(value, false)); } @@ -337,10 +355,15 @@ } // unbind previous handler (if any) not to have double handlers and then re-attach just 1 handler + unbindBlurHandler(); + elm.bind('blur', blurHandler); + } + + /** If found unbind the blur handler */ + function unbindBlurHandler() { if(typeof blurHandler === "function") { elm.unbind('blur', blurHandler); } - elm.bind('blur', blurHandler); } } // link() diff --git a/src/validation-service.js b/src/validation-service.js index 1a8c5ab..9ac5711 100644 --- a/src/validation-service.js +++ b/src/validation-service.js @@ -85,7 +85,7 @@ angular // user could pass his own scope, useful in a case of an isolate scope if (!!self.validationAttrs.isolatedScope) { var tempValidationOptions = scope.$validationOptions || null; // keep global validationOptions - scope = self.validationAttrs.isolatedScope; // rewrite original scope + scope = self.validationAttrs.isolatedScope; // rewrite original scope if(!!tempValidationOptions) { scope.$validationOptions = tempValidationOptions; // reuse the validationOption from original scope } @@ -124,20 +124,32 @@ angular }); // watch the element for any value change, validate it once that happen - var validationWatcher = scope.$watch(attrs.elmName, function (newVal, oldVal) { + var validationWatcher = scope.$watch(function() { + attrs.ctrl = angular.element(attrs.elm).controller('ngModel'); + + if(isKeyTypedBadInput(self, attrs.elmName)) { + return { badInput: true }; + } + return attrs.ctrl.$modelValue; + }, function (newValue, oldValue) { + if(!!newValue && !!newValue.badInput) { + var formElmObj = self.commonObj.getFormElementByName(attrs.elmName); + unbindBlurHandler(self, formElmObj); + return invalidateBadInputField(self, attrs.name); + } // when previous value was set and new value is not, this is most probably an invalid character entered in a type input="text" // we will still call the `.validate()` function so that it shows also the possible other error messages - if(newVal === undefined && oldVal !== undefined) { + if(newValue === undefined && (oldValue !== undefined && !isNaN(oldValue))) { $timeout.cancel(self.timer); self.commonObj.ctrl.$setValidity('validation', self.commonObj.validate('', true)); return; } // from the DOM element, find the Angular controller of this element & add value as well to list of attribtues attrs.ctrl = angular.element(attrs.elm).controller('ngModel'); - attrs.value = newVal; + attrs.value = newValue; self.commonObj.initialize(scope, attrs.elm, attrs, attrs.ctrl); - attemptToValidate(self, newVal); + attemptToValidate(self, newValue); }, true); // $watch() // save the watcher inside an array in case we want to deregister it when removing a validator @@ -205,7 +217,7 @@ angular /** Remove a validator and also any withstanding error message from that element * @param object Angular Form or Scope Object - * @param array/string of element name(s) (name attribute) + * @param object arguments that could be passed to the function * @return object self */ function removeValidator(obj, args) { @@ -243,7 +255,7 @@ angular /** Reset a Form, reset all input element to Pristine, Untouched & remove error dislayed (if any) * @param object Angular Form or Scope Object - * @param bool empty also the element values? (True by default) + * @param object arguments that could be passed to the function */ function resetForm(obj, args) { var self = this; @@ -295,7 +307,7 @@ angular } /** Set and initialize global options used by all validators - * @param object attrs: global options + * @param object: global options * @return object self */ function setGlobalOptions(options) { @@ -314,6 +326,7 @@ angular * and is also customizable through the (typing-limit) for which inactivity this.timer will trigger validation. * @param object self * @param string value: value of the input field + * @param int typingLimit: when user stop typing, in how much time it will start validating */ function attemptToValidate(self, value, typingLimit) { // get the waiting delay time if passed as argument or get it from common Object @@ -322,6 +335,12 @@ angular // get the form element custom object and use it after var formElmObj = self.commonObj.getFormElementByName(self.commonObj.ctrl.$name); + // if a field holds invalid characters which are not numbers inside an `input type="number"`, then it's automatically invalid + // we will still call the `.validate()` function so that it shows also the possible other error messages + if(!!value && !!value.badInput) { + return invalidateBadInputField(self, attrs.name); + } + // pre-validate without any events just to pre-fill our validationSummary with all field errors // passing false as 2nd argument for not showing any errors on screen self.commonObj.validate(value, false); @@ -370,6 +389,7 @@ angular /** Cancel current validation test and blank any leftover error message * @param object obj + * @param object formElmObj: form element object */ function cancelValidation(obj, formElmObj) { // get the form element custom object and use it after @@ -383,10 +403,29 @@ angular obj.commonObj.updateErrorMsg('', { isValid: true, obj: formElmObj }); // unbind onBlur handler (if found) so that it does not fail on a non-required element that is now dirty & empty - if(typeof _blurHandler === "function") { - var elm = (!!formElmObj && !!formElmObj.elm) ? formElmObj.elm : obj.commonObj.elm; - elm.unbind('blur', _blurHandler); - } + unbindBlurHandler(obj, formElmObj); + } + + /** Invalidate the field that was tagged as bad input, cancel the timer validation, + * display an invalid key error and add it as well to the validation summary. + * @param object self + * @param string: element input name + */ + function invalidateBadInputField(self, elmName) { + $timeout.cancel(self.timer); + var formElmObj = self.commonObj.getFormElementByName(elmName); + self.commonObj.updateErrorMsg('INVALID_KEY_CHAR', { isValid: false, translate: true, obj: formElmObj }); + self.commonObj.addToValidationSummary(formElmObj, 'INVALID_KEY_CHAR', true); + } + + /** Was the characters typed by the user bad input or not? + * @param object self + * @param string: element input name + * @return bool + */ + function isKeyTypedBadInput(self, elmName) { + var formElmObj = self.commonObj.getFormElementByName(elmName); + return (!!formElmObj && !!formElmObj.elm.prop('validity') && formElmObj.elm.prop('validity').badInput === true); } /** Remove a watcher and any withstanding error message from the element @@ -428,6 +467,24 @@ angular self.commonObj.removeFromValidationSummary(formElmObj.fieldName, validationSummary); } + /** If found unbind the blur hanlder + * @param object self + * @param object formElmObj: form element object + */ + function unbindBlurHandler(obj, formElmObj) { + formElmObj.isValidationCancelled = true; + if(typeof _blurHandler === "function") { + var elm = (!!formElmObj && !!formElmObj.elm) ? formElmObj.elm : obj.commonObj.elm; + elm.unbind('blur', _blurHandler); + } + } + + /** Watch for an disabled/ngDisabled attribute change, + * if it become disabled then skip validation else it becomes enable then we need to revalidate it + * @param object self + * @param object scope + * @param object attributes + */ function watchNgDisabled(self, scope, attrs) { scope.$watch(function() { return (typeof attrs.elm.attr('ng-disabled') === "undefined") ? null : scope.$eval(attrs.elm.attr('ng-disabled')); //this will evaluate attribute value `{{}}`` diff --git a/templates/testing2Forms.html b/templates/testing2Forms.html index f3f6746..727025e 100644 --- a/templates/testing2Forms.html +++ b/templates/testing2Forms.html @@ -12,7 +12,7 @@

Directive - 2 Forms

 |  diff --git a/templates/testingFormDirective.html b/templates/testingFormDirective.html index 4f5752d..442ce0a 100644 --- a/templates/testingFormDirective.html +++ b/templates/testingFormDirective.html @@ -13,7 +13,7 @@

Directive

 |  diff --git a/templates/testingFormNgRepeat.html b/templates/testingFormNgRepeat.html index 6079500..913e4c0 100644 --- a/templates/testingFormNgRepeat.html +++ b/templates/testingFormNgRepeat.html @@ -2,7 +2,7 @@

Directive - ngRepeat

diff --git a/templates/testingFormService.html b/templates/testingFormService.html index 4be5277..4704a0b 100644 --- a/templates/testingFormService.html +++ b/templates/testingFormService.html @@ -14,7 +14,7 @@

Service

 |  diff --git a/vendors/angular-translate/angular-translate-loader-static-files.min.js b/vendors/angular-translate/angular-translate-loader-static-files.min.js index c09cbf3..e51283e 100644 --- a/vendors/angular-translate/angular-translate-loader-static-files.min.js +++ b/vendors/angular-translate/angular-translate-loader-static-files.min.js @@ -1,6 +1,6 @@ /*! - * angular-translate - v2.6.1 - 2015-03-01 - * http://github.com/angular-translate/angular-translate - * Copyright (c) 2015 ; Licensed MIT + * angular-translate - v2.8.1 - 2015-10-01 + * + * Copyright (c) 2015 The angular-translate team, Pascal Precht; Licensed MIT */ -angular.module("pascalprecht.translate").factory("$translateStaticFilesLoader",["$q","$http",function(a,b){return function(c){if(!(c&&(angular.isArray(c.files)||angular.isString(c.prefix)&&angular.isString(c.suffix))))throw new Error("Couldn't load static files, no files and prefix or suffix specified!");c.files||(c.files=[{prefix:c.prefix,suffix:c.suffix}]);for(var d=function(d){if(!d||!angular.isString(d.prefix)||!angular.isString(d.suffix))throw new Error("Couldn't load static file, no prefix or suffix specified!");var e=a.defer();return b(angular.extend({url:[d.prefix,c.key,d.suffix].join(""),method:"GET",params:""},c.$http)).success(function(a){e.resolve(a)}).error(function(){e.reject(c.key)}),e.promise},e=a.defer(),f=[],g=c.files.length,h=0;g>h;h++)f.push(d({prefix:c.files[h].prefix,key:c.key,suffix:c.files[h].suffix}));return a.all(f).then(function(a){for(var b=a.length,c={},d=0;b>d;d++)for(var f in a[d])c[f]=a[d][f];e.resolve(c)},function(a){e.reject(a)}),e.promise}}]); \ No newline at end of file +!function(a,b){"function"==typeof define&&define.amd?define([],function(){return b()}):"object"==typeof exports?module.exports=b():b()}(this,function(){function a(a,b){"use strict";return function(c){if(!(c&&(angular.isArray(c.files)||angular.isString(c.prefix)&&angular.isString(c.suffix))))throw new Error("Couldn't load static files, no files and prefix or suffix specified!");c.files||(c.files=[{prefix:c.prefix,suffix:c.suffix}]);for(var d=function(d){if(!d||!angular.isString(d.prefix)||!angular.isString(d.suffix))throw new Error("Couldn't load static file, no prefix or suffix specified!");return b(angular.extend({url:[d.prefix,c.key,d.suffix].join(""),method:"GET",params:""},c.$http)).then(function(a){return a.data},function(){return a.reject(c.key)})},e=a.defer(),f=[],g=c.files.length,h=0;g>h;h++)f.push(d({prefix:c.files[h].prefix,key:c.key,suffix:c.files[h].suffix}));return a.all(f).then(function(a){for(var b=a.length,c={},d=0;b>d;d++)for(var f in a[d])c[f]=a[d][f];e.resolve(c)},function(a){e.reject(a)}),e.promise}}return angular.module("pascalprecht.translate").factory("$translateStaticFilesLoader",a),a.$inject=["$q","$http"],a.displayName="$translateStaticFilesLoader","pascalprecht.translate"}); \ No newline at end of file diff --git a/vendors/angular-translate/angular-translate.min.js b/vendors/angular-translate/angular-translate.min.js index cf4c127..6db6b84 100644 --- a/vendors/angular-translate/angular-translate.min.js +++ b/vendors/angular-translate/angular-translate.min.js @@ -1,6 +1,6 @@ /*! - * angular-translate - v2.6.1 - 2015-03-01 - * http://github.com/angular-translate/angular-translate - * Copyright (c) 2015 ; Licensed MIT + * angular-translate - v2.8.1 - 2015-10-01 + * + * Copyright (c) 2015 The angular-translate team, Pascal Precht; Licensed MIT */ -angular.module("pascalprecht.translate",["ng"]).run(["$translate",function(a){var b=a.storageKey(),c=a.storage(),d=function(){var d=a.preferredLanguage();angular.isString(d)?a.use(d):c.put(b,a.use())};c?c.get(b)?a.use(c.get(b))["catch"](d):d():angular.isString(a.preferredLanguage())&&a.use(a.preferredLanguage())}]),angular.module("pascalprecht.translate").provider("$translate",["$STORAGE_KEY","$windowProvider",function(a,b){var c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r={},s=[],t=a,u=[],v=!1,w="translate-cloak",x=!1,y=".",z=0,A="2.6.1",B=function(){var a,c,d=b.$get().navigator,e=["language","browserLanguage","systemLanguage","userLanguage"];if(angular.isArray(d.languages))for(a=0;ac;c++)if(a[c]===b)return c;return-1},E=function(){return this.replace(/^\s+|\s+$/g,"")},F=function(a){for(var b=[],c=angular.lowercase(a),e=0,f=s.length;f>e;e++)b.push(angular.lowercase(s[e]));if(D(b,c)>-1)return a;if(d){var g;for(var h in d){var i=!1,j=Object.prototype.hasOwnProperty.call(d,h)&&angular.lowercase(h)===angular.lowercase(a);if("*"===h.slice(-1)&&(i=h.slice(0,-1)===a.slice(0,h.length-1)),(j||i)&&(g=d[h],D(b,angular.lowercase(g))>-1))return g}}var k=a.split("_");return k.length>1&&D(b,angular.lowercase(k[0]))>-1?k[0]:a},G=function(a,b){if(!a&&!b)return r;if(a&&!b){if(angular.isString(a))return r[a]}else angular.isObject(r[a])||(r[a]={}),angular.extend(r[a],H(b));return this};this.translations=G,this.cloakClassName=function(a){return a?(w=a,this):w};var H=function(a,b,c,d){var e,f,g,h;b||(b=[]),c||(c={});for(e in a)Object.prototype.hasOwnProperty.call(a,e)&&(h=a[e],angular.isObject(h)?H(h,b.concat(e),c,e):(f=b.length?""+b.join(y)+y+e:e,b.length&&e===d&&(g=""+b.join(y),c[g]="@:"+f),c[f]=h));return c};this.addInterpolation=function(a){return u.push(a),this},this.useMessageFormatInterpolation=function(){return this.useInterpolation("$translateMessageFormatInterpolation")},this.useInterpolation=function(a){return l=a,this},this.useSanitizeValueStrategy=function(a){return v=a,this},this.preferredLanguage=function(a){return I(a),this};var I=function(a){return a&&(c=a),c};this.translationNotFoundIndicator=function(a){return this.translationNotFoundIndicatorLeft(a),this.translationNotFoundIndicatorRight(a),this},this.translationNotFoundIndicatorLeft=function(a){return a?(o=a,this):o},this.translationNotFoundIndicatorRight=function(a){return a?(p=a,this):p},this.fallbackLanguage=function(a){return J(a),this};var J=function(a){return a?(angular.isString(a)?(f=!0,e=[a]):angular.isArray(a)&&(f=!1,e=a),angular.isString(c)&&D(e,c)<0&&e.push(c),this):f?e[0]:e};this.use=function(a){if(a){if(!r[a]&&!m)throw new Error("$translateProvider couldn't find translationTable for langKey: '"+a+"'");return g=a,this}return g};var K=function(a){return a?void(t=a):j?j+t:t};this.storageKey=K,this.useUrlLoader=function(a,b){return this.useLoader("$translateUrlLoader",angular.extend({url:a},b))},this.useStaticFilesLoader=function(a){return this.useLoader("$translateStaticFilesLoader",a)},this.useLoader=function(a,b){return m=a,n=b||{},this},this.useLocalStorage=function(){return this.useStorage("$translateLocalStorage")},this.useCookieStorage=function(){return this.useStorage("$translateCookieStorage")},this.useStorage=function(a){return i=a,this},this.storagePrefix=function(a){return a?(j=a,this):a},this.useMissingTranslationHandlerLog=function(){return this.useMissingTranslationHandler("$translateMissingTranslationHandlerLog")},this.useMissingTranslationHandler=function(a){return k=a,this},this.usePostCompiling=function(a){return x=!!a,this},this.determinePreferredLanguage=function(a){var b=a&&angular.isFunction(a)?a():C();return c=s.length?F(b):b,this},this.registerAvailableLanguageKeys=function(a,b){return a?(s=a,b&&(d=b),this):s},this.useLoaderCache=function(a){return a===!1?q=void 0:a===!0?q=!0:"undefined"==typeof a?q="$translationCache":a&&(q=a),this},this.directivePriority=function(a){return void 0===a?z:(z=a,this)},this.$get=["$log","$injector","$rootScope","$q",function(a,b,d,j){var s,y,B,C=b.get(l||"$translateDefaultInterpolation"),L=!1,M={},N={},O=function(a,b,d,f){if(angular.isArray(a)){var h=function(a){for(var c={},e=[],g=function(a){var e=j.defer(),g=function(b){c[a]=b,e.resolve([a,b])};return O(a,b,d,f).then(g,g),e.promise},h=0,i=a.length;i>h;h++)e.push(g(a[h]));return j.all(e).then(function(){return c})};return h(a)}var k=j.defer();a&&(a=E.apply(a));var l=function(){var a=c?N[c]:N[g];if(y=0,i&&!a){var b=s.get(t);if(a=N[b],e&&e.length){var d=D(e,b);y=0===d?1:0,D(e,c)<0&&e.push(c)}}return a}();return l?l.then(function(){$(a,b,d,f).then(k.resolve,k.reject)},k.reject):$(a,b,d,f).then(k.resolve,k.reject),k.promise},P=function(a){return o&&(a=[o,a].join(" ")),p&&(a=[a,p].join(" ")),a},Q=function(a){g=a,d.$emit("$translateChangeSuccess",{language:a}),i&&s.put(O.storageKey(),g),C.setLocale(g),angular.forEach(M,function(a,b){M[b].setLocale(g)}),d.$emit("$translateChangeEnd",{language:a})},R=function(a){if(!a)throw"No language key specified for loading.";var c=j.defer();d.$emit("$translateLoadingStart",{language:a}),L=!0;var e=q;"string"==typeof e&&(e=b.get(e));var f=angular.extend({},n,{key:a,$http:angular.extend({},{cache:e},n.$http)});return b.get(m)(f).then(function(b){var e={};d.$emit("$translateLoadingSuccess",{language:a}),angular.isArray(b)?angular.forEach(b,function(a){angular.extend(e,H(a))}):angular.extend(e,H(b)),L=!1,c.resolve({key:a,table:e}),d.$emit("$translateLoadingEnd",{language:a})},function(a){d.$emit("$translateLoadingError",{language:a}),c.reject(a),d.$emit("$translateLoadingEnd",{language:a})}),c.promise};if(i&&(s=b.get(i),!s.get||!s.put))throw new Error("Couldn't use storage '"+i+"', missing get() or put() method!");angular.isFunction(C.useSanitizeValueStrategy)&&C.useSanitizeValueStrategy(v),u.length&&angular.forEach(u,function(a){var d=b.get(a);d.setLocale(c||g),angular.isFunction(d.useSanitizeValueStrategy)&&d.useSanitizeValueStrategy(v),M[d.getInterpolationIdentifier()]=d});var S=function(a){var b=j.defer();return Object.prototype.hasOwnProperty.call(r,a)?b.resolve(r[a]):N[a]?N[a].then(function(a){G(a.key,a.table),b.resolve(a.table)},b.reject):b.reject(),b.promise},T=function(a,b,c,d){var e=j.defer();return S(a).then(function(f){if(Object.prototype.hasOwnProperty.call(f,b)){d.setLocale(a);var h=f[b];"@:"===h.substr(0,2)?T(a,h.substr(2),c,d).then(e.resolve,e.reject):e.resolve(d.interpolate(f[b],c)),d.setLocale(g)}else e.reject()},e.reject),e.promise},U=function(a,b,c,d){var e,f=r[a];if(f&&Object.prototype.hasOwnProperty.call(f,b)){if(d.setLocale(a),e=d.interpolate(f[b],c),"@:"===e.substr(0,2))return U(a,e.substr(2),c,d);d.setLocale(g)}return e},V=function(a){if(k){var c=b.get(k)(a,g);return void 0!==c?c:a}return a},W=function(a,b,c,d,f){var g=j.defer();if(a0?B:y,a,b,c,d)},Z=function(a,b,c){return X(B>0?B:y,a,b,c)},$=function(a,b,c,d){var f=j.defer(),h=g?r[g]:r,i=c?M[c]:C;if(h&&Object.prototype.hasOwnProperty.call(h,a)){var l=h[a];"@:"===l.substr(0,2)?O(l.substr(2),b,c,d).then(f.resolve,f.reject):f.resolve(i.interpolate(l,b))}else{var m;k&&!L&&(m=V(a)),g&&e&&e.length?Y(a,b,i,d).then(function(a){f.resolve(a)},function(a){f.reject(P(a))}):k&&!L&&m?f.resolve(d?d:m):d?f.resolve(d):f.reject(P(a))}return f.promise},_=function(a,b,c){var d,f=g?r[g]:r,h=C;if(M&&Object.prototype.hasOwnProperty.call(M,c)&&(h=M[c]),f&&Object.prototype.hasOwnProperty.call(f,a)){var i=f[a];d="@:"===i.substr(0,2)?_(i.substr(2),b,c):h.interpolate(i,b)}else{var j;k&&!L&&(j=V(a)),g&&e&&e.length?(y=0,d=Z(a,b,h)):d=k&&!L&&j?j:P(a)}return d};if(O.preferredLanguage=function(a){return a&&I(a),c},O.cloakClassName=function(){return w},O.fallbackLanguage=function(a){if(void 0!==a&&null!==a){if(J(a),m&&e&&e.length)for(var b=0,c=e.length;c>b;b++)N[e[b]]||(N[e[b]]=R(e[b]));O.use(O.use())}return f?e[0]:e},O.useFallbackLanguage=function(a){if(void 0!==a&&null!==a)if(a){var b=D(e,a);b>-1&&(B=b)}else B=0},O.proposedLanguage=function(){return h},O.storage=function(){return s},O.use=function(a){if(!a)return g;var b=j.defer();d.$emit("$translateChangeStart",{language:a});var c=F(a);return c&&(a=c),r[a]||!m||N[a]?(b.resolve(a),Q(a)):(h=a,N[a]=R(a).then(function(c){return G(c.key,c.table),b.resolve(c.key),Q(c.key),h===a&&(h=void 0),c},function(a){h===a&&(h=void 0),d.$emit("$translateChangeError",{language:a}),b.reject(a),d.$emit("$translateChangeEnd",{language:a})})),b.promise},O.storageKey=function(){return K()},O.isPostCompilingEnabled=function(){return x},O.refresh=function(a){function b(){f.resolve(),d.$emit("$translateRefreshEnd",{language:a})}function c(){f.reject(),d.$emit("$translateRefreshEnd",{language:a})}if(!m)throw new Error("Couldn't refresh translation table, no loader registered!");var f=j.defer();if(d.$emit("$translateRefreshStart",{language:a}),a)r[a]?R(a).then(function(c){G(c.key,c.table),a===g&&Q(g),b()},c):c();else{var h=[],i={};if(e&&e.length)for(var k=0,l=e.length;l>k;k++)h.push(R(e[k])),i[e[k]]=!0;g&&!i[g]&&h.push(R(g)),j.all(h).then(function(a){angular.forEach(a,function(a){r[a.key]&&delete r[a.key],G(a.key,a.table)}),g&&Q(g),b()})}return f.promise},O.instant=function(a,b,d){if(null===a||angular.isUndefined(a))return a;if(angular.isArray(a)){for(var f={},h=0,i=a.length;i>h;h++)f[a[h]]=O.instant(a[h],b,d);return f}if(angular.isString(a)&&a.length<1)return a;a&&(a=E.apply(a));var j,l=[];c&&l.push(c),g&&l.push(g),e&&e.length&&(l=l.concat(e));for(var m=0,n=l.length;n>m;m++){var q=l[m];if(r[q]&&("undefined"!=typeof r[q][a]?j=_(a,b,d):(o||p)&&(j=P(a))),"undefined"!=typeof j)break}return j||""===j||(j=C.interpolate(a,b),k&&!L&&(j=V(a))),j},O.versionInfo=function(){return A},O.loaderCache=function(){return q},O.directivePriority=function(){return z},m&&(angular.equals(r,{})&&O.use(O.use()),e&&e.length))for(var ab=function(a){return G(a.key,a.table),d.$emit("$translateChangeEnd",{language:a.key}),a},bb=0,cb=e.length;cb>bb;bb++)N[e[bb]]=R(e[bb]).then(ab);return O}]}]),angular.module("pascalprecht.translate").factory("$translateDefaultInterpolation",["$interpolate",function(a){var b,c={},d="default",e=null,f={escaped:function(a){var b={};for(var c in a)Object.prototype.hasOwnProperty.call(a,c)&&(b[c]=angular.isNumber(a[c])?a[c]:angular.element("
").text(a[c]).html());return b}},g=function(a){var b;return b=angular.isFunction(f[e])?f[e](a):a};return c.setLocale=function(a){b=a},c.getInterpolationIdentifier=function(){return d},c.useSanitizeValueStrategy=function(a){return e=a,this},c.interpolate=function(b,c){return e&&(c=g(c)),a(b)(c||{})},c}]),angular.module("pascalprecht.translate").constant("$STORAGE_KEY","NG_TRANSLATE_LANG_KEY"),angular.module("pascalprecht.translate").directive("translate",["$translate","$q","$interpolate","$compile","$parse","$rootScope",function(a,b,c,d,e,f){var g=function(){return this.replace(/^\s+|\s+$/g,"")};return{restrict:"AE",scope:!0,priority:a.directivePriority(),compile:function(b,h){var i=h.translateValues?h.translateValues:void 0,j=h.translateInterpolation?h.translateInterpolation:void 0,k=b[0].outerHTML.match(/translate-value-+/i),l="^(.*)("+c.startSymbol()+".*"+c.endSymbol()+")(.*)",m="^(.*)"+c.startSymbol()+"(.*)"+c.endSymbol()+"(.*)";return function(b,n,o){b.interpolateParams={},b.preText="",b.postText="";var p={},q=function(a){if(angular.isFunction(q._unwatchOld)&&(q._unwatchOld(),q._unwatchOld=void 0),angular.equals(a,"")||!angular.isDefined(a)){var d=g.apply(n.text()).match(l);if(angular.isArray(d)){b.preText=d[1],b.postText=d[3],p.translate=c(d[2])(b.$parent);var e=n.text().match(m);angular.isArray(e)&&e[2]&&e[2].length&&(q._unwatchOld=b.$watch(e[2],function(a){p.translate=a,w()}))}else p.translate=n.text().replace(/^\s+|\s+$/g,"")}else p.translate=a;w()},r=function(a){o.$observe(a,function(b){p[a]=b,w()})},s=!0;o.$observe("translate",function(a){"undefined"==typeof a?q(""):""===a&&s||(p.translate=a,w()),s=!1});for(var t in o)o.hasOwnProperty(t)&&"translateAttr"===t.substr(0,13)&&r(t);if(o.$observe("translateDefault",function(a){b.defaultText=a}),i&&o.$observe("translateValues",function(a){a&&b.$parent.$watch(function(){angular.extend(b.interpolateParams,e(a)(b.$parent))})}),k){var u=function(a){o.$observe(a,function(c){var d=angular.lowercase(a.substr(14,1))+a.substr(15);b.interpolateParams[d]=c})};for(var v in o)Object.prototype.hasOwnProperty.call(o,v)&&"translateValue"===v.substr(0,14)&&"translateValues"!==v&&u(v)}var w=function(){for(var a in p)p.hasOwnProperty(a)&&x(a,p[a],b,b.interpolateParams,b.defaultText)},x=function(b,c,d,e,f){c?a(c,e,j,f).then(function(a){y(a,d,!0,b)},function(a){y(a,d,!1,b)}):y(c,d,!1,b)},y=function(b,c,e,f){if("translate"===f){e||"undefined"==typeof c.defaultText||(b=c.defaultText),n.html(c.preText+b+c.postText);var g=a.isPostCompilingEnabled(),i="undefined"!=typeof h.translateCompile,j=i&&"false"!==h.translateCompile;(g&&!i||j)&&d(n.contents())(c)}else{e||"undefined"==typeof c.defaultText||(b=c.defaultText);var k=o.$attr[f].substr(15);n.attr(k,b)}};b.$watch("interpolateParams",w,!0);var z=f.$on("$translateChangeSuccess",w);n.text().length&&q(""),w(),b.$on("$destroy",z)}}}}]),angular.module("pascalprecht.translate").directive("translateCloak",["$rootScope","$translate",function(a,b){return{compile:function(c){var d=function(){c.addClass(b.cloakClassName())},e=function(){c.removeClass(b.cloakClassName())},f=a.$on("$translateChangeEnd",function(){e(),f(),f=null});return d(),function(a,c,f){f.translateCloak&&f.translateCloak.length&&f.$observe("translateCloak",function(a){b(a).then(e,d)})}}}}]),angular.module("pascalprecht.translate").filter("translate",["$parse","$translate",function(a,b){var c=function(c,d,e){return angular.isObject(d)||(d=a(d)(this)),b.instant(c,d,e)};return c.$stateful=!0,c}]); \ No newline at end of file +!function(a,b){"function"==typeof define&&define.amd?define([],function(){return b()}):"object"==typeof exports?module.exports=b():b()}(this,function(){function a(a){"use strict";var b=a.storageKey(),c=a.storage(),d=function(){var d=a.preferredLanguage();angular.isString(d)?a.use(d):c.put(b,a.use())};d.displayName="fallbackFromIncorrectStorageValue",c?c.get(b)?a.use(c.get(b))["catch"](d):d():angular.isString(a.preferredLanguage())&&a.use(a.preferredLanguage())}function b(){"use strict";var a,b,c=null,d=!1,e=!1;b={sanitize:function(a,b){return"text"===b&&(a=g(a)),a},escape:function(a,b){return"text"===b&&(a=f(a)),a},sanitizeParameters:function(a,b){return"params"===b&&(a=h(a,g)),a},escapeParameters:function(a,b){return"params"===b&&(a=h(a,f)),a}},b.escaped=b.escapeParameters,this.addStrategy=function(a,c){return b[a]=c,this},this.removeStrategy=function(a){return delete b[a],this},this.useStrategy=function(a){return d=!0,c=a,this},this.$get=["$injector","$log",function(f,g){var h={},i=function(a,c,d){return angular.forEach(d,function(d){if(angular.isFunction(d))a=d(a,c);else if(angular.isFunction(b[d]))a=b[d](a,c);else{if(!angular.isString(b[d]))throw new Error("pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: '"+d+"'");if(!h[b[d]])try{h[b[d]]=f.get(b[d])}catch(e){throw h[b[d]]=function(){},new Error("pascalprecht.translate.$translateSanitization: Unknown sanitization strategy: '"+d+"'")}a=h[b[d]](a,c)}}),a},j=function(){d||e||(g.warn("pascalprecht.translate.$translateSanitization: No sanitization strategy has been configured. This can have serious security implications. See http://angular-translate.github.io/docs/#/guide/19_security for details."),e=!0)};return f.has("$sanitize")&&(a=f.get("$sanitize")),{useStrategy:function(a){return function(b){a.useStrategy(b)}}(this),sanitize:function(a,b,d){if(c||j(),arguments.length<3&&(d=c),!d)return a;var e=angular.isArray(d)?d:[d];return i(a,b,e)}}}];var f=function(a){var b=angular.element("
");return b.text(a),b.html()},g=function(b){if(!a)throw new Error("pascalprecht.translate.$translateSanitization: Error cannot find $sanitize service. Either include the ngSanitize module (https://docs.angularjs.org/api/ngSanitize) or use a sanitization strategy which does not depend on $sanitize, such as 'escape'.");return a(b)},h=function(a,b){if(angular.isObject(a)){var c=angular.isArray(a)?[]:{};return angular.forEach(a,function(a,d){c[d]=h(a,b)}),c}return angular.isNumber(a)?a:b(a)}}function c(a,b,c,d){"use strict";var e,f,g,h,i,j,k,l,m,n,o,p,q,r,s,t={},u=[],v=a,w=[],x="translate-cloak",y=!1,z=!1,A=".",B=!1,C=0,D=!0,E="default",F={"default":function(a){return(a||"").split("-").join("_")},java:function(a){var b=(a||"").split("-").join("_"),c=b.split("_");return c.length>1?c[0].toLowerCase()+"_"+c[1].toUpperCase():b},bcp47:function(a){var b=(a||"").split("_").join("-"),c=b.split("-");return c.length>1?c[0].toLowerCase()+"-"+c[1].toUpperCase():b}},G="2.8.1",H=function(){if(angular.isFunction(d.getLocale))return d.getLocale();var a,c,e=b.$get().navigator,f=["language","browserLanguage","systemLanguage","userLanguage"];if(angular.isArray(e.languages))for(a=0;ac;c++)if(a[c]===b)return c;return-1},K=function(){return this.toString().replace(/^\s+|\s+$/g,"")},L=function(a){for(var b=[],c=angular.lowercase(a),d=0,e=u.length;e>d;d++)b.push(angular.lowercase(u[d]));if(J(b,c)>-1)return a;if(f){var g;for(var h in f){var i=!1,j=Object.prototype.hasOwnProperty.call(f,h)&&angular.lowercase(h)===angular.lowercase(a);if("*"===h.slice(-1)&&(i=h.slice(0,-1)===a.slice(0,h.length-1)),(j||i)&&(g=f[h],J(b,angular.lowercase(g))>-1))return g}}if(a){var k=a.split("_");if(k.length>1&&J(b,angular.lowercase(k[0]))>-1)return k[0]}return a},M=function(a,b){if(!a&&!b)return t;if(a&&!b){if(angular.isString(a))return t[a]}else angular.isObject(t[a])||(t[a]={}),angular.extend(t[a],N(b));return this};this.translations=M,this.cloakClassName=function(a){return a?(x=a,this):x},this.nestedObjectDelimeter=function(a){return a?(A=a,this):A};var N=function(a,b,c,d){var e,f,g,h;b||(b=[]),c||(c={});for(e in a)Object.prototype.hasOwnProperty.call(a,e)&&(h=a[e],angular.isObject(h)?N(h,b.concat(e),c,e):(f=b.length?""+b.join(A)+A+e:e,b.length&&e===d&&(g=""+b.join(A),c[g]="@:"+f),c[f]=h));return c};N.displayName="flatObject",this.addInterpolation=function(a){return w.push(a),this},this.useMessageFormatInterpolation=function(){return this.useInterpolation("$translateMessageFormatInterpolation")},this.useInterpolation=function(a){return n=a,this},this.useSanitizeValueStrategy=function(a){return c.useStrategy(a),this},this.preferredLanguage=function(a){return a?(O(a),this):e};var O=function(a){return a&&(e=a),e};this.translationNotFoundIndicator=function(a){return this.translationNotFoundIndicatorLeft(a),this.translationNotFoundIndicatorRight(a),this},this.translationNotFoundIndicatorLeft=function(a){return a?(q=a,this):q},this.translationNotFoundIndicatorRight=function(a){return a?(r=a,this):r},this.fallbackLanguage=function(a){return P(a),this};var P=function(a){return a?(angular.isString(a)?(h=!0,g=[a]):angular.isArray(a)&&(h=!1,g=a),angular.isString(e)&&J(g,e)<0&&g.push(e),this):h?g[0]:g};this.use=function(a){if(a){if(!t[a]&&!o)throw new Error("$translateProvider couldn't find translationTable for langKey: '"+a+"'");return i=a,this}return i};var Q=function(a){return a?(v=a,this):l?l+v:v};this.storageKey=Q,this.useUrlLoader=function(a,b){return this.useLoader("$translateUrlLoader",angular.extend({url:a},b))},this.useStaticFilesLoader=function(a){return this.useLoader("$translateStaticFilesLoader",a)},this.useLoader=function(a,b){return o=a,p=b||{},this},this.useLocalStorage=function(){return this.useStorage("$translateLocalStorage")},this.useCookieStorage=function(){return this.useStorage("$translateCookieStorage")},this.useStorage=function(a){return k=a,this},this.storagePrefix=function(a){return a?(l=a,this):a},this.useMissingTranslationHandlerLog=function(){return this.useMissingTranslationHandler("$translateMissingTranslationHandlerLog")},this.useMissingTranslationHandler=function(a){return m=a,this},this.usePostCompiling=function(a){return y=!!a,this},this.forceAsyncReload=function(a){return z=!!a,this},this.uniformLanguageTag=function(a){return a?angular.isString(a)&&(a={standard:a}):a={},E=a.standard,this},this.determinePreferredLanguage=function(a){var b=a&&angular.isFunction(a)?a():I();return e=u.length?L(b):b,this},this.registerAvailableLanguageKeys=function(a,b){return a?(u=a,b&&(f=b),this):u},this.useLoaderCache=function(a){return a===!1?s=void 0:a===!0?s=!0:"undefined"==typeof a?s="$translationCache":a&&(s=a),this},this.directivePriority=function(a){return void 0===a?C:(C=a,this)},this.statefulFilter=function(a){return void 0===a?D:(D=a,this)},this.$get=["$log","$injector","$rootScope","$q",function(a,b,c,d){var f,l,u,E=b.get(n||"$translateDefaultInterpolation"),F=!1,H={},I={},R=function(a,b,c,h){if(angular.isArray(a)){var j=function(a){for(var e={},f=[],g=function(a){var f=d.defer(),g=function(b){e[a]=b,f.resolve([a,b])};return R(a,b,c,h).then(g,g),f.promise},i=0,j=a.length;j>i;i++)f.push(g(a[i]));return d.all(f).then(function(){return e})};return j(a)}var m=d.defer();a&&(a=K.apply(a));var n=function(){var a=e?I[e]:I[i];if(l=0,k&&!a){var b=f.get(v);if(a=I[b],g&&g.length){var c=J(g,b);l=0===c?1:0,J(g,e)<0&&g.push(e)}}return a}();if(n){var o=function(){ca(a,b,c,h).then(m.resolve,m.reject)};o.displayName="promiseResolved",n["finally"](o,m.reject)}else ca(a,b,c,h).then(m.resolve,m.reject);return m.promise},S=function(a){return q&&(a=[q,a].join(" ")),r&&(a=[a,r].join(" ")),a},T=function(a){i=a,k&&f.put(R.storageKey(),i),c.$emit("$translateChangeSuccess",{language:a}),E.setLocale(i);var b=function(a,b){H[b].setLocale(i)};b.displayName="eachInterpolatorLocaleSetter",angular.forEach(H,b),c.$emit("$translateChangeEnd",{language:a})},U=function(a){if(!a)throw"No language key specified for loading.";var e=d.defer();c.$emit("$translateLoadingStart",{language:a}),F=!0;var f=s;"string"==typeof f&&(f=b.get(f));var g=angular.extend({},p,{key:a,$http:angular.extend({},{cache:f},p.$http)}),h=function(b){var d={};c.$emit("$translateLoadingSuccess",{language:a}),angular.isArray(b)?angular.forEach(b,function(a){angular.extend(d,N(a))}):angular.extend(d,N(b)),F=!1,e.resolve({key:a,table:d}),c.$emit("$translateLoadingEnd",{language:a})};h.displayName="onLoaderSuccess";var i=function(a){c.$emit("$translateLoadingError",{language:a}),e.reject(a),c.$emit("$translateLoadingEnd",{language:a})};return i.displayName="onLoaderError",b.get(o)(g).then(h,i),e.promise};if(k&&(f=b.get(k),!f.get||!f.put))throw new Error("Couldn't use storage '"+k+"', missing get() or put() method!");if(w.length){var V=function(a){var c=b.get(a);c.setLocale(e||i),H[c.getInterpolationIdentifier()]=c};V.displayName="interpolationFactoryAdder",angular.forEach(w,V)}var W=function(a){var b=d.defer();if(Object.prototype.hasOwnProperty.call(t,a))b.resolve(t[a]);else if(I[a]){var c=function(a){M(a.key,a.table),b.resolve(a.table)};c.displayName="translationTableResolver",I[a].then(c,b.reject)}else b.reject();return b.promise},X=function(a,b,c,e){var f=d.defer(),g=function(d){if(Object.prototype.hasOwnProperty.call(d,b)){e.setLocale(a);var g=d[b];"@:"===g.substr(0,2)?X(a,g.substr(2),c,e).then(f.resolve,f.reject):f.resolve(e.interpolate(d[b],c)),e.setLocale(i)}else f.reject()};return g.displayName="fallbackTranslationResolver",W(a).then(g,f.reject),f.promise},Y=function(a,b,c,d){var e,f=t[a];if(f&&Object.prototype.hasOwnProperty.call(f,b)){if(d.setLocale(a),e=d.interpolate(f[b],c),"@:"===e.substr(0,2))return Y(a,e.substr(2),c,d);d.setLocale(i)}return e},Z=function(a,c){if(m){var d=b.get(m)(a,i,c);return void 0!==d?d:a}return a},$=function(a,b,c,e,f){var h=d.defer();if(a0?u:l,a,b,c,d)},ba=function(a,b,c){return _(u>0?u:l,a,b,c)},ca=function(a,b,c,e){var f=d.defer(),h=i?t[i]:t,j=c?H[c]:E;if(h&&Object.prototype.hasOwnProperty.call(h,a)){var k=h[a];"@:"===k.substr(0,2)?R(k.substr(2),b,c,e).then(f.resolve,f.reject):f.resolve(j.interpolate(k,b))}else{var l;m&&!F&&(l=Z(a,b)),i&&g&&g.length?aa(a,b,j,e).then(function(a){f.resolve(a)},function(a){f.reject(S(a))}):m&&!F&&l?e?f.resolve(e):f.resolve(l):e?f.resolve(e):f.reject(S(a))}return f.promise},da=function(a,b,c){var d,e=i?t[i]:t,f=E;if(H&&Object.prototype.hasOwnProperty.call(H,c)&&(f=H[c]),e&&Object.prototype.hasOwnProperty.call(e,a)){var h=e[a];d="@:"===h.substr(0,2)?da(h.substr(2),b,c):f.interpolate(h,b)}else{var j;m&&!F&&(j=Z(a,b)),i&&g&&g.length?(l=0,d=ba(a,b,f)):d=m&&!F&&j?j:S(a)}return d},ea=function(a){j===a&&(j=void 0),I[a]=void 0};R.preferredLanguage=function(a){return a&&O(a),e},R.cloakClassName=function(){return x},R.nestedObjectDelimeter=function(){return A},R.fallbackLanguage=function(a){if(void 0!==a&&null!==a){if(P(a),o&&g&&g.length)for(var b=0,c=g.length;c>b;b++)I[g[b]]||(I[g[b]]=U(g[b]));R.use(R.use())}return h?g[0]:g},R.useFallbackLanguage=function(a){if(void 0!==a&&null!==a)if(a){var b=J(g,a);b>-1&&(u=b)}else u=0},R.proposedLanguage=function(){return j},R.storage=function(){return f},R.use=function(a){if(!a)return i;var b=d.defer();c.$emit("$translateChangeStart",{language:a});var e=L(a);return e&&(a=e),!z&&t[a]||!o||I[a]?j===a&&I[a]?I[a].then(function(a){return b.resolve(a.key),a},function(a){return b.reject(a),d.reject(a)}):(b.resolve(a),T(a)):(j=a,I[a]=U(a).then(function(c){return M(c.key,c.table),b.resolve(c.key),j===a&&T(c.key),c},function(a){return c.$emit("$translateChangeError",{language:a}),b.reject(a),c.$emit("$translateChangeEnd",{language:a}),d.reject(a)}),I[a]["finally"](function(){ea(a)})),b.promise},R.storageKey=function(){return Q()},R.isPostCompilingEnabled=function(){return y},R.isForceAsyncReloadEnabled=function(){return z},R.refresh=function(a){function b(){f.resolve(),c.$emit("$translateRefreshEnd",{language:a})}function e(){f.reject(),c.$emit("$translateRefreshEnd",{language:a})}if(!o)throw new Error("Couldn't refresh translation table, no loader registered!");var f=d.defer();if(c.$emit("$translateRefreshStart",{language:a}),a)if(t[a]){var h=function(c){M(c.key,c.table),a===i&&T(i),b()};h.displayName="refreshPostProcessor",U(a).then(h,e)}else e();else{var j=[],k={};if(g&&g.length)for(var l=0,m=g.length;m>l;l++)j.push(U(g[l])),k[g[l]]=!0;i&&!k[i]&&j.push(U(i));var n=function(a){t={},angular.forEach(a,function(a){M(a.key,a.table)}),i&&T(i),b()};n.displayName="refreshPostProcessor",d.all(j).then(n,e)}return f.promise},R.instant=function(a,b,c){if(null===a||angular.isUndefined(a))return a;if(angular.isArray(a)){for(var d={},f=0,h=a.length;h>f;f++)d[a[f]]=R.instant(a[f],b,c);return d}if(angular.isString(a)&&a.length<1)return a;a&&(a=K.apply(a));var j,k=[];e&&k.push(e),i&&k.push(i),g&&g.length&&(k=k.concat(g));for(var l=0,n=k.length;n>l;l++){var o=k[l];if(t[o]&&("undefined"!=typeof t[o][a]?j=da(a,b,c):(q||r)&&(j=S(a))),"undefined"!=typeof j)break}return j||""===j||(j=E.interpolate(a,b),m&&!F&&(j=Z(a,b))),j},R.versionInfo=function(){return G},R.loaderCache=function(){return s},R.directivePriority=function(){return C},R.statefulFilter=function(){return D},R.isReady=function(){return B};var fa=d.defer();fa.promise.then(function(){B=!0}),R.onReady=function(a){var b=d.defer();return angular.isFunction(a)&&b.promise.then(a),B?b.resolve():fa.promise.then(b.resolve),b.promise};var ga=c.$on("$translateReady",function(){fa.resolve(),ga(),ga=null}),ha=c.$on("$translateChangeEnd",function(){fa.resolve(),ha(),ha=null});if(o){if(angular.equals(t,{})&&R.use()&&R.use(R.use()),g&&g.length)for(var ia=function(a){return M(a.key,a.table),c.$emit("$translateChangeEnd",{language:a.key}),a},ja=0,ka=g.length;ka>ja;ja++){var la=g[ja];(z||!t[la])&&(I[la]=U(la).then(ia))}}else c.$emit("$translateReady",{language:R.use()});return R}]}function d(a,b){"use strict";var c,d={},e="default";return d.setLocale=function(a){c=a},d.getInterpolationIdentifier=function(){return e},d.useSanitizeValueStrategy=function(a){return b.useStrategy(a),this},d.interpolate=function(c,d){d=d||{},d=b.sanitize(d,"params");var e=a(c)(d);return e=b.sanitize(e,"text")},d}function e(a,b,c,d,e,g){"use strict";var h=function(){return this.toString().replace(/^\s+|\s+$/g,"")};return{restrict:"AE",scope:!0,priority:a.directivePriority(),compile:function(b,i){var j=i.translateValues?i.translateValues:void 0,k=i.translateInterpolation?i.translateInterpolation:void 0,l=b[0].outerHTML.match(/translate-value-+/i),m="^(.*)("+c.startSymbol()+".*"+c.endSymbol()+")(.*)",n="^(.*)"+c.startSymbol()+"(.*)"+c.endSymbol()+"(.*)";return function(b,o,p){b.interpolateParams={},b.preText="",b.postText="",b.translateNamespace=f(b);var q={},r=function(a,c,d){if(c.translateValues&&angular.extend(a,e(c.translateValues)(b.$parent)),l)for(var f in d)if(Object.prototype.hasOwnProperty.call(c,f)&&"translateValue"===f.substr(0,14)&&"translateValues"!==f){var g=angular.lowercase(f.substr(14,1))+f.substr(15);a[g]=d[f]}},s=function(a){if(angular.isFunction(s._unwatchOld)&&(s._unwatchOld(),s._unwatchOld=void 0),angular.equals(a,"")||!angular.isDefined(a)){var d=h.apply(o.text()),e=d.match(m);if(angular.isArray(e)){b.preText=e[1],b.postText=e[3],q.translate=c(e[2])(b.$parent);var f=d.match(n);angular.isArray(f)&&f[2]&&f[2].length&&(s._unwatchOld=b.$watch(f[2],function(a){q.translate=a,y()}))}else q.translate=d}else q.translate=a;y()},t=function(a){p.$observe(a,function(b){q[a]=b,y()})};r(b.interpolateParams,p,i);var u=!0;p.$observe("translate",function(a){"undefined"==typeof a?s(""):""===a&&u||(q.translate=a,y()),u=!1});for(var v in p)p.hasOwnProperty(v)&&"translateAttr"===v.substr(0,13)&&t(v);if(p.$observe("translateDefault",function(a){b.defaultText=a}),j&&p.$observe("translateValues",function(a){a&&b.$parent.$watch(function(){angular.extend(b.interpolateParams,e(a)(b.$parent))})}),l){var w=function(a){p.$observe(a,function(c){var d=angular.lowercase(a.substr(14,1))+a.substr(15);b.interpolateParams[d]=c})};for(var x in p)Object.prototype.hasOwnProperty.call(p,x)&&"translateValue"===x.substr(0,14)&&"translateValues"!==x&&w(x)}var y=function(){for(var a in q)q.hasOwnProperty(a)&&void 0!==q[a]&&z(a,q[a],b,b.interpolateParams,b.defaultText,b.translateNamespace)},z=function(b,c,d,e,f,g){c?(g&&"."===c.charAt(0)&&(c=g+c),a(c,e,k,f).then(function(a){A(a,d,!0,b)},function(a){A(a,d,!1,b)})):A(c,d,!1,b)},A=function(b,c,e,f){if("translate"===f){e||"undefined"==typeof c.defaultText||(b=c.defaultText),o.empty().append(c.preText+b+c.postText);var g=a.isPostCompilingEnabled(),h="undefined"!=typeof i.translateCompile,j=h&&"false"!==i.translateCompile;(g&&!h||j)&&d(o.contents())(c)}else{e||"undefined"==typeof c.defaultText||(b=c.defaultText);var k=p.$attr[f];"data-"===k.substr(0,5)&&(k=k.substr(5)),k=k.substr(15),o.attr(k,b)}};(j||l||p.translateDefault)&&b.$watch("interpolateParams",y,!0);var B=g.$on("$translateChangeSuccess",y);o.text().length?s(p.translate?p.translate:""):p.translate&&s(p.translate),y(),b.$on("$destroy",B)}}}}function f(a){"use strict";return a.translateNamespace?a.translateNamespace:a.$parent?f(a.$parent):void 0}function g(a){"use strict";return{compile:function(b){var c=function(){b.addClass(a.cloakClassName())},d=function(){b.removeClass(a.cloakClassName())};return a.onReady(function(){d()}),c(),function(b,e,f){f.translateCloak&&f.translateCloak.length&&f.$observe("translateCloak",function(b){a(b).then(d,c)})}}}}function h(){"use strict";return{restrict:"A",scope:!0,compile:function(){return{pre:function(a,b,c){a.translateNamespace=f(a),a.translateNamespace&&"."===c.translateNamespace.charAt(0)?a.translateNamespace+=c.translateNamespace:a.translateNamespace=c.translateNamespace}}}}}function f(a){"use strict";return a.translateNamespace?a.translateNamespace:a.$parent?f(a.$parent):void 0}function i(a,b){"use strict";var c=function(c,d,e){return angular.isObject(d)||(d=a(d)(this)),b.instant(c,d,e)};return b.statefulFilter()&&(c.$stateful=!0),c}function j(a){"use strict";return a("translations")}return angular.module("pascalprecht.translate",["ng"]).run(a),a.$inject=["$translate"],a.displayName="runTranslate",angular.module("pascalprecht.translate").provider("$translateSanitization",b),angular.module("pascalprecht.translate").constant("pascalprechtTranslateOverrider",{}).provider("$translate",c),c.$inject=["$STORAGE_KEY","$windowProvider","$translateSanitizationProvider","pascalprechtTranslateOverrider"],c.displayName="displayName",angular.module("pascalprecht.translate").factory("$translateDefaultInterpolation",d),d.$inject=["$interpolate","$translateSanitization"],d.displayName="$translateDefaultInterpolation",angular.module("pascalprecht.translate").constant("$STORAGE_KEY","NG_TRANSLATE_LANG_KEY"),angular.module("pascalprecht.translate").directive("translate",e),e.$inject=["$translate","$q","$interpolate","$compile","$parse","$rootScope"],e.displayName="translateDirective",angular.module("pascalprecht.translate").directive("translateCloak",g),g.$inject=["$translate"],g.displayName="translateCloakDirective",angular.module("pascalprecht.translate").directive("translateNamespace",h),h.displayName="translateNamespaceDirective",angular.module("pascalprecht.translate").filter("translate",i),i.$inject=["$parse","$translate"],i.displayName="translateFilterFactory",angular.module("pascalprecht.translate").factory("$translationCache",j),j.$inject=["$cacheFactory"],j.displayName="$translationCache","pascalprecht.translate"}); \ No newline at end of file