1
1
/*
2
- * angular-auto-validate - v1.0 .20 - 2014-08-18
2
+ * angular-auto-validate - v1.4 .20 - 2014-09-11
3
3
* https://github.com/jonsamwell/angular-auto-validate
4
4
* Copyright (c) 2014 Jon Samwell (http://www.jonsamwell.com)
5
5
*/
248
248
var reset = function ( el ) {
249
249
angular . forEach ( el . find ( 'span' ) , function ( spanEl ) {
250
250
spanEl = angular . element ( spanEl ) ;
251
- if ( spanEl . hasClass ( 'error-msg' ) || spanEl . hasClass ( 'form-control-feedback' ) ) {
251
+ if ( spanEl . hasClass ( 'error-msg' ) || spanEl . hasClass ( 'form-control-feedback' ) || spanEl . hasClass ( 'control-feedback' ) ) {
252
252
spanEl . remove ( ) ;
253
253
}
254
254
} ) ;
255
255
256
256
el . removeClass ( 'has-success has-error has-feedback' ) ;
257
257
} ,
258
- findFormGroupElement = function ( el ) {
258
+ findWithClassElementAsc = function ( el , klass ) {
259
259
var parent = el ;
260
260
for ( var i = 0 ; i <= 3 ; i += 1 ) {
261
- if ( parent !== undefined && parent . hasClass ( 'form-group' ) ) {
261
+ if ( parent !== undefined && parent . hasClass ( klass ) ) {
262
262
break ;
263
263
} else if ( parent !== undefined ) {
264
264
parent = parent . parent ( ) ;
268
268
return parent ;
269
269
} ,
270
270
271
+ findWithClassElementDesc = function ( el , klass ) {
272
+ var child ;
273
+ for ( var i = 0 ; i < el . children . length ; i += 1 ) {
274
+ child = el . children [ i ] ;
275
+ if ( child !== undefined && angular . element ( child ) . hasClass ( klass ) ) {
276
+ break ;
277
+ } else if ( child . children !== undefined ) {
278
+ child = findWithClassElementDesc ( child , klass ) ;
279
+ if ( child . length > 0 ) {
280
+ break ;
281
+ }
282
+ }
283
+ }
284
+
285
+ return angular . element ( child ) ;
286
+ } ,
287
+
288
+ findFormGroupElement = function ( el ) {
289
+ return findWithClassElementAsc ( el , 'form-group' ) ;
290
+ } ,
291
+
292
+ findInputGroupElement = function ( el ) {
293
+ return findWithClassElementDesc ( el , 'input-group' ) ;
294
+ } ,
295
+
271
296
insertAfter = function ( referenceNode , newNode ) {
272
297
referenceNode [ 0 ] . parentNode . insertBefore ( newNode [ 0 ] , referenceNode [ 0 ] . nextSibling ) ;
273
298
} ,
308
333
* @param {Element } el - The input control element that is the target of the validation.
309
334
*/
310
335
makeValid = function ( el ) {
311
- var frmGroupEl = findFormGroupElement ( el ) ;
336
+ var frmGroupEl = findFormGroupElement ( el ) ,
337
+ inputGroupEl = findInputGroupElement ( frmGroupEl [ 0 ] ) ;
338
+
312
339
reset ( frmGroupEl ) ;
313
- frmGroupEl . addClass ( 'has-success has-feedback' ) ;
340
+ frmGroupEl . addClass ( 'has-success ' + ( inputGroupEl . length > 0 ? '' : ' has-feedback') ) ;
314
341
if ( addValidationStateIcons ) {
315
- insertAfter ( el , angular . element ( '<span class="glyphicon glyphicon-ok form-control-feedback"></span>' ) ) ;
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' ;
346
+ }
347
+
348
+ insertAfter ( el , angular . element ( iconElText ) ) ;
316
349
}
317
350
} ,
318
351
330
363
*/
331
364
makeInvalid = function ( el , errorMsg ) {
332
365
var frmGroupEl = findFormGroupElement ( el ) ,
366
+ inputGroupEl = findInputGroupElement ( frmGroupEl [ 0 ] ) ,
333
367
helpTextEl = angular . element ( '<span class="help-block has-error error-msg">' + errorMsg + '</span>' ) ;
334
- reset ( frmGroupEl ) ;
335
- frmGroupEl . addClass ( 'has-error has-feedback' ) ;
336
- insertAfter ( el , helpTextEl ) ;
368
+ reset ( frmGroupEl , inputGroupEl ) ;
369
+ frmGroupEl . addClass ( 'has-error ' + ( inputGroupEl . length > 0 ? '' : ' has-feedback') ) ;
370
+ insertAfter ( inputGroupEl . length > 0 ? inputGroupEl : el , helpTextEl ) ;
337
371
if ( addValidationStateIcons ) {
338
- insertAfter ( el , angular . element ( '<span class="glyphicon glyphicon-remove form-control-feedback"></span>' ) ) ;
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
+ }
377
+
378
+ insertAfter ( el , angular . element ( iconElText ) ) ;
339
379
}
340
380
} ,
341
381
441
481
function ( $q , $http ) {
442
482
var currentCulture = 'en-gb' ,
443
483
444
- i18nFileRootPath = 'Scripts/i18n ' ,
484
+ i18nFileRootPath = 'js/angular-auto-validate/dist/lang ' ,
445
485
446
486
cultureRetrievalPromise ,
447
487
459
499
* Set the root path to the il8n files on the server
460
500
*
461
501
* @param {String } rootPath - The root path on the server to the il8n file - this defaults
462
- * to 'Scripts/i18n /'
502
+ * to 'js/angular-auto-validate/lang /'
463
503
*/
464
504
setI18nFileRootPath = function ( rootPath ) {
465
505
i18nFileRootPath = rootPath ;
525
565
// try and find an attribute which overrides the given error type in the form of errorType-err-type="someMsgKey"
526
566
errorType += '-err-type' ;
527
567
568
+
528
569
overrideKey = el . attr ( errorType ) ;
529
570
if ( overrideKey === undefined ) {
530
571
overrideKey = el . attr ( 'data-ng-' + errorType ) || el . attr ( 'ng-' + errorType ) ;
531
572
}
573
+
574
+ if ( overrideKey ) {
575
+ overrideKey = overrideKey . replace ( / [ \W ] / g, '' ) ;
576
+ }
532
577
}
533
578
534
579
return overrideKey ;
728
773
return errorTypeToReturn ;
729
774
} ;
730
775
731
- if ( shouldValidateElement ( el ) && modelCtrl && needsValidation ) {
776
+ if ( ( forceValidation || shouldValidateElement ( el ) ) && modelCtrl && needsValidation ) {
732
777
isValid = ! modelCtrl . $invalid ;
733
778
734
779
if ( isValid ) {
767
812
} ,
768
813
769
814
validateForm = function ( frmElement ) {
770
- var frmValid = true ;
771
- if ( frmElement === undefined ) {
772
- return false ;
815
+ var frmValid = true ,
816
+ frmCtrl = frmElement ? angular . element ( frmElement ) . controller ( 'form' ) : undefined ,
817
+ processElement = function ( ctrlElement , force ) {
818
+ var controller , isValid ;
819
+ ctrlElement = angular . element ( ctrlElement ) ;
820
+ controller = ctrlElement . controller ( 'ngModel' ) ;
821
+
822
+ if ( controller !== undefined && ( force || shouldValidateElement ( ctrlElement ) ) ) {
823
+ if ( ctrlElement [ 0 ] . nodeName . toLowerCase ( ) === 'form' ) {
824
+ // we probably have a sub form
825
+ validateForm ( ctrlElement ) ;
826
+ } else {
827
+ isValid = validateElement ( controller , ctrlElement , true ) ;
828
+ frmValid = frmValid && isValid ;
829
+ }
830
+ }
831
+ } ;
832
+
833
+ if ( frmElement === undefined || ( frmCtrl !== undefined && frmCtrl . disableDynamicValidation ) ) {
834
+ return frmElement !== undefined ;
773
835
}
774
836
775
837
angular . forEach ( frmElement [ 0 ] , function ( ctrlElement ) {
776
- var controller , isValid ;
777
- ctrlElement = angular . element ( ctrlElement ) ;
778
- controller = ctrlElement . controller ( 'ngModel' ) ;
779
-
780
- if ( controller !== undefined && shouldValidateElement ( ctrlElement ) ) {
781
- if ( ctrlElement [ 0 ] . nodeName . toLowerCase ( ) === 'form' ) {
782
- // we probably have a sub form
783
- validateForm ( ctrlElement ) ;
784
- } else {
785
- isValid = validateElement ( controller , ctrlElement , true ) ;
786
- frmValid = frmValid && isValid ;
787
- }
788
- }
838
+ processElement ( ctrlElement ) ;
789
839
} ) ;
790
840
841
+ // If you have a custom form control that should be validated i.e.
842
+ // <my-custom-element>...</my-custom-element> it will not be part of the forms
843
+ // HTMLFormControlsCollection and thus won't be included in the above element iteration although
844
+ // it will be on the Angular FormController (if it has a name attribute). So adding the directive
845
+ // register-custom-form-control="" to the control root and autoValidate will include it in this
846
+ // iteration.
847
+ if ( frmElement [ 0 ] . customHTMLFormControlsCollection ) {
848
+ angular . forEach ( frmElement [ 0 ] . customHTMLFormControlsCollection , function ( ctrlElement ) {
849
+ // need to force the validation as the element might not be a known form input type
850
+ // so the normal validation process will ignore it.
851
+ processElement ( ctrlElement , true ) ;
852
+ } ) ;
853
+ }
854
+
791
855
return frmValid ;
856
+ } ,
857
+
858
+ setElementValidationError = function ( element , errorMsgKey , errorMsg ) {
859
+ if ( errorMsgKey ) {
860
+ validator . getErrorMessage ( errorMsgKey , element ) . then ( function ( msg ) {
861
+ validator . makeInvalid ( element , msg ) ;
862
+ } ) ;
863
+ } else {
864
+ validator . makeInvalid ( element , errorMsg ) ;
865
+ }
792
866
} ;
793
867
794
868
return {
869
+ setElementValidationError : setElementValidationError ,
795
870
validateElement : validateElement ,
796
871
validateForm : validateForm ,
797
872
resetElement : resetElement ,
823
898
] ) ;
824
899
} ( angular ) ) ;
825
900
901
+ ( function ( angular ) {
902
+ 'use strict' ;
903
+
904
+ angular . module ( 'jcs-autoValidate' ) . directive ( 'registerCustomFormControl' , [
905
+
906
+ function ( ) {
907
+ var findParentForm = function ( el ) {
908
+ var parent = el ;
909
+ for ( var i = 0 ; i <= 10 ; i += 1 ) {
910
+ if ( parent !== undefined && parent . nodeName . toLowerCase ( ) === 'form' ) {
911
+ break ;
912
+ } else if ( parent !== undefined ) {
913
+ parent = angular . element ( parent ) . parent ( ) [ 0 ] ;
914
+ }
915
+ }
916
+
917
+ return parent ;
918
+ } ;
919
+
920
+ return {
921
+ restrict : 'A' ,
922
+ link : function ( scope , element ) {
923
+ var frmEl = findParentForm ( element . parent ( ) [ 0 ] ) ;
924
+ if ( frmEl ) {
925
+ frmEl . customHTMLFormControlsCollection = frmEl . customHTMLFormControlsCollection || [ ] ;
926
+ frmEl . customHTMLFormControlsCollection . push ( element [ 0 ] ) ;
927
+ }
928
+ }
929
+ } ;
930
+ }
931
+ ] ) ;
932
+ } ( angular ) ) ;
933
+
934
+ ( function ( angular ) {
935
+ 'use strict' ;
936
+
937
+ angular . module ( 'jcs-autoValidate' ) . directive ( 'disableDynamicValidation' , [
938
+
939
+ function ( ) {
940
+ return {
941
+ restrict : 'A' ,
942
+ require : 'form' ,
943
+ compile : function ( ) {
944
+ return {
945
+ pre : function ( scope , element , attrs , ctrl ) {
946
+ ctrl . disableDynamicValidation = true ;
947
+ }
948
+ } ;
949
+ }
950
+ } ;
951
+ }
952
+ ] ) ;
953
+ } ( angular ) ) ;
954
+
826
955
( function ( angular ) {
827
956
'use strict' ;
828
957
873
1002
directive . compile = function ( ) {
874
1003
return function ( scope , element , attrs , ctrls ) {
875
1004
var ngModelCtrl = ctrls [ 0 ] ,
1005
+ frmCtrl = ctrls [ 1 ] ,
876
1006
supportsNgModelOptions = angular . version . major >= 1 && angular . version . minor >= 3 ,
877
1007
ngModelOptions = attrs . ngModelOptions === undefined ? undefined : scope . $eval ( attrs . ngModelOptions ) ,
878
1008
setValidity = ngModelCtrl . $setValidity ,
887
1017
ngModelOptions = ngModelCtrl . $options === undefined ? undefined : ngModelCtrl . $options ;
888
1018
}
889
1019
890
- if ( attrs . formnovalidate === undefined ) {
1020
+ if ( attrs . formnovalidate === undefined || ( frmCtrl !== undefined && frmCtrl . disableDynamicValidation !== true ) ) {
891
1021
if ( supportsNgModelOptions || ngModelOptions === undefined || ngModelOptions . updateOn === undefined || ngModelOptions . updateOn === '' ) {
892
1022
ngModelCtrl . $setValidity = function ( validationErrorKey , isValid ) {
893
1023
setValidity . call ( ngModelCtrl , validationErrorKey , isValid ) ;
903
1033
} ) ;
904
1034
}
905
1035
906
- // We override this so
1036
+ // We override this so we can reset the element state when it is called.
907
1037
ngModelCtrl . $setPristine = function ( ) {
908
1038
setPristine . call ( ngModelCtrl ) ;
909
1039
validationManager . resetElement ( element ) ;
917
1047
} else {
918
1048
link . apply ( this , arguments ) ;
919
1049
}
1050
+
1051
+ ngModelCtrl . setExternalValidation = function ( errorMsgKey , errorMessage , addToModelErrors ) {
1052
+ if ( addToModelErrors ) {
1053
+ ngModelCtrl . $errors [ errorMsgKey ] = false ;
1054
+ }
1055
+
1056
+ validationManager . setElementValidationError ( element , errorMsgKey , errorMessage ) ;
1057
+ } ;
1058
+
1059
+ if ( frmCtrl ) {
1060
+ frmCtrl . setExternalValidation = function ( modelProperty , errorMsgKey , errorMessageOverride , addToModelErrors ) {
1061
+ var success = false ;
1062
+ if ( frmCtrl [ modelProperty ] ) {
1063
+ frmCtrl [ modelProperty ] . setExternalValidation ( errorMsgKey , errorMessageOverride , addToModelErrors ) ;
1064
+ success = true ;
1065
+ }
1066
+
1067
+ return success ;
1068
+ } ;
1069
+ }
920
1070
} ;
921
1071
} ;
922
1072
943
1093
validator . setDefaultElementModifier ( bootstrap3ElementModifier . key ) ;
944
1094
}
945
1095
] ) ;
946
- } ( angular ) ) ;
1096
+ } ( angular ) ) ;
0 commit comments