Browse Source

#175: Showing errors in tooltip or popover

nghuuphuoc 11 years ago
parent
commit
e14bb6c35a

+ 1 - 0
CHANGELOG.md

@@ -5,6 +5,7 @@
 * [#121](https://github.com/nghuuphuoc/bootstrapvalidator/issues/121): Add events for form validate successfully or not
 * [#195](https://github.com/nghuuphuoc/bootstrapvalidator/issues/195): Add events for field validation
 * [#164](https://github.com/nghuuphuoc/bootstrapvalidator/issues/164): Add ```container``` option for indicating the element showing all errors
+* [#175](https://github.com/nghuuphuoc/bootstrapvalidator/issues/175): Showing errors in tooltip or popover
 * [#211](https://github.com/nghuuphuoc/bootstrapvalidator/issues/211), [#235](https://github.com/nghuuphuoc/bootstrapvalidator/issues/235): Add new method ```getInvalidFields()``` that returns all invalid fields
 
 ## v0.4.5 (2015-05-15)

+ 1 - 1
demo/container2.html

@@ -16,7 +16,7 @@
             <section>
                 <div class="col-lg-8 col-lg-offset-2">
                     <div class="page-header">
-                        <h2><code>container</code> example</h2>
+                        <h2>Showing errors in custom container</h2>
                     </div>
 
                     <form id="defaultForm" method="post" class="form-horizontal" action="target.php">

+ 177 - 0
demo/container3.html

@@ -0,0 +1,177 @@
+<!DOCTYPE html>
+<html>
+<head>
+    <title>BootstrapValidator demo</title>
+
+    <link rel="stylesheet" href="../vendor/bootstrap/css/bootstrap.css"/>
+    <link rel="stylesheet" href="../dist/css/bootstrapValidator.css"/>
+    <script type="text/javascript" src="../vendor/jquery/jquery-1.10.2.min.js"></script>
+    <script type="text/javascript" src="../vendor/bootstrap/js/bootstrap.min.js"></script>
+    <script type="text/javascript" src="../dist/js/bootstrapValidator.js"></script>
+</head>
+<body>
+    <div class="container">
+        <div class="row">
+            <div class="col-lg-8 col-lg-offset-2">
+                <div class="page-header">
+                    <h2>Showing errors in tooltip or popover</h2>
+                </div>
+
+                <form id="defaultForm" method="post" class="form-horizontal" action="target.php">
+                    <div class="form-group">
+                        <label class="col-lg-3 control-label">Full name</label>
+                        <div class="col-lg-4">
+                            <input type="text" class="form-control" name="firstName" placeholder="First name" />
+                        </div>
+                        <div class="col-lg-4">
+                            <input type="text" class="form-control" name="lastName" placeholder="Last name" />
+                        </div>
+                    </div>
+
+                    <div class="form-group">
+                        <label class="col-lg-3 control-label">Username</label>
+                        <div class="col-lg-5">
+                            <input type="text" class="form-control" name="username" />
+                        </div>
+                    </div>
+
+                    <div class="form-group">
+                        <label class="col-lg-3 control-label">Email address</label>
+                        <div class="col-lg-5">
+                            <input type="text" class="form-control" name="email" />
+                        </div>
+                    </div>
+
+                    <div class="form-group">
+                        <label class="col-lg-3 control-label">Password</label>
+                        <div class="col-lg-5">
+                            <input type="password" class="form-control" name="password" />
+                        </div>
+                    </div>
+
+                    <div class="form-group">
+                        <label class="col-lg-3 control-label">Gender</label>
+                        <div class="col-lg-5">
+                            <div class="radio">
+                                <label>
+                                    <input type="radio" name="gender" value="male" /> Male
+                                </label>
+                            </div>
+                            <div class="radio">
+                                <label>
+                                    <input type="radio" name="gender" value="female" /> Female
+                                </label>
+                            </div>
+                            <div class="radio">
+                                <label>
+                                    <input type="radio" name="gender" value="other" /> Other
+                                </label>
+                            </div>
+                        </div>
+                    </div>
+
+                    <div class="form-group">
+                        <div class="col-lg-9 col-lg-offset-3">
+                            <button type="submit" class="btn btn-primary" name="signup" value="Sign up">Sign up</button>
+                        </div>
+                    </div>
+                </form>
+            </div>
+        </div>
+    </div>
+
+<script type="text/javascript">
+$(document).ready(function() {
+    $('#defaultForm').bootstrapValidator({
+        message: 'This value is not valid',
+        container: 'tooltip',
+        feedbackIcons: {
+            valid: 'glyphicon glyphicon-ok',
+            invalid: 'glyphicon glyphicon-remove',
+            validating: 'glyphicon glyphicon-refresh'
+        },
+        fields: {
+            firstName: {
+                validators: {
+                    notEmpty: {
+                        message: 'The first name is required and cannot be empty'
+                    },
+                    stringCase: {
+                        message: 'The first name must contain upper case characters only',
+                        case: 'upper'
+                    },
+                    regexp: {
+                        regexp: /^[A-Z\s]+$/i,
+                        message: 'The first name can only consist of alphabetical characters and spaces'
+                    }
+                }
+            },
+            lastName: {
+                validators: {
+                    notEmpty: {
+                        message: 'The last name is required and cannot be empty'
+                    },
+                    stringCase: {
+                        message: 'The last name must contain upper case characters only',
+                        case: 'upper'
+                    },
+                    regexp: {
+                        regexp: /^[A-Z\s]+$/i,
+                        message: 'The last name can only consist of alphabetical characters and spaces'
+                    }
+                }
+            },
+            username: {
+                message: 'The username is not valid',
+                validators: {
+                    notEmpty: {
+                        message: 'The username is required and cannot be empty'
+                    },
+                    stringLength: {
+                        min: 6,
+                        max: 30,
+                        message: 'The username must be more than 6 and less than 30 characters long'
+                    },
+                    regexp: {
+                        regexp: /^[a-zA-Z0-9_\.]+$/,
+                        message: 'The username can only consist of alphabetical, number, dot and underscore'
+                    },
+                    different: {
+                        field: 'password',
+                        message: 'The username and password cannot be the same as each other'
+                    }
+                }
+            },
+            email: {
+                container: 'popover',
+                validators: {
+                    emailAddress: {
+                        message: 'The input is not a valid email address'
+                    }
+                }
+            },
+            password: {
+                container: 'popover',
+                validators: {
+                    notEmpty: {
+                        message: 'The password is required and cannot be empty'
+                    },
+                    different: {
+                        field: 'username',
+                        message: 'The password cannot be the same as username'
+                    }
+                }
+            },
+            gender: {
+                validators: {
+                    notEmpty: {
+                        message: 'The gender is required'
+                    }
+                }
+            }
+        }
+    });
+});
+</script>
+</body>
+</html>

+ 8 - 0
dist/css/bootstrapValidator.css

@@ -17,3 +17,11 @@
 .nav-tabs li.bv-tab-error > a {
     color: #a94442;
 }
+.bv-form .tooltip-inner {
+    text-align: left;
+}
+.bv-form .tooltip-inner ul {
+    list-style: square;
+    margin: 0;
+    padding: 0;
+}

+ 1 - 1
dist/css/bootstrapValidator.min.css

@@ -10,4 +10,4 @@
  */
 
 
-.bv-form .help-block{margin-bottom:0}.nav-tabs li.bv-tab-success>a{color:#3c763d}.nav-tabs li.bv-tab-error>a{color:#a94442}
+.bv-form .help-block{margin-bottom:0}.nav-tabs li.bv-tab-success>a{color:#3c763d}.nav-tabs li.bv-tab-error>a{color:#a94442}.bv-form .tooltip-inner{text-align:left}.bv-form .tooltip-inner ul{list-style:square;margin:0;padding:0}

+ 76 - 16
dist/js/bootstrapValidator.js

@@ -290,9 +290,9 @@
                 $parent   = $field.parents('.form-group'),
                 // Allow user to indicate where the error messages are shown
                 container = this.options.fields[field].container || this.options.container,
-                $message  = container ? $(container) : this._getMessageContainer($field);
+                $message  = (container && ['tooltip', 'popover'].indexOf(container) == -1) ? $(container) : this._getMessageContainer($field);
 
-            if (container) {
+            if (container && ['tooltip', 'popover'].indexOf(container) == -1) {
                 $message.addClass('has-error');
             }
 
@@ -715,12 +715,14 @@
          * @returns {BootstrapValidator}
          */
         updateElementStatus: function($field, status, validatorName) {
-            var that     = this,
-                field    = $field.attr('data-bv-field'),
-                $parent  = $field.parents('.form-group'),
-                $message = $field.data('bv.messages'),
-                $errors  = $message.find('.help-block[data-bv-validator][data-bv-for="' + field + '"]'),
-                $icon    = $parent.find('.form-control-feedback[data-bv-icon-for="' + field + '"]');
+            var that       = this,
+                field      = $field.attr('data-bv-field'),
+                $parent    = $field.parents('.form-group'),
+                $message   = $field.data('bv.messages'),
+                $allErrors = $message.find('.help-block[data-bv-validator][data-bv-for="' + field + '"]'),
+                $errors    = validatorName ? $allErrors.filter('[data-bv-validator="' + validatorName + '"]') : $allErrors,
+                $icon      = $parent.find('.form-control-feedback[data-bv-icon-for="' + field + '"]'),
+                container  = this.options.fields[field].container || this.options.container;
 
             // Update status
             if (validatorName) {
@@ -740,38 +742,64 @@
             }
 
             // Show/hide error elements and feedback icons
-            validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').attr('data-bv-result', status) : $errors.attr('data-bv-result', status);
+            $errors.attr('data-bv-result', status);
             switch (status) {
                 case this.STATUS_VALIDATING:
                     this.disableSubmitButtons(true);
                     $parent.removeClass('has-success').removeClass('has-error');
-                    // TODO: Show validating message
-                    validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide();
                     if ($icon) {
                         $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show();
                     }
                     if ($tab) {
                         $tab.removeClass('bv-tab-success').removeClass('bv-tab-error');
                     }
+                    switch (true) {
+                        case ($icon && 'tooltip' == container):
+                            $icon.css('cursor', '').tooltip('destroy');
+                            break;
+                        case ($icon && 'popover' == container):
+                            $icon.css('cursor', '').popover('destroy');
+                            break;
+                        default:
+                            $errors.hide();
+                            break;
+                    }
                     break;
 
                 case this.STATUS_INVALID:
                     this.disableSubmitButtons(true);
                     $parent.removeClass('has-success').addClass('has-error');
-                    validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').show() : $errors.show();
                     if ($icon) {
                         $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show();
                     }
                     if ($tab) {
                         $tab.removeClass('bv-tab-success').addClass('bv-tab-error');
                     }
+                    switch (true) {
+                        case ($icon && 'tooltip' == container):
+                            $icon.css('cursor', 'pointer').tooltip('destroy').tooltip({
+                                html: true,
+                                placement: 'top',
+                                title: $allErrors.filter('[data-bv-result="' + that.STATUS_INVALID + '"]').eq(0).html()
+                            });
+                            break;
+                        case ($icon && 'popover' == container):
+                            $icon.css('cursor', 'pointer').popover('destroy').popover({
+                                content: $allErrors.filter('[data-bv-result="' + that.STATUS_INVALID + '"]').eq(0).html(),
+                                html: true,
+                                placement: 'top',
+                                trigger: 'hover click'
+                            });
+                            break;
+                        default:
+                            $errors.show();
+                            break;
+                    }
                     break;
 
                 case this.STATUS_VALID:
-                    validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide();
-
                     // If the field is valid (passes all validators)
-                    var validField = $errors.filter(function() {
+                    var validField = $allErrors.filter(function() {
                                         var v = $(this).attr('data-bv-validator');
                                         return $field.data('bv.result.' + v) != that.STATUS_VALID;
                                     }).length == 0;
@@ -813,19 +841,51 @@
                     if ($tab) {
                         $tab.removeClass('bv-tab-success').removeClass('bv-tab-error').addClass(isValidContainer($tabPane) ? 'bv-tab-success' : 'bv-tab-error');
                     }
+                    switch (true) {
+                        case ($icon && 'tooltip' == container):
+                            validField ? $icon.css('cursor', '').tooltip('destroy')
+                                       : $icon.css('cursor', 'pointer').tooltip('destroy').tooltip({
+                                            html: true,
+                                            placement: 'top',
+                                            title: $allErrors.filter('[data-bv-result="' + that.STATUS_INVALID + '"]').eq(0).html()
+                                        });
+                            break;
+                        case ($icon && 'popover' == container):
+                            validField ? $icon.css('cursor', '').popover('destroy')
+                                       : $icon.css('cursor', 'pointer').popover('destroy').popover({
+                                            content: $allErrors.filter('[data-bv-result="' + that.STATUS_INVALID + '"]').eq(0).html(),
+                                            html: true,
+                                            placement: 'top',
+                                            trigger: 'click'
+                                        });
+                            break;
+                        default:
+                            $errors.hide();
+                            break;
+                    }
                     break;
 
                 case this.STATUS_NOT_VALIDATED:
                 default:
                     this.disableSubmitButtons(false);
                     $parent.removeClass('has-success').removeClass('has-error');
-                    validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide();
                     if ($icon) {
                         $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide();
                     }
                     if ($tab) {
                         $tab.removeClass('bv-tab-success').removeClass('bv-tab-error');
                     }
+                    switch (true) {
+                        case ($icon && 'tooltip' == container):
+                            $icon.css('cursor', '').tooltip('destroy');
+                            break;
+                        case ($icon && 'popover' == container):
+                            $icon.css('cursor', '').popover('destroy');
+                            break;
+                        default:
+                            $errors.hide();
+                            break;
+                    }
                     break;
             }
 

File diff suppressed because it is too large
+ 2 - 2
dist/js/bootstrapValidator.min.js


+ 8 - 0
src/css/bootstrapValidator.css

@@ -17,3 +17,11 @@
 .nav-tabs li.bv-tab-error > a {
     color: #a94442;
 }
+.bv-form .tooltip-inner {
+    text-align: left;
+}
+.bv-form .tooltip-inner ul {
+    list-style: square;
+    margin: 0;
+    padding: 0;
+}

+ 76 - 16
src/js/bootstrapValidator.js

@@ -289,9 +289,9 @@
                 $parent   = $field.parents('.form-group'),
                 // Allow user to indicate where the error messages are shown
                 container = this.options.fields[field].container || this.options.container,
-                $message  = container ? $(container) : this._getMessageContainer($field);
+                $message  = (container && ['tooltip', 'popover'].indexOf(container) == -1) ? $(container) : this._getMessageContainer($field);
 
-            if (container) {
+            if (container && ['tooltip', 'popover'].indexOf(container) == -1) {
                 $message.addClass('has-error');
             }
 
@@ -714,12 +714,14 @@
          * @returns {BootstrapValidator}
          */
         updateElementStatus: function($field, status, validatorName) {
-            var that     = this,
-                field    = $field.attr('data-bv-field'),
-                $parent  = $field.parents('.form-group'),
-                $message = $field.data('bv.messages'),
-                $errors  = $message.find('.help-block[data-bv-validator][data-bv-for="' + field + '"]'),
-                $icon    = $parent.find('.form-control-feedback[data-bv-icon-for="' + field + '"]');
+            var that       = this,
+                field      = $field.attr('data-bv-field'),
+                $parent    = $field.parents('.form-group'),
+                $message   = $field.data('bv.messages'),
+                $allErrors = $message.find('.help-block[data-bv-validator][data-bv-for="' + field + '"]'),
+                $errors    = validatorName ? $allErrors.filter('[data-bv-validator="' + validatorName + '"]') : $allErrors,
+                $icon      = $parent.find('.form-control-feedback[data-bv-icon-for="' + field + '"]'),
+                container  = this.options.fields[field].container || this.options.container;
 
             // Update status
             if (validatorName) {
@@ -739,38 +741,64 @@
             }
 
             // Show/hide error elements and feedback icons
-            validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').attr('data-bv-result', status) : $errors.attr('data-bv-result', status);
+            $errors.attr('data-bv-result', status);
             switch (status) {
                 case this.STATUS_VALIDATING:
                     this.disableSubmitButtons(true);
                     $parent.removeClass('has-success').removeClass('has-error');
-                    // TODO: Show validating message
-                    validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide();
                     if ($icon) {
                         $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show();
                     }
                     if ($tab) {
                         $tab.removeClass('bv-tab-success').removeClass('bv-tab-error');
                     }
+                    switch (true) {
+                        case ($icon && 'tooltip' == container):
+                            $icon.css('cursor', '').tooltip('destroy');
+                            break;
+                        case ($icon && 'popover' == container):
+                            $icon.css('cursor', '').popover('destroy');
+                            break;
+                        default:
+                            $errors.hide();
+                            break;
+                    }
                     break;
 
                 case this.STATUS_INVALID:
                     this.disableSubmitButtons(true);
                     $parent.removeClass('has-success').addClass('has-error');
-                    validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').show() : $errors.show();
                     if ($icon) {
                         $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show();
                     }
                     if ($tab) {
                         $tab.removeClass('bv-tab-success').addClass('bv-tab-error');
                     }
+                    switch (true) {
+                        case ($icon && 'tooltip' == container):
+                            $icon.css('cursor', 'pointer').tooltip('destroy').tooltip({
+                                html: true,
+                                placement: 'top',
+                                title: $allErrors.filter('[data-bv-result="' + that.STATUS_INVALID + '"]').eq(0).html()
+                            });
+                            break;
+                        case ($icon && 'popover' == container):
+                            $icon.css('cursor', 'pointer').popover('destroy').popover({
+                                content: $allErrors.filter('[data-bv-result="' + that.STATUS_INVALID + '"]').eq(0).html(),
+                                html: true,
+                                placement: 'top',
+                                trigger: 'hover click'
+                            });
+                            break;
+                        default:
+                            $errors.show();
+                            break;
+                    }
                     break;
 
                 case this.STATUS_VALID:
-                    validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide();
-
                     // If the field is valid (passes all validators)
-                    var validField = $errors.filter(function() {
+                    var validField = $allErrors.filter(function() {
                                         var v = $(this).attr('data-bv-validator');
                                         return $field.data('bv.result.' + v) != that.STATUS_VALID;
                                     }).length == 0;
@@ -812,19 +840,51 @@
                     if ($tab) {
                         $tab.removeClass('bv-tab-success').removeClass('bv-tab-error').addClass(isValidContainer($tabPane) ? 'bv-tab-success' : 'bv-tab-error');
                     }
+                    switch (true) {
+                        case ($icon && 'tooltip' == container):
+                            validField ? $icon.css('cursor', '').tooltip('destroy')
+                                       : $icon.css('cursor', 'pointer').tooltip('destroy').tooltip({
+                                            html: true,
+                                            placement: 'top',
+                                            title: $allErrors.filter('[data-bv-result="' + that.STATUS_INVALID + '"]').eq(0).html()
+                                        });
+                            break;
+                        case ($icon && 'popover' == container):
+                            validField ? $icon.css('cursor', '').popover('destroy')
+                                       : $icon.css('cursor', 'pointer').popover('destroy').popover({
+                                            content: $allErrors.filter('[data-bv-result="' + that.STATUS_INVALID + '"]').eq(0).html(),
+                                            html: true,
+                                            placement: 'top',
+                                            trigger: 'click'
+                                        });
+                            break;
+                        default:
+                            $errors.hide();
+                            break;
+                    }
                     break;
 
                 case this.STATUS_NOT_VALIDATED:
                 default:
                     this.disableSubmitButtons(false);
                     $parent.removeClass('has-success').removeClass('has-error');
-                    validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide();
                     if ($icon) {
                         $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide();
                     }
                     if ($tab) {
                         $tab.removeClass('bv-tab-success').removeClass('bv-tab-error');
                     }
+                    switch (true) {
+                        case ($icon && 'tooltip' == container):
+                            $icon.css('cursor', '').tooltip('destroy');
+                            break;
+                        case ($icon && 'popover' == container):
+                            $icon.css('cursor', '').popover('destroy');
+                            break;
+                        default:
+                            $errors.hide();
+                            break;
+                    }
                     break;
             }