/**
 * Created by acr on 4/14/2015.
 */
var module = angular.module('ngValidateModule',[]);

module
    .directive('ngValidate', function ($log,$compile,ngValidateFactory) {

        var validationFunction = function (scope, element, attrs, ctrl) {

            //Validate as invisible elements as Valid
            //check controller visibility-Jquery style (visible if width>0 & height>0, visibility hidden considered visible)
            if(!(element.prop('offsetWidth')>0 && element.prop('offsetHeight')>0)){
                ctrl.$setValidity("notVisibleValidation",true);
                return;
            }

            var strategy = attrs.ngValidate;
            var validationCase = ngValidateFactory.strategies[strategy];

            $log.info('validating element:');
            $log.info(element);
            $log.info("with strategy: " + strategy);

            if(!validationCase || !angular.isArray(validationCase) || validationCase.length==0){
                $log.info("Invalid validation case. Validating as true.");
                ctrl.$setValidity("emptyValidation",true);
                return;
            }

            var isValid,errorMessage,callFunction;
            for(var i= 0,l=validationCase.length;i<l;++i){
                if(angular.isFunction(validationCase[i].value)){
                    isValid = validationCase[i].value(element.val());
                }else if(angular.isArray(validationCase[i].value)){
                    var argumentsArray = validationCase[i].value.slice(1);
                    argumentsArray.unshift(element.val());
                    isValid = validationCase[i].value[0].apply(null,argumentsArray);
                }

                ctrl.$setValidity(strategy +"-"+ i,isValid);
                if(!isValid){
                    errorMessage = validationCase[i].message || "";
                    break;
                }
            }
            scope.errorStatus  = !isValid;
            scope.errorMessage = errorMessage;
            scope.$apply();

        };

        return {
            require: 'ngModel',
            scope: true,
            link: function (scope, element, attrs, ctrl) {
                element.after($compile(angular.element('<span ng-show="errorStatus" ng-bind="errorMessage"></span>'))(scope));
                scope.$on('ng-validate',function(){validationFunction(scope, element, attrs, ctrl)});
                element.on('blur',function(){
                    validationFunction(scope, element, attrs, ctrl);
                })
            }
        };


    })

.factory('ngValidateFactory',function(){
        var ngValidate = {};

        //generic function example
        ngValidate.allowedChars = function(){
            return true;
        };

        ngValidate.minLength = function(testVal,expectedVal){
            return testVal.length >= expectedVal;
        };

        ngValidate.maxLength = function(testVal,expectedVal){
            return testVal.length <= expectedVal;
        };

        ngValidate.required = function(testVal){
            return !!testVal;
        };

        ngValidate.pattern = function(testVal,patternval){
            return patternval.test(testVal);
        };

        ngValidate.emailPattern = function(testVal){
            return pattern(testVal,/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/);
        };

        ngValidate.equalTo = function(testVal,expectedVal){
            return testVal === expectedVal;
        };

        ngValidate.strategies = {};

        //Default Strategies
        ngValidate.strategies.required = [{
            value:ngValidate.required,
            message:'This Field is required'
        }];

        ngValidate.strategies.minLength = [{
            value:[ngValidate.minLength,8],
            message:'Minimum 8 characters required'
        }];

        ngValidate.strategies.maxLength = [{
            value:[ngValidate.maxLength,32],
            message:'Maximum 32 characters allowed'
        }];

        ngValidate.strategies.email = [{
            value:[ngValidate.maxLength,32],
            message:'Please enter valid email address'
        }];

        return ngValidate;

    })
@@ -234,24 +234,39 @@
  attrs, ctrl
+, fromBroadcast
 ) %7B%0A%0A       
@@ -616,32 +616,222 @@
 %0A            %7D%0A%0A
+            //Validate as disabled elements as Valid%0A            if(!!attrs.disabled)%7B%0A                ctrl.$setValidity(%22notVisibleValidation%22,true);%0A                return;%0A            %7D%0A%0A
             var 
@@ -929,24 +929,114 @@
 strategy%5D;%0A%0A
+            //TODO case:arg syntax for minlength:length, maxlength:length, pattern:regex%0A%0A
             
@@ -2287,32 +2287,51 @@
 age;%0A           
+ if(!fromBroadcast)
  scope.$apply();
@@ -2701,16 +2701,22 @@
 rs, ctrl
+, true
 )%7D);%0A   
@@ -2824,16 +2824,23 @@
 rs, ctrl
+, false
 );%0A     

Add disabled element check. Add broadcast check