diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 8ac556a..95cdba5 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -14,6 +14,7 @@ npm install **Before coding** Boot the Environment ``` grunt dev +grunt check // check the code quality ``` **Start coding** diff --git a/Gruntfile.js b/Gruntfile.js index 69ac7c5..94262f2 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -1,4 +1,4 @@ -module.exports = function (grunt) { +module.exports = function(grunt) { // Variable var ROOT_PATH = '.'; @@ -10,14 +10,12 @@ module.exports = function (grunt) { pkg: grunt.file.readJSON('package.json'), clean: { dist: { - files: [ - { - dot: true, - src: [ - 'dist' - ] - } - ] + files: [{ + dot: true, + src: [ + 'dist' + ] + }] } }, copy: { @@ -44,6 +42,13 @@ module.exports = function (grunt) { } } }, + jsbeautifier: { + files: ['*.js', 'src/**/*.js'], + options: {} + }, + jshint: { + all: ['*.js', 'src/**/*.js'] + }, browserSync: { dev: { bsFiles: { @@ -80,10 +85,11 @@ module.exports = function (grunt) { } }); - require( "load-grunt-tasks" )( grunt ); + require("load-grunt-tasks")(grunt); // Register Task grunt.registerTask('dev', ['browserSync', 'watch']); - grunt.registerTask('build', ['clean', 'concat', 'uglify']) + grunt.registerTask('build', ['clean', 'concat', 'uglify']); + grunt.registerTask('check', ['jshint', 'jsbeautifier']); // use this before commit -}; \ No newline at end of file +}; diff --git a/dist/angular-validation-rule.js b/dist/angular-validation-rule.js index 80d62ee..3b960f7 100644 --- a/dist/angular-validation-rule.js +++ b/dist/angular-validation-rule.js @@ -1,37 +1,39 @@ -(function () { +(function() { angular.module('validation.rule', ['validation']) - .config(['$validationProvider', function ($validationProvider) { + .config(['$validationProvider', + function($validationProvider) { - var expression = { - required: function (value) { - return !!value; - }, - url: /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/, - email: /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/, - number: /^\d+$/ - }; + var expression = { + required: function(value) { + return !!value; + }, + url: /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/, + email: /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/, + number: /^\d+$/ + }; - var defaultMsg = { - required: { - error: 'This should be Required!!', - success: 'It\'s Required' - }, - url: { - error: 'This should be Url', - success: 'It\'s Url' - }, - email: { - error: 'This should be Email', - success: 'It\'s Email' - }, - number: { - error: 'This should be Number', - success: 'It\'s Number' - } - }; + var defaultMsg = { + required: { + error: 'This should be Required!!', + success: 'It\'s Required' + }, + url: { + error: 'This should be Url', + success: 'It\'s Url' + }, + email: { + error: 'This should be Email', + success: 'It\'s Email' + }, + number: { + error: 'This should be Number', + success: 'It\'s Number' + } + }; - $validationProvider.setExpression(expression).setDefaultMsg(defaultMsg); + $validationProvider.setExpression(expression).setDefaultMsg(defaultMsg); - }]); + } + ]); -}).call(this); \ No newline at end of file +}).call(this); diff --git a/dist/angular-validation.js b/dist/angular-validation.js index ee6eb51..9ba6aa0 100644 --- a/dist/angular-validation.js +++ b/dist/angular-validation.js @@ -1,9 +1,10 @@ -(function () { +(function() { angular.module('validation', ['validation.provider', 'validation.directive']); }).call(this); -(function () { + +(function() { angular.module('validation.provider', []) - .provider('$validation', function () { + .provider('$validation', function() { var $injector, @@ -18,7 +19,7 @@ * Setup the provider * @param injector */ - var setup = function (injector) { + var setup = function(injector) { $injector = injector; $scope = $injector.get('$rootScope'); $http = $injector.get('$http'); @@ -46,7 +47,7 @@ * @param obj * @returns {*} */ - this.setExpression = function (obj) { + this.setExpression = function(obj) { angular.extend(expression, obj); return _this; }; @@ -57,7 +58,7 @@ * @param exprs * @returns {*} */ - this.getExpression = function (exprs) { + this.getExpression = function(exprs) { return expression[exprs]; }; @@ -67,7 +68,7 @@ * @param obj * @returns {*} */ - this.setDefaultMsg = function (obj) { + this.setDefaultMsg = function(obj) { angular.extend(defaultMsg, obj); return _this; }; @@ -78,7 +79,7 @@ * @param msg * @returns {*} */ - this.getDefaultMsg = function (msg) { + this.getDefaultMsg = function(msg) { return defaultMsg[msg]; }; @@ -88,7 +89,7 @@ * @param func * @returns {*} */ - this.setErrorHTML = function (func) { + this.setErrorHTML = function(func) { if (func.constructor !== Function) { return; } @@ -104,7 +105,7 @@ * @param message * @returns {string} */ - this.getErrorHTML = function (message) { + this.getErrorHTML = function(message) { return '

' + message + '

'; }; @@ -114,7 +115,7 @@ * @param func * @returns {*} */ - this.setSuccessHTML = function (func) { + this.setSuccessHTML = function(func) { if (func.constructor !== Function) { return; } @@ -130,7 +131,7 @@ * @param message * @returns {string} */ - this.getSuccessHTML = function (message) { + this.getSuccessHTML = function(message) { return '

' + message + '

'; }; @@ -159,7 +160,7 @@ * @param form * @returns {boolean} */ - this.checkValid = function (form) { + this.checkValid = function(form) { if (form.$valid === undefined) { return false; } @@ -172,7 +173,7 @@ * @param form * @returns {promise|*} */ - this.validate = function (form) { + this.validate = function(form) { var deferred = $q.defer(), idx = 0; @@ -190,32 +191,31 @@ $scope.$broadcast(form[k].$name + 'submit-' + form[k].validationId, idx++); } } else { - for (var k in form) { // whole scope - if (form[k] && form[k].hasOwnProperty('$dirty')) { - $scope.$broadcast(k + 'submit-' + form[k].validationId, idx++); + for (var i in form) { // whole scope + if (form[i] && form[i].hasOwnProperty('$dirty')) { + $scope.$broadcast(i + 'submit-' + form[i].validationId, idx++); } } } - deferred.promise.success = function (fn) { - deferred.promise.then(function (value) { + deferred.promise.success = function(fn) { + deferred.promise.then(function(value) { fn(value); }); return deferred.promise; }; - deferred.promise.error = function (fn) { - deferred.promise.then(null, function (value) { + deferred.promise.error = function(fn) { + deferred.promise.then(null, function(value) { fn(value); }); return deferred.promise; }; - $timeout(function () { + $timeout(function() { if (_this.checkValid(form)) { deferred.resolve('success'); - } - else { + } else { deferred.reject('error'); } }); @@ -228,7 +228,7 @@ * reset the specific form * @param form */ - this.reset = function (form) { + this.reset = function(form) { if (form === undefined) { console.error('This is not a regular Form name scope'); @@ -242,9 +242,9 @@ $scope.$broadcast(form[k].$name + 'reset-' + form[k].validationId); } } else { - for (var k in form) { - if (form[k].hasOwnProperty('$dirty')) { - $scope.$broadcast(k + 'reset-' + form[k].validationId); + for (var i in form) { + if (form[i].hasOwnProperty('$dirty')) { + $scope.$broadcast(i + 'reset-' + form[i].validationId); } } } @@ -255,326 +255,330 @@ * $get * @returns {{setErrorHTML: *, getErrorHTML: Function, setSuccessHTML: *, getSuccessHTML: Function, setExpression: *, getExpression: Function, setDefaultMsg: *, getDefaultMsg: Function, checkValid: Function, validate: Function, reset: Function}} */ - this.$get = ['$injector', function ($injector) { - setup($injector); - return { - setErrorHTML: this.setErrorHTML, - getErrorHTML: this.getErrorHTML, - setSuccessHTML: this.setSuccessHTML, - getSuccessHTML: this.getSuccessHTML, - setExpression: this.setExpression, - getExpression: this.getExpression, - setDefaultMsg: this.setDefaultMsg, - getDefaultMsg: this.getDefaultMsg, - showSuccessMessage: this.showSuccessMessage, - showErrorMessage: this.showErrorMessage, - checkValid: this.checkValid, - validate: this.validate, - reset: this.reset - }; - }]; + this.$get = ['$injector', + function($injector) { + setup($injector); + return { + setErrorHTML: this.setErrorHTML, + getErrorHTML: this.getErrorHTML, + setSuccessHTML: this.setSuccessHTML, + getSuccessHTML: this.getSuccessHTML, + setExpression: this.setExpression, + getExpression: this.getExpression, + setDefaultMsg: this.setDefaultMsg, + getDefaultMsg: this.getDefaultMsg, + showSuccessMessage: this.showSuccessMessage, + showErrorMessage: this.showErrorMessage, + checkValid: this.checkValid, + validate: this.validate, + reset: this.reset + }; + } + ]; }); }).call(this); -(function () { +(function() { angular.module('validation.directive', ['validation.provider']) - .directive('validator', ['$injector', function ($injector) { - - var $validationProvider = $injector.get('$validation'), - $q = $injector.get('$q'), - $timeout = $injector.get('$timeout'); - - /** - * Do this function if validation valid - * @param element - * @param validMessage - * @param validation - * @param callback - * @param ctrl - * @returns {} - */ - var validFunc = function (element, validMessage, validation, callback, ctrl) { - if ($validationProvider.showSuccessMessage) { - element.next().html($validationProvider.getSuccessHTML(validMessage || $validationProvider.getDefaultMsg(validation).success)); - } else { - element.next().html(''); - } - ctrl.$setValidity(ctrl.$name, true); - if (callback) callback(); - - return true; - }; - - - /** - * Do this function if validation invalid - * @param element - * @param validMessage - * @param validation - * @param callback - * @param ctrl - * @returns {} - */ - var invalidFunc = function (element, validMessage, validation, callback, ctrl) { - if ($validationProvider.showErrorMessage) { - element.next().html($validationProvider.getErrorHTML(validMessage || $validationProvider.getDefaultMsg(validation).error)); - } else { - element.next().html(''); - } - ctrl.$setValidity(ctrl.$name, false); - if (callback) callback(); + .directive('validator', ['$injector', + function($injector) { + + var $validationProvider = $injector.get('$validation'), + $q = $injector.get('$q'), + $timeout = $injector.get('$timeout'); + + /** + * Do this function if validation valid + * @param element + * @param validMessage + * @param validation + * @param callback + * @param ctrl + * @returns {} + */ + var validFunc = function(element, validMessage, validation, callback, ctrl) { + if ($validationProvider.showSuccessMessage) { + element.next().html($validationProvider.getSuccessHTML(validMessage || $validationProvider.getDefaultMsg(validation).success)); + } else { + element.next().html(''); + } + ctrl.$setValidity(ctrl.$name, true); + if (callback) callback(); - return false; - }; + return true; + }; - /** - * If var is true, focus element when validate end - * @type {boolean} - ***private variable - */ - var isFocusElement = false; + /** + * Do this function if validation invalid + * @param element + * @param validMessage + * @param validation + * @param callback + * @param ctrl + * @returns {} + */ + var invalidFunc = function(element, validMessage, validation, callback, ctrl) { + if ($validationProvider.showErrorMessage) { + element.next().html($validationProvider.getErrorHTML(validMessage || $validationProvider.getDefaultMsg(validation).error)); + } else { + element.next().html(''); + } + ctrl.$setValidity(ctrl.$name, false); + if (callback) callback(); + return false; + }; - /** - * Check Validation with Function or RegExp - * @param scope - * @param element - * @param attrs - * @param ctrl - * @param validation - * @param value - * @returns {} - */ - var checkValidation = function (scope, element, attrs, ctrl, validation, value) { - var successMessage = validation + 'SuccessMessage', - errorMessage = validation + 'ErrorMessage', - expressionType = $validationProvider.getExpression(validation).constructor, - valid = { - success: function () { - return validFunc(element, attrs[successMessage], validation, scope.validCallback, ctrl); - }, - error: function () { - return invalidFunc(element, attrs[errorMessage], validation, scope.invalidCallback, ctrl); - } - }; - // Check with Function - if (expressionType === Function) { - return $q.all([$validationProvider.getExpression(validation)(value, scope, element, attrs)]) - .then(function (data) { - if (data && data.length > 0 && data[0]) { - return valid.success(); - } else { - return valid.error(); + /** + * If var is true, focus element when validate end + * @type {boolean} + ***private variable + */ + var isFocusElement = false; + + + /** + * Check Validation with Function or RegExp + * @param scope + * @param element + * @param attrs + * @param ctrl + * @param validation + * @param value + * @returns {} + */ + var checkValidation = function(scope, element, attrs, ctrl, validation, value) { + var successMessage = validation + 'SuccessMessage', + errorMessage = validation + 'ErrorMessage', + expressionType = $validationProvider.getExpression(validation).constructor, + valid = { + success: function() { + return validFunc(element, attrs[successMessage], validation, scope.validCallback, ctrl); + }, + error: function() { + return invalidFunc(element, attrs[errorMessage], validation, scope.invalidCallback, ctrl); } - }, function () { - return valid.error(); - }); - } - // Check with RegExp - else if (expressionType === RegExp) { - return $validationProvider.getExpression(validation).test(value) ? valid.success() : valid.error(); - } else { - return valid.error(); - } - }; - - - /** - * generate unique guid - */ - var s4 = function () { - return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); - }; - var guid = function () { - return (s4() + s4() + s4() + s4()); - }; + }; + + // Check with Function + if (expressionType === Function) { + return $q.all([$validationProvider.getExpression(validation)(value, scope, element, attrs)]) + .then(function(data) { + if (data && data.length > 0 && data[0]) { + return valid.success(); + } else { + return valid.error(); + } + }, function() { + return valid.error(); + }); + } + // Check with RegExp + else if (expressionType === RegExp) { + return $validationProvider.getExpression(validation).test(value) ? valid.success() : valid.error(); + } else { + return valid.error(); + } + }; - return { - restrict: 'A', - require: 'ngModel', - scope: { - model: '=ngModel', - initialValidity: '=initialValidity', - validCallback: '&', - invalidCallback: '&' - }, - link: function (scope, element, attrs, ctrl) { - - /** - * watch - * @type {watch} - * - * Use to collect scope.$watch method - * - * use watch() to destroy the $watch method - */ - var watch = function () {}; - - /** - * validator - * @type {*|Array} - * - * Convert user input String to Array - */ - var validator = attrs.validator.split(','); - - /** - * guid use - */ - var uid = ctrl.validationId = guid(); - - /** - * Valid/Invalid Message - */ - element.after(''); - - /** - * Set initial validity to false if no boolean value is transmitted - */ - var initialValidity = false; - if (typeof scope.initialValidity === 'boolean') { - initialValidity = scope.initialValidity; - } + /** + * generate unique guid + */ + var s4 = function() { + return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); + }; + var guid = function() { + return (s4() + s4() + s4() + s4()); + }; - /** - * Set custom initial validity - * Usage: - */ - ctrl.$setValidity(ctrl.$name, initialValidity); - /** - * Reset the validation for specific form - */ - scope.$on(ctrl.$name + 'reset-' + uid, function () { + return { + restrict: 'A', + require: 'ngModel', + scope: { + model: '=ngModel', + initialValidity: '=initialValidity', + validCallback: '&', + invalidCallback: '&' + }, + link: function(scope, element, attrs, ctrl) { /** - * clear scope.$watch here - * when reset status - * clear the $watch method to prevent - * $watch again while reset the form + * watch + * @type {watch} + * + * Use to collect scope.$watch method + * + * use watch() to destroy the $watch method */ - watch(); - - isFocusElement = false; - ctrl.$setViewValue(''); - ctrl.$setPristine(); - ctrl.$setValidity(ctrl.$name, false); - ctrl.$render(); - element.next().html(''); - }); - - /** - * Check Every validator - */ - validator.forEach(function (validation) { + var watch = function() {}; /** - * Click submit form, check the validity when submit + * validator + * @type {*|Array} + * + * Convert user input String to Array */ - scope.$on(ctrl.$name + 'submit-' + uid, function (event, index) { - var value = element[0].value, - isValid = false; - - if (index == 0) { - isFocusElement = false; - } - - isValid = checkValidation(scope, element, attrs, ctrl, validation, value); + var validator = attrs.validator.split(','); - if (attrs.validMethod === 'submit') { - watch(); // clear previous scope.$watch - watch = scope.$watch('model', function (value, oldValue) { + /** + * guid use + */ + var uid = ctrl.validationId = guid(); - // don't watch when init - if (value === oldValue) { - return; - } + /** + * Valid/Invalid Message + */ + element.after(''); - // scope.$watch will translate '' to undefined - // undefined/null will pass the required submit /^.+/ - // cause some error in this validation - if (value === undefined || value === null) { - value = ''; - } + /** + * Set initial validity to false if no boolean value is transmitted + */ + var initialValidity = false; + if (typeof scope.initialValidity === 'boolean') { + initialValidity = scope.initialValidity; + } - isValid = checkValidation(scope, element, attrs, ctrl, validation, value); - }); + /** + * Set custom initial validity + * Usage: + */ + ctrl.$setValidity(ctrl.$name, initialValidity); - } + /** + * Reset the validation for specific form + */ + scope.$on(ctrl.$name + 'reset-' + uid, function() { - // Focus first input element when submit error #11 - if (!isFocusElement && !isValid) { - isFocusElement = true; - element[0].focus(); - } + /** + * clear scope.$watch here + * when reset status + * clear the $watch method to prevent + * $watch again while reset the form + */ + watch(); + + isFocusElement = false; + ctrl.$setViewValue(''); + ctrl.$setPristine(); + ctrl.$setValidity(ctrl.$name, false); + ctrl.$render(); + element.next().html(''); }); /** - * Validate blur method + * Check Every validator */ - if (attrs.validMethod === 'blur') { - element.bind('blur', function () { - var value = element[0].value; - scope.$apply(function() { - checkValidation(scope, element, attrs, ctrl, validation, value); - }); + validator.forEach(function(validation) { + + /** + * Click submit form, check the validity when submit + */ + scope.$on(ctrl.$name + 'submit-' + uid, function(event, index) { + var value = element[0].value, + isValid = false; + + if (index === 0) { + isFocusElement = false; + } + + isValid = checkValidation(scope, element, attrs, ctrl, validation, value); + + if (attrs.validMethod === 'submit') { + watch(); // clear previous scope.$watch + watch = scope.$watch('model', function(value, oldValue) { + + // don't watch when init + if (value === oldValue) { + return; + } + + // scope.$watch will translate '' to undefined + // undefined/null will pass the required submit /^.+/ + // cause some error in this validation + if (value === undefined || value === null) { + value = ''; + } + + isValid = checkValidation(scope, element, attrs, ctrl, validation, value); + }); + + } + + // Focus first input element when submit error #11 + if (!isFocusElement && !isValid) { + isFocusElement = true; + element[0].focus(); + } }); - return; - } + /** + * Validate blur method + */ + if (attrs.validMethod === 'blur') { + element.bind('blur', function() { + var value = element[0].value; + scope.$apply(function() { + checkValidation(scope, element, attrs, ctrl, validation, value); + }); + }); - /** - * Validate submit & submit-only method - */ - if (attrs.validMethod === 'submit' || attrs.validMethod === 'submit-only') { - return; - } + return; + } - /** - * Validate watch method - * This is the default method - */ - scope.$watch('model', function (value) { /** - * dirty, pristine, viewValue control here + * Validate submit & submit-only method */ - if (ctrl.$pristine && ctrl.$viewValue) { - // has value when initial - ctrl.$setViewValue(ctrl.$viewValue); - } else if (ctrl.$pristine) { - // Don't validate form when the input is clean(pristine) - element.next().html(''); + if (attrs.validMethod === 'submit' || attrs.validMethod === 'submit-only') { return; } - checkValidation(scope, element, attrs, ctrl, validation, value); - }); - }); + /** + * Validate watch method + * This is the default method + */ + scope.$watch('model', function(value) { + /** + * dirty, pristine, viewValue control here + */ + if (ctrl.$pristine && ctrl.$viewValue) { + // has value when initial + ctrl.$setViewValue(ctrl.$viewValue); + } else if (ctrl.$pristine) { + // Don't validate form when the input is clean(pristine) + element.next().html(''); + return; + } + checkValidation(scope, element, attrs, ctrl, validation, value); + }); - $timeout(function () { - /** - * Don't showup the validation Message - */ - attrs.$observe('noValidationMessage', function (value) { - var el = element.next(); - if (value == "true" || value == true) { - el.css('display', 'none'); - } else if (value == "false" || value == false) { - el.css('display', 'block'); - } else { - } }); - }); - } - }; - }]) + $timeout(function() { + /** + * Don't showup the validation Message + */ + attrs.$observe('noValidationMessage', function(value) { + var el = element.next(); + if (value == "true" || value === true) { + el.css('display', 'none'); + } else if (value == "false" || value === false) { + el.css('display', 'block'); + } else {} + }); + }); - .directive('validationSubmit', ['$injector', function ($injector) { + } + }; + } + ]) + + .directive('validationSubmit', ['$injector', + function($injector) { var $validationProvider = $injector.get('$validation'), $timeout = $injector.get('$timeout'), @@ -586,24 +590,26 @@ link: function postLink(scope, element, attrs) { var form = $parse(attrs.validationSubmit)(scope); - $timeout(function () { + $timeout(function() { // Disable ng-click event propagation element.off('click'); - element.on('click', function (e) { + element.on('click', function(e) { e.preventDefault(); $validationProvider.validate(form) - .success(function () { + .success(function() { $parse(attrs.ngClick)(scope); }); }); }); } - } - }]) + }; + } + ]) - .directive('validationReset', ['$injector', function ($injector) { + .directive('validationReset', ['$injector', + function($injector) { var $validationProvider = $injector.get('$validation'), $timeout = $injector.get('$timeout'), @@ -613,15 +619,16 @@ link: function postLink(scope, element, attrs) { var form = $parse(attrs.validationReset)(scope); - $timeout(function () { - element.on('click', function (e) { + $timeout(function() { + element.on('click', function(e) { e.preventDefault(); $validationProvider.reset(form); }); }); } - } - }]); + }; + } + ]); }).call(this); diff --git a/dist/angular-validation.min.js b/dist/angular-validation.min.js index ac125f7..43e2ecd 100644 --- a/dist/angular-validation.min.js +++ b/dist/angular-validation.min.js @@ -1 +1 @@ -(function(){angular.module("validation",["validation.provider","validation.directive"])}).call(this),function(){angular.module("validation.provider",[]).provider("$validation",function(){var a,b,c,d,e,f=this,g=function(f){a=f,b=a.get("$rootScope"),c=a.get("$http"),d=a.get("$q"),e=a.get("$timeout")},h={},i={};this.setExpression=function(a){return angular.extend(h,a),f},this.getExpression=function(a){return h[a]},this.setDefaultMsg=function(a){return angular.extend(i,a),f},this.getDefaultMsg=function(a){return i[a]},this.setErrorHTML=function(a){return a.constructor===Function?(f.getErrorHTML=a,f):void 0},this.getErrorHTML=function(a){return'

'+a+"

"},this.setSuccessHTML=function(a){return a.constructor===Function?(f.getSuccessHTML=a,f):void 0},this.getSuccessHTML=function(a){return'

'+a+"

"},this.showSuccessMessage=!0,this.showErrorMessage=!0,this.checkValid=function(a){return void 0===a.$valid?!1:a&&a.$valid===!0},this.validate=function(a){var c=d.defer(),g=0;if(void 0===a)return console.error("This is not a regular Form name scope"),c.reject("This is not a regular Form name scope"),c.promise;if(a.validationId)b.$broadcast(a.$name+"submit-"+a.validationId,g++);else if(a.constructor===Array)for(var h in a)b.$broadcast(a[h].$name+"submit-"+a[h].validationId,g++);else for(var h in a)a[h]&&a[h].hasOwnProperty("$dirty")&&b.$broadcast(h+"submit-"+a[h].validationId,g++);return c.promise.success=function(a){return c.promise.then(function(b){a(b)}),c.promise},c.promise.error=function(a){return c.promise.then(null,function(b){a(b)}),c.promise},e(function(){f.checkValid(a)?c.resolve("success"):c.reject("error")}),c.promise},this.reset=function(a){if(void 0===a)return void console.error("This is not a regular Form name scope");if(a.validationId)b.$broadcast(a.$name+"reset-"+a.validationId);else if(a.constructor===Array)for(var c in a)b.$broadcast(a[c].$name+"reset-"+a[c].validationId);else for(var c in a)a[c].hasOwnProperty("$dirty")&&b.$broadcast(c+"reset-"+a[c].validationId)},this.$get=["$injector",function(a){return g(a),{setErrorHTML:this.setErrorHTML,getErrorHTML:this.getErrorHTML,setSuccessHTML:this.setSuccessHTML,getSuccessHTML:this.getSuccessHTML,setExpression:this.setExpression,getExpression:this.getExpression,setDefaultMsg:this.setDefaultMsg,getDefaultMsg:this.getDefaultMsg,showSuccessMessage:this.showSuccessMessage,showErrorMessage:this.showErrorMessage,checkValid:this.checkValid,validate:this.validate,reset:this.reset}}]})}.call(this),function(){angular.module("validation.directive",["validation.provider"]).directive("validator",["$injector",function(a){var b=a.get("$validation"),c=a.get("$q"),d=a.get("$timeout"),e=function(a,c,d,e,f){return a.next().html(b.showSuccessMessage?b.getSuccessHTML(c||b.getDefaultMsg(d).success):""),f.$setValidity(f.$name,!0),e&&e(),!0},f=function(a,c,d,e,f){return a.next().html(b.showErrorMessage?b.getErrorHTML(c||b.getDefaultMsg(d).error):""),f.$setValidity(f.$name,!1),e&&e(),!1},g=!1,h=function(a,d,g,h,i,j){var k=i+"SuccessMessage",l=i+"ErrorMessage",m=b.getExpression(i).constructor,n={success:function(){return e(d,g[k],i,a.validCallback,h)},error:function(){return f(d,g[l],i,a.invalidCallback,h)}};return m===Function?c.all([b.getExpression(i)(j,a,d,g)]).then(function(a){return a&&a.length>0&&a[0]?n.success():n.error()},function(){return n.error()}):m===RegExp&&b.getExpression(i).test(j)?n.success():n.error()},i=function(){return(65536*(1+Math.random())|0).toString(16).substring(1)},j=function(){return i()+i()+i()+i()};return{restrict:"A",require:"ngModel",scope:{model:"=ngModel",initialValidity:"=initialValidity",validCallback:"&",invalidCallback:"&"},link:function(a,b,c,e){var f=function(){},i=c.validator.split(","),k=e.validationId=j();b.after("");var l=!1;"boolean"==typeof a.initialValidity&&(l=a.initialValidity),e.$setValidity(e.$name,l),a.$on(e.$name+"reset-"+k,function(){f(),g=!1,e.$setViewValue(""),e.$setPristine(),e.$setValidity(e.$name,!1),e.$render(),b.next().html("")}),i.forEach(function(d){return a.$on(e.$name+"submit-"+k,function(i,j){var k=b[0].value,l=!1;0==j&&(g=!1),l=h(a,b,c,e,d,k),"submit"===c.validMethod&&(f(),f=a.$watch("model",function(f,g){f!==g&&((void 0===f||null===f)&&(f=""),l=h(a,b,c,e,d,f))})),g||l||(g=!0,b[0].focus())}),"blur"===c.validMethod?void b.bind("blur",function(){var f=b[0].value;a.$apply(function(){h(a,b,c,e,d,f)})}):void("submit"!==c.validMethod&&"submit-only"!==c.validMethod&&a.$watch("model",function(f){if(e.$pristine&&e.$viewValue)e.$setViewValue(e.$viewValue);else if(e.$pristine)return void b.next().html("");h(a,b,c,e,d,f)}))}),d(function(){c.$observe("noValidationMessage",function(a){var c=b.next();"true"==a||1==a?c.css("display","none"):("false"==a||0==a)&&c.css("display","block")})})}}}]).directive("validationSubmit",["$injector",function(a){var b=a.get("$validation"),c=a.get("$timeout"),d=a.get("$parse");return{priority:1,require:"?ngClick",link:function(a,e,f){var g=d(f.validationSubmit)(a);c(function(){e.off("click"),e.on("click",function(c){c.preventDefault(),b.validate(g).success(function(){d(f.ngClick)(a)})})})}}}]).directive("validationReset",["$injector",function(a){var b=a.get("$validation"),c=a.get("$timeout"),d=a.get("$parse");return{link:function(a,e,f){var g=d(f.validationReset)(a);c(function(){e.on("click",function(a){a.preventDefault(),b.reset(g)})})}}}])}.call(this); \ No newline at end of file +(function(){angular.module("validation",["validation.provider","validation.directive"])}).call(this),function(){angular.module("validation.provider",[]).provider("$validation",function(){var a,b,c,d,e,f=this,g=function(f){a=f,b=a.get("$rootScope"),c=a.get("$http"),d=a.get("$q"),e=a.get("$timeout")},h={},i={};this.setExpression=function(a){return angular.extend(h,a),f},this.getExpression=function(a){return h[a]},this.setDefaultMsg=function(a){return angular.extend(i,a),f},this.getDefaultMsg=function(a){return i[a]},this.setErrorHTML=function(a){return a.constructor===Function?(f.getErrorHTML=a,f):void 0},this.getErrorHTML=function(a){return'

'+a+"

"},this.setSuccessHTML=function(a){return a.constructor===Function?(f.getSuccessHTML=a,f):void 0},this.getSuccessHTML=function(a){return'

'+a+"

"},this.showSuccessMessage=!0,this.showErrorMessage=!0,this.checkValid=function(a){return void 0===a.$valid?!1:a&&a.$valid===!0},this.validate=function(a){var c=d.defer(),g=0;if(void 0===a)return console.error("This is not a regular Form name scope"),c.reject("This is not a regular Form name scope"),c.promise;if(a.validationId)b.$broadcast(a.$name+"submit-"+a.validationId,g++);else if(a.constructor===Array)for(var h in a)b.$broadcast(a[h].$name+"submit-"+a[h].validationId,g++);else for(var i in a)a[i]&&a[i].hasOwnProperty("$dirty")&&b.$broadcast(i+"submit-"+a[i].validationId,g++);return c.promise.success=function(a){return c.promise.then(function(b){a(b)}),c.promise},c.promise.error=function(a){return c.promise.then(null,function(b){a(b)}),c.promise},e(function(){f.checkValid(a)?c.resolve("success"):c.reject("error")}),c.promise},this.reset=function(a){if(void 0===a)return void console.error("This is not a regular Form name scope");if(a.validationId)b.$broadcast(a.$name+"reset-"+a.validationId);else if(a.constructor===Array)for(var c in a)b.$broadcast(a[c].$name+"reset-"+a[c].validationId);else for(var d in a)a[d].hasOwnProperty("$dirty")&&b.$broadcast(d+"reset-"+a[d].validationId)},this.$get=["$injector",function(a){return g(a),{setErrorHTML:this.setErrorHTML,getErrorHTML:this.getErrorHTML,setSuccessHTML:this.setSuccessHTML,getSuccessHTML:this.getSuccessHTML,setExpression:this.setExpression,getExpression:this.getExpression,setDefaultMsg:this.setDefaultMsg,getDefaultMsg:this.getDefaultMsg,showSuccessMessage:this.showSuccessMessage,showErrorMessage:this.showErrorMessage,checkValid:this.checkValid,validate:this.validate,reset:this.reset}}]})}.call(this),function(){angular.module("validation.directive",["validation.provider"]).directive("validator",["$injector",function(a){var b=a.get("$validation"),c=a.get("$q"),d=a.get("$timeout"),e=function(a,c,d,e,f){return a.next().html(b.showSuccessMessage?b.getSuccessHTML(c||b.getDefaultMsg(d).success):""),f.$setValidity(f.$name,!0),e&&e(),!0},f=function(a,c,d,e,f){return a.next().html(b.showErrorMessage?b.getErrorHTML(c||b.getDefaultMsg(d).error):""),f.$setValidity(f.$name,!1),e&&e(),!1},g=!1,h=function(a,d,g,h,i,j){var k=i+"SuccessMessage",l=i+"ErrorMessage",m=b.getExpression(i).constructor,n={success:function(){return e(d,g[k],i,a.validCallback,h)},error:function(){return f(d,g[l],i,a.invalidCallback,h)}};return m===Function?c.all([b.getExpression(i)(j,a,d,g)]).then(function(a){return a&&a.length>0&&a[0]?n.success():n.error()},function(){return n.error()}):m===RegExp&&b.getExpression(i).test(j)?n.success():n.error()},i=function(){return(65536*(1+Math.random())|0).toString(16).substring(1)},j=function(){return i()+i()+i()+i()};return{restrict:"A",require:"ngModel",scope:{model:"=ngModel",initialValidity:"=initialValidity",validCallback:"&",invalidCallback:"&"},link:function(a,b,c,e){var f=function(){},i=c.validator.split(","),k=e.validationId=j();b.after("");var l=!1;"boolean"==typeof a.initialValidity&&(l=a.initialValidity),e.$setValidity(e.$name,l),a.$on(e.$name+"reset-"+k,function(){f(),g=!1,e.$setViewValue(""),e.$setPristine(),e.$setValidity(e.$name,!1),e.$render(),b.next().html("")}),i.forEach(function(d){return a.$on(e.$name+"submit-"+k,function(i,j){var k=b[0].value,l=!1;0===j&&(g=!1),l=h(a,b,c,e,d,k),"submit"===c.validMethod&&(f(),f=a.$watch("model",function(f,g){f!==g&&((void 0===f||null===f)&&(f=""),l=h(a,b,c,e,d,f))})),g||l||(g=!0,b[0].focus())}),"blur"===c.validMethod?void b.bind("blur",function(){var f=b[0].value;a.$apply(function(){h(a,b,c,e,d,f)})}):void("submit"!==c.validMethod&&"submit-only"!==c.validMethod&&a.$watch("model",function(f){if(e.$pristine&&e.$viewValue)e.$setViewValue(e.$viewValue);else if(e.$pristine)return void b.next().html("");h(a,b,c,e,d,f)}))}),d(function(){c.$observe("noValidationMessage",function(a){var c=b.next();"true"==a||a===!0?c.css("display","none"):("false"==a||a===!1)&&c.css("display","block")})})}}}]).directive("validationSubmit",["$injector",function(a){var b=a.get("$validation"),c=a.get("$timeout"),d=a.get("$parse");return{priority:1,require:"?ngClick",link:function(a,e,f){var g=d(f.validationSubmit)(a);c(function(){e.off("click"),e.on("click",function(c){c.preventDefault(),b.validate(g).success(function(){d(f.ngClick)(a)})})})}}}]).directive("validationReset",["$injector",function(a){var b=a.get("$validation"),c=a.get("$timeout"),d=a.get("$parse");return{link:function(a,e,f){var g=d(f.validationReset)(a);c(function(){e.on("click",function(a){a.preventDefault(),b.reset(g)})})}}}])}.call(this); \ No newline at end of file diff --git a/package.json b/package.json index bb595a2..8f13c53 100644 --- a/package.json +++ b/package.json @@ -1,45 +1,54 @@ { - "name": "angular-validation", - "version": "1.2.2", - "description": "Client-side Validation for AngularJS", - "repository": { - "type": "git", - "url": "https://github.com/huei90/angular-validation" - }, - "homepage": "http://huei90.github.io/angular-validation/", - "scripts": { - "test": "grunt karma", - "build": "grunt build", - "development": "grunt dev" - }, - "author": { - "name": "Huei Tan", - "email": "huei90@gmail.com", - "url": "https://github.com/huei90" - }, - "license": "MIT", - "keywords": ["angular", "angularjs", "validation", "angular validation", "validator", "client-side"], - "bugs": "https://github.com/huei90/angular-validation/issues", - "devDependencies": { - "grunt": "~0.4.4", - "grunt-contrib-watch": "~0.6.1", - "grunt-browser-sync": "~0.9.1", - "grunt-contrib-concat": "~0.4.0", - "grunt-contrib-uglify": "~0.5.0", - "grunt-contrib-copy": "~0.5.0", - "grunt-contrib-clean": "~0.5.0", - "time-grunt": "~0.3.1", - "load-grunt-tasks": "~0.5.0", - "karma-chrome-launcher": "~0.1.2", - "karma-firefox-launcher": "~0.1.2", - "karma-script-launcher": "~0.1.0", - "karma-html2js-preprocessor": "~0.1.0", - "karma-jasmine": "~0.1.4", - "requirejs": "~2.1.9", - "karma-requirejs": "~0.2.0", - "karma-coffee-preprocessor": "~0.2.1", - "karma-phantomjs-launcher": "~0.1.1", - "karma": "~0.12.1", - "grunt-karma": "~0.8.2" - } + "name": "angular-validation", + "version": "1.2.2", + "description": "Client-side Validation for AngularJS", + "repository": { + "type": "git", + "url": "https://github.com/huei90/angular-validation" + }, + "homepage": "http://huei90.github.io/angular-validation/", + "scripts": { + "test": "grunt karma", + "build": "grunt build", + "development": "grunt dev" + }, + "author": { + "name": "Huei Tan", + "email": "huei90@gmail.com", + "url": "https://github.com/huei90" + }, + "license": "MIT", + "keywords": [ + "angular", + "angularjs", + "validation", + "angular validation", + "validator", + "client-side" + ], + "bugs": "https://github.com/huei90/angular-validation/issues", + "devDependencies": { + "grunt": "~0.4.4", + "grunt-browser-sync": "~0.9.1", + "grunt-contrib-clean": "~0.5.0", + "grunt-contrib-concat": "~0.4.0", + "grunt-contrib-copy": "~0.5.0", + "grunt-contrib-jshint": "^0.10.0", + "grunt-contrib-uglify": "~0.5.0", + "grunt-contrib-watch": "~0.6.1", + "grunt-jsbeautifier": "^0.2.7", + "grunt-karma": "~0.8.2", + "karma": "~0.12.1", + "karma-chrome-launcher": "~0.1.2", + "karma-coffee-preprocessor": "~0.2.1", + "karma-firefox-launcher": "~0.1.2", + "karma-html2js-preprocessor": "~0.1.0", + "karma-jasmine": "~0.1.4", + "karma-phantomjs-launcher": "~0.1.1", + "karma-requirejs": "~0.2.0", + "karma-script-launcher": "~0.1.0", + "load-grunt-tasks": "~0.5.0", + "requirejs": "~2.1.9", + "time-grunt": "~0.3.1" + } } diff --git a/src/directive.js b/src/directive.js index 9d960cd..27699d9 100644 --- a/src/directive.js +++ b/src/directive.js @@ -1,301 +1,303 @@ -(function () { +(function() { angular.module('validation.directive', ['validation.provider']) - .directive('validator', ['$injector', function ($injector) { - - var $validationProvider = $injector.get('$validation'), - $q = $injector.get('$q'), - $timeout = $injector.get('$timeout'); - - /** - * Do this function if validation valid - * @param element - * @param validMessage - * @param validation - * @param callback - * @param ctrl - * @returns {} - */ - var validFunc = function (element, validMessage, validation, callback, ctrl) { - if ($validationProvider.showSuccessMessage) { - element.next().html($validationProvider.getSuccessHTML(validMessage || $validationProvider.getDefaultMsg(validation).success)); - } else { - element.next().html(''); - } - ctrl.$setValidity(ctrl.$name, true); - if (callback) callback(); - - return true; - }; - - - /** - * Do this function if validation invalid - * @param element - * @param validMessage - * @param validation - * @param callback - * @param ctrl - * @returns {} - */ - var invalidFunc = function (element, validMessage, validation, callback, ctrl) { - if ($validationProvider.showErrorMessage) { - element.next().html($validationProvider.getErrorHTML(validMessage || $validationProvider.getDefaultMsg(validation).error)); - } else { - element.next().html(''); - } - ctrl.$setValidity(ctrl.$name, false); - if (callback) callback(); - - return false; - }; - - - /** - * If var is true, focus element when validate end - * @type {boolean} - ***private variable - */ - var isFocusElement = false; - - - /** - * Check Validation with Function or RegExp - * @param scope - * @param element - * @param attrs - * @param ctrl - * @param validation - * @param value - * @returns {} - */ - var checkValidation = function (scope, element, attrs, ctrl, validation, value) { - var successMessage = validation + 'SuccessMessage', - errorMessage = validation + 'ErrorMessage', - expressionType = $validationProvider.getExpression(validation).constructor, - valid = { - success: function () { - return validFunc(element, attrs[successMessage], validation, scope.validCallback, ctrl); - }, - error: function () { - return invalidFunc(element, attrs[errorMessage], validation, scope.invalidCallback, ctrl); - } - }; - - // Check with Function - if (expressionType === Function) { - return $q.all([$validationProvider.getExpression(validation)(value, scope, element, attrs)]) - .then(function (data) { - if (data && data.length > 0 && data[0]) { - return valid.success(); - } else { - return valid.error(); + .directive('validator', ['$injector', + function($injector) { + + var $validationProvider = $injector.get('$validation'), + $q = $injector.get('$q'), + $timeout = $injector.get('$timeout'); + + /** + * Do this function if validation valid + * @param element + * @param validMessage + * @param validation + * @param callback + * @param ctrl + * @returns {} + */ + var validFunc = function(element, validMessage, validation, callback, ctrl) { + if ($validationProvider.showSuccessMessage) { + element.next().html($validationProvider.getSuccessHTML(validMessage || $validationProvider.getDefaultMsg(validation).success)); + } else { + element.next().html(''); + } + ctrl.$setValidity(ctrl.$name, true); + if (callback) callback(); + + return true; + }; + + + /** + * Do this function if validation invalid + * @param element + * @param validMessage + * @param validation + * @param callback + * @param ctrl + * @returns {} + */ + var invalidFunc = function(element, validMessage, validation, callback, ctrl) { + if ($validationProvider.showErrorMessage) { + element.next().html($validationProvider.getErrorHTML(validMessage || $validationProvider.getDefaultMsg(validation).error)); + } else { + element.next().html(''); + } + ctrl.$setValidity(ctrl.$name, false); + if (callback) callback(); + + return false; + }; + + + /** + * If var is true, focus element when validate end + * @type {boolean} + ***private variable + */ + var isFocusElement = false; + + + /** + * Check Validation with Function or RegExp + * @param scope + * @param element + * @param attrs + * @param ctrl + * @param validation + * @param value + * @returns {} + */ + var checkValidation = function(scope, element, attrs, ctrl, validation, value) { + var successMessage = validation + 'SuccessMessage', + errorMessage = validation + 'ErrorMessage', + expressionType = $validationProvider.getExpression(validation).constructor, + valid = { + success: function() { + return validFunc(element, attrs[successMessage], validation, scope.validCallback, ctrl); + }, + error: function() { + return invalidFunc(element, attrs[errorMessage], validation, scope.invalidCallback, ctrl); } - }, function () { - return valid.error(); - }); - } - // Check with RegExp - else if (expressionType === RegExp) { - return $validationProvider.getExpression(validation).test(value) ? valid.success() : valid.error(); - } else { - return valid.error(); - } - }; - - - /** - * generate unique guid - */ - var s4 = function () { - return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); - }; - var guid = function () { - return (s4() + s4() + s4() + s4()); - }; - - - return { - restrict: 'A', - require: 'ngModel', - scope: { - model: '=ngModel', - initialValidity: '=initialValidity', - validCallback: '&', - invalidCallback: '&' - }, - link: function (scope, element, attrs, ctrl) { - - /** - * watch - * @type {watch} - * - * Use to collect scope.$watch method - * - * use watch() to destroy the $watch method - */ - var watch = function () {}; - - /** - * validator - * @type {*|Array} - * - * Convert user input String to Array - */ - var validator = attrs.validator.split(','); - - /** - * guid use - */ - var uid = ctrl.validationId = guid(); - - /** - * Valid/Invalid Message - */ - element.after(''); - - /** - * Set initial validity to false if no boolean value is transmitted - */ - var initialValidity = false; - if (typeof scope.initialValidity === 'boolean') { - initialValidity = scope.initialValidity; + }; + + // Check with Function + if (expressionType === Function) { + return $q.all([$validationProvider.getExpression(validation)(value, scope, element, attrs)]) + .then(function(data) { + if (data && data.length > 0 && data[0]) { + return valid.success(); + } else { + return valid.error(); + } + }, function() { + return valid.error(); + }); } - - /** - * Set custom initial validity - * Usage: - */ - ctrl.$setValidity(ctrl.$name, initialValidity); - - /** - * Reset the validation for specific form - */ - scope.$on(ctrl.$name + 'reset-' + uid, function () { + // Check with RegExp + else if (expressionType === RegExp) { + return $validationProvider.getExpression(validation).test(value) ? valid.success() : valid.error(); + } else { + return valid.error(); + } + }; + + + /** + * generate unique guid + */ + var s4 = function() { + return (((1 + Math.random()) * 0x10000) | 0).toString(16).substring(1); + }; + var guid = function() { + return (s4() + s4() + s4() + s4()); + }; + + + return { + restrict: 'A', + require: 'ngModel', + scope: { + model: '=ngModel', + initialValidity: '=initialValidity', + validCallback: '&', + invalidCallback: '&' + }, + link: function(scope, element, attrs, ctrl) { /** - * clear scope.$watch here - * when reset status - * clear the $watch method to prevent - * $watch again while reset the form + * watch + * @type {watch} + * + * Use to collect scope.$watch method + * + * use watch() to destroy the $watch method */ - watch(); - - isFocusElement = false; - ctrl.$setViewValue(''); - ctrl.$setPristine(); - ctrl.$setValidity(ctrl.$name, false); - ctrl.$render(); - element.next().html(''); - }); - - /** - * Check Every validator - */ - validator.forEach(function (validation) { + var watch = function() {}; /** - * Click submit form, check the validity when submit + * validator + * @type {*|Array} + * + * Convert user input String to Array */ - scope.$on(ctrl.$name + 'submit-' + uid, function (event, index) { - var value = element[0].value, - isValid = false; - - if (index == 0) { - isFocusElement = false; - } - - isValid = checkValidation(scope, element, attrs, ctrl, validation, value); + var validator = attrs.validator.split(','); - if (attrs.validMethod === 'submit') { - watch(); // clear previous scope.$watch - watch = scope.$watch('model', function (value, oldValue) { + /** + * guid use + */ + var uid = ctrl.validationId = guid(); - // don't watch when init - if (value === oldValue) { - return; - } + /** + * Valid/Invalid Message + */ + element.after(''); - // scope.$watch will translate '' to undefined - // undefined/null will pass the required submit /^.+/ - // cause some error in this validation - if (value === undefined || value === null) { - value = ''; - } + /** + * Set initial validity to false if no boolean value is transmitted + */ + var initialValidity = false; + if (typeof scope.initialValidity === 'boolean') { + initialValidity = scope.initialValidity; + } - isValid = checkValidation(scope, element, attrs, ctrl, validation, value); - }); + /** + * Set custom initial validity + * Usage: + */ + ctrl.$setValidity(ctrl.$name, initialValidity); - } + /** + * Reset the validation for specific form + */ + scope.$on(ctrl.$name + 'reset-' + uid, function() { - // Focus first input element when submit error #11 - if (!isFocusElement && !isValid) { - isFocusElement = true; - element[0].focus(); - } + /** + * clear scope.$watch here + * when reset status + * clear the $watch method to prevent + * $watch again while reset the form + */ + watch(); + + isFocusElement = false; + ctrl.$setViewValue(''); + ctrl.$setPristine(); + ctrl.$setValidity(ctrl.$name, false); + ctrl.$render(); + element.next().html(''); }); /** - * Validate blur method + * Check Every validator */ - if (attrs.validMethod === 'blur') { - element.bind('blur', function () { - var value = element[0].value; - scope.$apply(function() { - checkValidation(scope, element, attrs, ctrl, validation, value); - }); + validator.forEach(function(validation) { + + /** + * Click submit form, check the validity when submit + */ + scope.$on(ctrl.$name + 'submit-' + uid, function(event, index) { + var value = element[0].value, + isValid = false; + + if (index === 0) { + isFocusElement = false; + } + + isValid = checkValidation(scope, element, attrs, ctrl, validation, value); + + if (attrs.validMethod === 'submit') { + watch(); // clear previous scope.$watch + watch = scope.$watch('model', function(value, oldValue) { + + // don't watch when init + if (value === oldValue) { + return; + } + + // scope.$watch will translate '' to undefined + // undefined/null will pass the required submit /^.+/ + // cause some error in this validation + if (value === undefined || value === null) { + value = ''; + } + + isValid = checkValidation(scope, element, attrs, ctrl, validation, value); + }); + + } + + // Focus first input element when submit error #11 + if (!isFocusElement && !isValid) { + isFocusElement = true; + element[0].focus(); + } }); - return; - } + /** + * Validate blur method + */ + if (attrs.validMethod === 'blur') { + element.bind('blur', function() { + var value = element[0].value; + scope.$apply(function() { + checkValidation(scope, element, attrs, ctrl, validation, value); + }); + }); - /** - * Validate submit & submit-only method - */ - if (attrs.validMethod === 'submit' || attrs.validMethod === 'submit-only') { - return; - } + return; + } - /** - * Validate watch method - * This is the default method - */ - scope.$watch('model', function (value) { /** - * dirty, pristine, viewValue control here + * Validate submit & submit-only method */ - if (ctrl.$pristine && ctrl.$viewValue) { - // has value when initial - ctrl.$setViewValue(ctrl.$viewValue); - } else if (ctrl.$pristine) { - // Don't validate form when the input is clean(pristine) - element.next().html(''); + if (attrs.validMethod === 'submit' || attrs.validMethod === 'submit-only') { return; } - checkValidation(scope, element, attrs, ctrl, validation, value); - }); - }); + /** + * Validate watch method + * This is the default method + */ + scope.$watch('model', function(value) { + /** + * dirty, pristine, viewValue control here + */ + if (ctrl.$pristine && ctrl.$viewValue) { + // has value when initial + ctrl.$setViewValue(ctrl.$viewValue); + } else if (ctrl.$pristine) { + // Don't validate form when the input is clean(pristine) + element.next().html(''); + return; + } + checkValidation(scope, element, attrs, ctrl, validation, value); + }); - $timeout(function () { - /** - * Don't showup the validation Message - */ - attrs.$observe('noValidationMessage', function (value) { - var el = element.next(); - if (value == "true" || value == true) { - el.css('display', 'none'); - } else if (value == "false" || value == false) { - el.css('display', 'block'); - } else { - } }); - }); - } - }; - }]) + $timeout(function() { + /** + * Don't showup the validation Message + */ + attrs.$observe('noValidationMessage', function(value) { + var el = element.next(); + if (value == "true" || value === true) { + el.css('display', 'none'); + } else if (value == "false" || value === false) { + el.css('display', 'block'); + } else {} + }); + }); - .directive('validationSubmit', ['$injector', function ($injector) { + } + }; + } + ]) + + .directive('validationSubmit', ['$injector', + function($injector) { var $validationProvider = $injector.get('$validation'), $timeout = $injector.get('$timeout'), @@ -307,24 +309,26 @@ link: function postLink(scope, element, attrs) { var form = $parse(attrs.validationSubmit)(scope); - $timeout(function () { + $timeout(function() { // Disable ng-click event propagation element.off('click'); - element.on('click', function (e) { + element.on('click', function(e) { e.preventDefault(); $validationProvider.validate(form) - .success(function () { + .success(function() { $parse(attrs.ngClick)(scope); }); }); }); } - } - }]) + }; + } + ]) - .directive('validationReset', ['$injector', function ($injector) { + .directive('validationReset', ['$injector', + function($injector) { var $validationProvider = $injector.get('$validation'), $timeout = $injector.get('$timeout'), @@ -334,15 +338,16 @@ link: function postLink(scope, element, attrs) { var form = $parse(attrs.validationReset)(scope); - $timeout(function () { - element.on('click', function (e) { + $timeout(function() { + element.on('click', function(e) { e.preventDefault(); $validationProvider.reset(form); }); }); } - } - }]); + }; + } + ]); }).call(this); diff --git a/src/module.js b/src/module.js index 90af875..b74a75e 100644 --- a/src/module.js +++ b/src/module.js @@ -1,3 +1,3 @@ -(function () { +(function() { angular.module('validation', ['validation.provider', 'validation.directive']); -}).call(this); \ No newline at end of file +}).call(this); diff --git a/src/provider.js b/src/provider.js index 6126a19..91fa849 100644 --- a/src/provider.js +++ b/src/provider.js @@ -1,6 +1,6 @@ -(function () { +(function() { angular.module('validation.provider', []) - .provider('$validation', function () { + .provider('$validation', function() { var $injector, @@ -15,7 +15,7 @@ * Setup the provider * @param injector */ - var setup = function (injector) { + var setup = function(injector) { $injector = injector; $scope = $injector.get('$rootScope'); $http = $injector.get('$http'); @@ -43,7 +43,7 @@ * @param obj * @returns {*} */ - this.setExpression = function (obj) { + this.setExpression = function(obj) { angular.extend(expression, obj); return _this; }; @@ -54,7 +54,7 @@ * @param exprs * @returns {*} */ - this.getExpression = function (exprs) { + this.getExpression = function(exprs) { return expression[exprs]; }; @@ -64,7 +64,7 @@ * @param obj * @returns {*} */ - this.setDefaultMsg = function (obj) { + this.setDefaultMsg = function(obj) { angular.extend(defaultMsg, obj); return _this; }; @@ -75,7 +75,7 @@ * @param msg * @returns {*} */ - this.getDefaultMsg = function (msg) { + this.getDefaultMsg = function(msg) { return defaultMsg[msg]; }; @@ -85,7 +85,7 @@ * @param func * @returns {*} */ - this.setErrorHTML = function (func) { + this.setErrorHTML = function(func) { if (func.constructor !== Function) { return; } @@ -101,7 +101,7 @@ * @param message * @returns {string} */ - this.getErrorHTML = function (message) { + this.getErrorHTML = function(message) { return '

' + message + '

'; }; @@ -111,7 +111,7 @@ * @param func * @returns {*} */ - this.setSuccessHTML = function (func) { + this.setSuccessHTML = function(func) { if (func.constructor !== Function) { return; } @@ -127,7 +127,7 @@ * @param message * @returns {string} */ - this.getSuccessHTML = function (message) { + this.getSuccessHTML = function(message) { return '

' + message + '

'; }; @@ -156,7 +156,7 @@ * @param form * @returns {boolean} */ - this.checkValid = function (form) { + this.checkValid = function(form) { if (form.$valid === undefined) { return false; } @@ -169,7 +169,7 @@ * @param form * @returns {promise|*} */ - this.validate = function (form) { + this.validate = function(form) { var deferred = $q.defer(), idx = 0; @@ -187,32 +187,31 @@ $scope.$broadcast(form[k].$name + 'submit-' + form[k].validationId, idx++); } } else { - for (var k in form) { // whole scope - if (form[k] && form[k].hasOwnProperty('$dirty')) { - $scope.$broadcast(k + 'submit-' + form[k].validationId, idx++); + for (var i in form) { // whole scope + if (form[i] && form[i].hasOwnProperty('$dirty')) { + $scope.$broadcast(i + 'submit-' + form[i].validationId, idx++); } } } - deferred.promise.success = function (fn) { - deferred.promise.then(function (value) { + deferred.promise.success = function(fn) { + deferred.promise.then(function(value) { fn(value); }); return deferred.promise; }; - deferred.promise.error = function (fn) { - deferred.promise.then(null, function (value) { + deferred.promise.error = function(fn) { + deferred.promise.then(null, function(value) { fn(value); }); return deferred.promise; }; - $timeout(function () { + $timeout(function() { if (_this.checkValid(form)) { deferred.resolve('success'); - } - else { + } else { deferred.reject('error'); } }); @@ -225,7 +224,7 @@ * reset the specific form * @param form */ - this.reset = function (form) { + this.reset = function(form) { if (form === undefined) { console.error('This is not a regular Form name scope'); @@ -239,9 +238,9 @@ $scope.$broadcast(form[k].$name + 'reset-' + form[k].validationId); } } else { - for (var k in form) { - if (form[k].hasOwnProperty('$dirty')) { - $scope.$broadcast(k + 'reset-' + form[k].validationId); + for (var i in form) { + if (form[i].hasOwnProperty('$dirty')) { + $scope.$broadcast(i + 'reset-' + form[i].validationId); } } } @@ -252,24 +251,26 @@ * $get * @returns {{setErrorHTML: *, getErrorHTML: Function, setSuccessHTML: *, getSuccessHTML: Function, setExpression: *, getExpression: Function, setDefaultMsg: *, getDefaultMsg: Function, checkValid: Function, validate: Function, reset: Function}} */ - this.$get = ['$injector', function ($injector) { - setup($injector); - return { - setErrorHTML: this.setErrorHTML, - getErrorHTML: this.getErrorHTML, - setSuccessHTML: this.setSuccessHTML, - getSuccessHTML: this.getSuccessHTML, - setExpression: this.setExpression, - getExpression: this.getExpression, - setDefaultMsg: this.setDefaultMsg, - getDefaultMsg: this.getDefaultMsg, - showSuccessMessage: this.showSuccessMessage, - showErrorMessage: this.showErrorMessage, - checkValid: this.checkValid, - validate: this.validate, - reset: this.reset - }; - }]; + this.$get = ['$injector', + function($injector) { + setup($injector); + return { + setErrorHTML: this.setErrorHTML, + getErrorHTML: this.getErrorHTML, + setSuccessHTML: this.setSuccessHTML, + getSuccessHTML: this.getSuccessHTML, + setExpression: this.setExpression, + getExpression: this.getExpression, + setDefaultMsg: this.setDefaultMsg, + getDefaultMsg: this.getDefaultMsg, + showSuccessMessage: this.showSuccessMessage, + showErrorMessage: this.showErrorMessage, + checkValid: this.checkValid, + validate: this.validate, + reset: this.reset + }; + } + ]; }); }).call(this); diff --git a/src/rule.js b/src/rule.js index 80d62ee..3b960f7 100644 --- a/src/rule.js +++ b/src/rule.js @@ -1,37 +1,39 @@ -(function () { +(function() { angular.module('validation.rule', ['validation']) - .config(['$validationProvider', function ($validationProvider) { + .config(['$validationProvider', + function($validationProvider) { - var expression = { - required: function (value) { - return !!value; - }, - url: /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/, - email: /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/, - number: /^\d+$/ - }; + var expression = { + required: function(value) { + return !!value; + }, + url: /((([A-Za-z]{3,9}:(?:\/\/)?)(?:[-;:&=\+\$,\w]+@)?[A-Za-z0-9.-]+|(?:www.|[-;:&=\+\$,\w]+@)[A-Za-z0-9.-]+)((?:\/[\+~%\/.\w-_]*)?\??(?:[-\+=&;%@.\w_]*)#?(?:[\w]*))?)/, + email: /^([\w-\.]+)@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.)|(([\w-]+\.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(\]?)$/, + number: /^\d+$/ + }; - var defaultMsg = { - required: { - error: 'This should be Required!!', - success: 'It\'s Required' - }, - url: { - error: 'This should be Url', - success: 'It\'s Url' - }, - email: { - error: 'This should be Email', - success: 'It\'s Email' - }, - number: { - error: 'This should be Number', - success: 'It\'s Number' - } - }; + var defaultMsg = { + required: { + error: 'This should be Required!!', + success: 'It\'s Required' + }, + url: { + error: 'This should be Url', + success: 'It\'s Url' + }, + email: { + error: 'This should be Email', + success: 'It\'s Email' + }, + number: { + error: 'This should be Number', + success: 'It\'s Number' + } + }; - $validationProvider.setExpression(expression).setDefaultMsg(defaultMsg); + $validationProvider.setExpression(expression).setDefaultMsg(defaultMsg); - }]); + } + ]); -}).call(this); \ No newline at end of file +}).call(this);