Browse Source

#146: Add validateFieldElement

nghuuphuoc 12 years ago
parent
commit
92632c6994
1 changed files with 88 additions and 58 deletions
  1. 88 58
      src/js/bootstrapValidator.js

+ 88 - 58
src/js/bootstrapValidator.js

@@ -18,12 +18,13 @@
         this.invalidField  = null;  // First invalid field
         this.$submitButton = null;  // The submit button which is clicked to submit form
 
-        this._init();
-
+        // Validating status
         this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED';
         this.STATUS_VALIDATING    = 'VALIDATING';
         this.STATUS_INVALID       = 'INVALID';
         this.STATUS_VALID         = 'VALID';
+
+        this._init();
     };
 
     // The default options
@@ -196,59 +197,69 @@
                 delete this.options.fields[field];
                 return;
             }
+            for (var validatorName in this.options.fields[field].validators) {
+                if (!$.fn.bootstrapValidator.validators[validatorName]) {
+                    delete this.options.fields[field].validators[validatorName];
+                }
+            }
 
             // Set the attribute to indicate the fields which are defined by selector
-            if (fields.attr('data-bv-field')) {
+            if (!fields.attr('data-bv-field')) {
                 fields.attr('data-bv-field', field);
             }
 
-            // Create help block elements for showing the error messages
-            var $field   = $(fields[0]),
-                $parent  = $field.parents('.form-group'),
-                // Allow user to indicate where the error messages are shown
-                $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field);
+            var that      = this,
+                type      = fields.attr('type'),
+                event     = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup',
+                total     = fields.length,
+                updateAll = (total == 1) || ('radio' == type || 'checkbox' == type);
+
+            for (var i = 0; i < total; i++) {
+                var $field   = $(fields[i]),
+                    $parent  = $field.parents('.form-group'),
+                    // Allow user to indicate where the error messages are shown
+                    $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field);
+
+                // Whenever the user change the field value, mark it as not validated yet
+                $field.on(event + '.bv', function() {
+                    that.updateStatus(updateAll ? field : $(this), that.STATUS_NOT_VALIDATED, null);
+                });
 
-            $field.data('bootstrapValidator.messageContainer', $message);
-            for (var validatorName in this.options.fields[field].validators) {
-                if (!$.fn.bootstrapValidator.validators[validatorName]) {
-                    delete this.options.fields[field].validators[validatorName];
-                    continue;
+                // Create help block elements for showing the error messages
+                $field.data('bootstrapValidator.messageContainer', $message);
+                for (validatorName in this.options.fields[field].validators) {
+                    $field.data('bv.result.' + validatorName, this.STATUS_NOT_VALIDATED);
+                    //this.results[field][validatorName] = this.STATUS_NOT_VALIDATED;
+
+                    if (!updateAll || i == total - 1) {
+                        $('<small/>')
+                            //.css('display', 'none')
+                            .attr('data-bv-validator', validatorName)
+                            .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message)
+                            .addClass('help-block')
+                            .appendTo($message);
+                    }
                 }
 
-                this.results[field][validatorName] = this.STATUS_NOT_VALIDATED;
-                $('<small/>')
-                    .css('display', 'none')
-                    .attr('data-bv-validator', validatorName)
-                    .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message)
-                    .addClass('help-block')
-                    .appendTo($message);
-            }
-
-            // Prepare the feedback icons
-            // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation)
-            if (this.options.feedbackIcons
-                && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid)
-            {
-                $parent.addClass('has-feedback');
-                var $icon = $('<i/>').css('display', 'none').addClass('form-control-feedback').attr('data-bv-field', field).insertAfter($(fields[fields.length - 1]));
-                // The feedback icon does not render correctly if there is no label
-                // https://github.com/twbs/bootstrap/issues/12873
-                if ($parent.find('label').length == 0) {
-                    $icon.css('top', 0);
+                // Prepare the feedback icons
+                // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation)
+                if (this.options.feedbackIcons
+                    && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid
+                    && (!updateAll || i == total - 1))
+                {
+                    $parent.addClass('has-feedback');
+                    var $icon = $('<i/>').css('display', 'none').addClass('form-control-feedback').attr('data-bv-field', field).insertAfter($field);
+                    // The feedback icon does not render correctly if there is no label
+                    // https://github.com/twbs/bootstrap/issues/12873
+                    if ($parent.find('label').length == 0) {
+                        $icon.css('top', 0);
+                    }
                 }
             }
 
             if (this.options.fields[field]['enabled'] == null) {
                 this.options.fields[field]['enabled'] = true;
             }
-
-            // Whenever the user change the field value, mark it as not validated yet
-            var that  = this,
-                type  = fields.attr('type'),
-                event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup';
-            fields.on(event + '.bootstrapValidator', function() {
-                that.updateStatus($field, that.STATUS_NOT_VALIDATED, null);
-            });
         },
 
         /**
@@ -289,17 +300,21 @@
                     (function(f) {
                         var fields = that.getFieldElements(f);
                         if (fields) {
-                            var type    = fields.attr('type'),
-                                trigger = that.options.fields[field].trigger
-                                        || that.options.trigger
-                                        || (('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup'),
-                                events  = trigger.split(' ').map(function(item) {
-                                    return item + '.bootstrapValidator';
+                            var type      = fields.attr('type'),
+                                total     = fields.length,
+                                updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type),
+                                trigger   = that.options.fields[field].trigger
+                                            || that.options.trigger
+                                            || (('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup'),
+                                events    = trigger.split(' ').map(function(item) {
+                                    return item + '.bv';
                                 }).join(' ');
 
-                            fields.on(events, function() {
-                                that.validateField(f);
-                            });
+                            for (var i = 0; i < total; i++) {
+                                $(fields[i]).on(events, function () {
+                                    updateAll ? that.validateField(f) : that.validateFieldElement($(this));
+                                });
+                            }
                         }
                     })(field);
                 }
@@ -385,24 +400,37 @@
         /**
          * Validate given field
          *
-         * @param {String} field The field name
+         * @param {String} field The field element
+         * @returns {BootstrapValidator}
          */
         validateField: function(field) {
-            if (!this.options.fields[field]['enabled']) {
-                return;
+            var fields = this.getFieldElements(field),
+                type   = fields.attr('type'),
+                n      = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length;
+
+            for (var i = 0; i < n; i++) {
+                this.validateFieldElement($(fields[i]));
             }
 
+            return this;
+        },
+
+        /**
+         * Validate field element
+         *
+         * @param {jQuery} $field The field element
+         * @returns {BootstrapValidator}
+         */
+        validateFieldElement: function($field) {
             var that       = this,
-                fields     = this.getFieldElements(field),
-                $field     = $(fields[0]),
+                field      = $field.attr('data-bv-field'),
                 validators = this.options.fields[field].validators,
                 validatorName,
                 validateResult;
 
             // We don't need to validate disabled field
-            if (fields.length == 1 && fields.is(':disabled')) {
-                delete this.options.fields[field];
-                return;
+            if ($field.is(':disabled')) {
+                return this;
             }
 
             for (validatorName in validators) {
@@ -435,6 +463,8 @@
                     this.updateStatus($field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName);
                 }
             }
+
+            return this;
         },
 
         /**