|
1 | 1 | /*
|
2 |
| - * angular-auto-validate - v1.4.20 - 2014-10-16 |
| 2 | + * angular-auto-validate - v1.13.22 - 2014-12-06 |
3 | 3 | * https://github.com/jonsamwell/angular-auto-validate
|
4 | 4 | * Copyright (c) 2014 Jon Samwell (http://www.jonsamwell.com)
|
5 | 5 | */
|
|
19 | 19 | var elementStateModifiers = {},
|
20 | 20 | enableValidElementStyling = true,
|
21 | 21 | enableInvalidElementStyling = true,
|
| 22 | + validationEnabled = true, |
22 | 23 |
|
23 | 24 | toBoolean = function (value) {
|
24 | 25 | var v;
|
|
54 | 55 | return enableInvalidElementStyling && !getBooleanAttributeValue(el, 'disable-invalid-styling');
|
55 | 56 | };
|
56 | 57 |
|
| 58 | + /** |
| 59 | + * @ngdoc function |
| 60 | + * @name validator#enable |
| 61 | + * @methodOf validator |
| 62 | + * |
| 63 | + * @description |
| 64 | + * By default auto validate will validate all forms and elements with an ngModel directive on. By |
| 65 | + * setting enabled to false you will explicitly have to opt in to enable validation on forms and child |
| 66 | + * elements. |
| 67 | + * |
| 68 | + * Note: this can be overridden by add the 'auto-validate-enabled="true/false' attribute to a form. |
| 69 | + * |
| 70 | + * Example: |
| 71 | + * <pre> |
| 72 | + * app.config(function (validator) { |
| 73 | + * validator.enable(false); |
| 74 | + * }); |
| 75 | + * </pre> |
| 76 | + * |
| 77 | + * @param {Boolean} isEnabled true to enable, false to disable. |
| 78 | + */ |
| 79 | + this.enable = function (isEnabled) { |
| 80 | + validationEnabled = isEnabled; |
| 81 | + }; |
| 82 | + |
| 83 | + /** |
| 84 | + * @ngdoc function |
| 85 | + * @name validator#isEnabled |
| 86 | + * @methodOf validator |
| 87 | + * |
| 88 | + * @description |
| 89 | + * Returns true if the library is enabeld. |
| 90 | + * |
| 91 | + * @return {Boolean} true if enabled, otherwise false. |
| 92 | + */ |
| 93 | + this.isEnabled = function () { |
| 94 | + return validationEnabled; |
| 95 | + }; |
| 96 | + |
57 | 97 | /**
|
58 | 98 | * @ngdoc function
|
59 | 99 | * @name validator#setDefaultElementModifier
|
|
229 | 269 | };
|
230 | 270 |
|
231 | 271 | this.$get = [
|
232 |
| - |
233 | 272 | function () {
|
234 | 273 | return this;
|
235 | 274 | }
|
|
243 | 282 |
|
244 | 283 | angular.module('jcs-autoValidate')
|
245 | 284 | .factory('bootstrap3ElementModifier', [
|
246 |
| - |
247 |
| - function () { |
| 285 | + '$log', |
| 286 | + function ($log) { |
248 | 287 | var reset = function (el) {
|
249 | 288 | angular.forEach(el.find('span'), function (spanEl) {
|
250 | 289 | spanEl = angular.element(spanEl);
|
|
256 | 295 | el.removeClass('has-success has-error has-feedback');
|
257 | 296 | },
|
258 | 297 | findWithClassElementAsc = function (el, klass) {
|
259 |
| - var parent = el; |
| 298 | + var retuenEl, |
| 299 | + parent = el; |
260 | 300 | for (var i = 0; i <= 3; i += 1) {
|
261 | 301 | if (parent !== undefined && parent.hasClass(klass)) {
|
| 302 | + retuenEl = parent; |
262 | 303 | break;
|
263 | 304 | } else if (parent !== undefined) {
|
264 | 305 | parent = parent.parent();
|
265 | 306 | }
|
266 | 307 | }
|
267 | 308 |
|
268 |
| - return parent; |
| 309 | + return retuenEl; |
269 | 310 | },
|
270 | 311 |
|
271 | 312 | findWithClassElementDesc = function (el, klass) {
|
|
334 | 375 | */
|
335 | 376 | makeValid = function (el) {
|
336 | 377 | var frmGroupEl = findFormGroupElement(el),
|
| 378 | + inputGroupEl; |
| 379 | + |
| 380 | + if (frmGroupEl) { |
| 381 | + reset(frmGroupEl); |
337 | 382 | inputGroupEl = findInputGroupElement(frmGroupEl[0]);
|
| 383 | + frmGroupEl.addClass('has-success ' + (inputGroupEl.length > 0 ? '' : 'has-feedback')); |
| 384 | + if (addValidationStateIcons) { |
| 385 | + var iconElText = '<span class="glyphicon glyphicon-ok form-control-feedback"></span>'; |
| 386 | + if (inputGroupEl.length > 0) { |
| 387 | + iconElText = iconElText.replace('form-', ''); |
| 388 | + iconElText = '<span class="input-group-addon control-feedback">' + iconElText + '</span'; |
| 389 | + } |
338 | 390 |
|
339 |
| - reset(frmGroupEl); |
340 |
| - frmGroupEl.addClass('has-success ' + (inputGroupEl.length > 0 ? '' : 'has-feedback')); |
341 |
| - if (addValidationStateIcons) { |
342 |
| - var iconElText = '<span class="glyphicon glyphicon-ok form-control-feedback"></span>'; |
343 |
| - if (inputGroupEl.length > 0) { |
344 |
| - iconElText = iconElText.replace('form-', ''); |
345 |
| - iconElText = '<span class="input-group-addon control-feedback">' + iconElText + '</span'; |
| 391 | + insertAfter(el, angular.element(iconElText)); |
346 | 392 | }
|
347 |
| - |
348 |
| - insertAfter(el, angular.element(iconElText)); |
| 393 | + } else { |
| 394 | + $log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); |
349 | 395 | }
|
350 | 396 | },
|
351 | 397 |
|
|
363 | 409 | */
|
364 | 410 | makeInvalid = function (el, errorMsg) {
|
365 | 411 | var frmGroupEl = findFormGroupElement(el),
|
366 |
| - inputGroupEl = findInputGroupElement(frmGroupEl[0]), |
367 |
| - helpTextEl = angular.element('<span class="help-block has-error error-msg">' + errorMsg + '</span>'); |
368 |
| - reset(frmGroupEl, inputGroupEl); |
369 |
| - frmGroupEl.addClass('has-error ' + (inputGroupEl.length > 0 ? '' : 'has-feedback')); |
370 |
| - insertAfter(inputGroupEl.length > 0 ? inputGroupEl : el, helpTextEl); |
371 |
| - if (addValidationStateIcons) { |
372 |
| - var iconElText = '<span class="glyphicon glyphicon-remove form-control-feedback"></span>'; |
373 |
| - if (inputGroupEl.length > 0) { |
374 |
| - iconElText = iconElText.replace('form-', ''); |
375 |
| - iconElText = '<span class="input-group-addon control-feedback">' + iconElText + '</span'; |
376 |
| - } |
| 412 | + helpTextEl = angular.element('<span class="help-block has-error error-msg">' + errorMsg + '</span>'), |
| 413 | + inputGroupEl; |
377 | 414 |
|
378 |
| - insertAfter(el, angular.element(iconElText)); |
| 415 | + if (frmGroupEl) { |
| 416 | + reset(frmGroupEl); |
| 417 | + inputGroupEl = findInputGroupElement(frmGroupEl[0]); |
| 418 | + frmGroupEl.addClass('has-error ' + (inputGroupEl.length > 0 ? '' : 'has-feedback')); |
| 419 | + insertAfter(inputGroupEl.length > 0 ? inputGroupEl : el, helpTextEl); |
| 420 | + if (addValidationStateIcons) { |
| 421 | + var iconElText = '<span class="glyphicon glyphicon-remove form-control-feedback"></span>'; |
| 422 | + if (inputGroupEl.length > 0) { |
| 423 | + iconElText = iconElText.replace('form-', ''); |
| 424 | + iconElText = '<span class="input-group-addon control-feedback">' + iconElText + '</span'; |
| 425 | + } |
| 426 | + |
| 427 | + insertAfter(el, angular.element(iconElText)); |
| 428 | + } |
| 429 | + } else { |
| 430 | + $log.error('Angular-auto-validate: invalid bs3 form structure elements must be wrapped by a form-group class'); |
379 | 431 | }
|
380 | 432 | },
|
381 | 433 |
|
|
481 | 533 | function ($q, $http) {
|
482 | 534 | var currentCulture = 'en-gb',
|
483 | 535 |
|
484 |
| - i18nFileRootPath = 'Scripts/lang', |
| 536 | + i18nFileRootPath = 'js/angular-auto-validate/dist/lang', |
485 | 537 |
|
486 | 538 | cultureRetrievalPromise,
|
487 | 539 |
|
|
499 | 551 | * Set the root path to the il8n files on the server
|
500 | 552 | *
|
501 | 553 | * @param {String} rootPath - The root path on the server to the il8n file - this defaults
|
502 |
| - * to 'Scripts/lang/' |
| 554 | + * to 'js/angular-auto-validate/lang/' |
503 | 555 | */
|
504 | 556 | setI18nFileRootPath = function (rootPath) {
|
505 | 557 | i18nFileRootPath = rootPath;
|
|
738 | 790 | (function (angular) {
|
739 | 791 | 'use strict';
|
740 | 792 |
|
| 793 | + |
| 794 | + angular.module('jcs-autoValidate') |
| 795 | + .factory('jcs-elementUtils', [ |
| 796 | + function () { |
| 797 | + var isElementVisible = function (el) { |
| 798 | + return el[0].offsetWidth > 0 && el[0].offsetHeight > 0; |
| 799 | + }; |
| 800 | + |
| 801 | + return { |
| 802 | + isElementVisible: isElementVisible |
| 803 | + }; |
| 804 | + } |
| 805 | + ]); |
| 806 | + |
741 | 807 | angular.module('jcs-autoValidate')
|
742 | 808 | .factory('validationManager', [
|
743 | 809 | 'validator',
|
744 |
| - function (validator) { |
| 810 | + 'jcs-elementUtils', |
| 811 | + function (validator, elementUtils) { |
745 | 812 | var elementTypesToValidate = ['input', 'textarea', 'select', 'form'],
|
746 | 813 |
|
| 814 | + elementIsVisible = function (el) { |
| 815 | + return elementUtils.isElementVisible(el); |
| 816 | + }, |
| 817 | + |
747 | 818 | shouldValidateElement = function (el) {
|
748 |
| - return el && el.length > 0 && elementTypesToValidate.indexOf(el[0].nodeName.toLowerCase()) > -1; |
| 819 | + return el && el.length > 0 && elementIsVisible(el) && elementTypesToValidate.indexOf(el[0].nodeName.toLowerCase()) > -1; |
749 | 820 | },
|
750 | 821 |
|
751 | 822 | /**
|
|
773 | 844 | return errorTypeToReturn;
|
774 | 845 | };
|
775 | 846 |
|
776 |
| - if ((forceValidation || shouldValidateElement(el)) && modelCtrl && needsValidation) { |
| 847 | + if ((forceValidation || (shouldValidateElement(el) && modelCtrl && needsValidation))) { |
777 | 848 | isValid = !modelCtrl.$invalid;
|
778 | 849 |
|
779 | 850 | if (isValid) {
|
780 | 851 | validator.makeValid(el);
|
781 | 852 | } else {
|
782 | 853 | errorType = findErrorType(modelCtrl.$error);
|
783 | 854 |
|
784 |
| - validator.getErrorMessage(errorType, el).then(function (errorMsg) { |
785 |
| - validator.makeInvalid(el, errorMsg); |
786 |
| - }); |
| 855 | + if (errorType === undefined) { |
| 856 | + // we have a weird situation some users are encountering where a custom control |
| 857 | + // is valid but the ngModel is report it isn't and thus no valid error type can be found |
| 858 | + isValid = true; |
| 859 | + } else { |
| 860 | + validator.getErrorMessage(errorType, el).then(function (errorMsg) { |
| 861 | + validator.makeInvalid(el, errorMsg); |
| 862 | + }); |
| 863 | + } |
787 | 864 | }
|
788 | 865 | }
|
789 | 866 |
|
|
934 | 1011 | (function (angular) {
|
935 | 1012 | 'use strict';
|
936 | 1013 |
|
937 |
| - angular.module('jcs-autoValidate').directive('disableDynamicValidation', [ |
938 |
| - |
939 |
| - function () { |
| 1014 | + angular.module('jcs-autoValidate').directive('form', [ |
| 1015 | + 'validator', |
| 1016 | + function (validator) { |
940 | 1017 | return {
|
941 |
| - restrict: 'A', |
| 1018 | + restrict: 'E', |
942 | 1019 | require: 'form',
|
943 | 1020 | compile: function () {
|
944 | 1021 | return {
|
945 | 1022 | pre: function (scope, element, attrs, ctrl) {
|
946 |
| - ctrl.disableDynamicValidation = true; |
| 1023 | + ctrl.disableDynamicValidation = !validator.isEnabled(); |
| 1024 | + if (attrs.disableDynamicValidation !== undefined) { |
| 1025 | + ctrl.disableDynamicValidation = attrs.disableDynamicValidation === undefined || attrs.disableDynamicValidation === '' || attrs.disableDynamicValidation === 'true'; |
| 1026 | + } |
947 | 1027 | }
|
948 | 1028 | };
|
949 | 1029 | }
|
|
968 | 1048 | return function (scope, element) {
|
969 | 1049 | element.on('submit', function (event) {
|
970 | 1050 | scope.$apply(function () {
|
971 |
| - if (force === true || validationManager.validateForm(element)) { |
| 1051 | + if (validationManager.validateForm(element) || force === true) { |
972 | 1052 | fn(scope, {
|
973 | 1053 | $event: event
|
974 | 1054 | });
|
|
1022 | 1102 | ngModelOptions = ngModelCtrl.$options === undefined ? undefined : ngModelCtrl.$options;
|
1023 | 1103 | }
|
1024 | 1104 |
|
1025 |
| - if (attrs.formnovalidate === undefined || (frmCtrl !== undefined && frmCtrl.disableDynamicValidation !== true)) { |
| 1105 | + if (attrs.formnovalidate === undefined || (frmCtrl !== undefined && frmCtrl.disableDynamicValidation === false)) { |
1026 | 1106 | if (supportsNgModelOptions || ngModelOptions === undefined || ngModelOptions.updateOn === undefined || ngModelOptions.updateOn === '') {
|
1027 | 1107 | ngModelCtrl.$setValidity = function (validationErrorKey, isValid) {
|
1028 | 1108 | setValidity.call(ngModelCtrl, validationErrorKey, isValid);
|
|
1055 | 1135 |
|
1056 | 1136 | ngModelCtrl.setExternalValidation = function (errorMsgKey, errorMessage, addToModelErrors) {
|
1057 | 1137 | if (addToModelErrors) {
|
1058 |
| - ngModelCtrl.$errors[errorMsgKey] = false; |
| 1138 | + if (ngModelCtrl.$error) { |
| 1139 | + ngModelCtrl.$error[errorMsgKey] = false; |
| 1140 | + } else { |
| 1141 | + ngModelCtrl.$errors[errorMsgKey] = false; |
| 1142 | + } |
1059 | 1143 | }
|
1060 | 1144 |
|
1061 | 1145 | validationManager.setElementValidationError(element, errorMsgKey, errorMessage);
|
1062 | 1146 | };
|
1063 | 1147 |
|
| 1148 | + ngModelCtrl.removeExternalValidation = function (errorMsgKey, addToModelErrors) { |
| 1149 | + if (addToModelErrors) { |
| 1150 | + if (ngModelCtrl.$error) { |
| 1151 | + ngModelCtrl.$error[errorMsgKey] = true; |
| 1152 | + } else { |
| 1153 | + ngModelCtrl.$errors[errorMsgKey] = true; |
| 1154 | + } |
| 1155 | + } |
| 1156 | + |
| 1157 | + validationManager.resetElement(element); |
| 1158 | + }; |
| 1159 | + |
1064 | 1160 | if (frmCtrl) {
|
1065 | 1161 | frmCtrl.setExternalValidation = function (modelProperty, errorMsgKey, errorMessageOverride, addToModelErrors) {
|
1066 | 1162 | var success = false;
|
|
1071 | 1167 |
|
1072 | 1168 | return success;
|
1073 | 1169 | };
|
| 1170 | + |
| 1171 | + frmCtrl.removeExternalValidation = function (modelProperty, errorMsgKey, errorMessageOverride, addToModelErrors) { |
| 1172 | + var success = false; |
| 1173 | + if (frmCtrl[modelProperty]) { |
| 1174 | + frmCtrl[modelProperty].removeExternalValidation(errorMsgKey, addToModelErrors); |
| 1175 | + success = true; |
| 1176 | + } |
| 1177 | + |
| 1178 | + return success; |
| 1179 | + }; |
1074 | 1180 | }
|
1075 | 1181 | };
|
1076 | 1182 | };
|
|
0 commit comments