浏览代码

#1033, #1043: Add autoFocus option

Phuoc Nguyen 11 年之前
父节点
当前提交
9458868167

+ 2 - 2
CHANGELOG.md

@@ -12,10 +12,11 @@ __New Features__
 * [#1010](https://github.com/nghuuphuoc/bootstrapvalidator/pull/1010): Add Ireland [postal code](http://bootstrapvalidator.com/validators/zipCode/) validator, thanks to [@zmira](https://github.com/zmira)
 * [#1018](https://github.com/nghuuphuoc/bootstrapvalidator/pull/1018): Add German [phone number](http://bootstrapvalidator.com/validators/phone/) and [postal code](http://bootstrapvalidator.com/validators/zipCode/) validators, thanks to [@jhadenfeldt](https://github.com/jhadenfeldt)
 * [#1022](https://github.com/nghuuphuoc/bootstrapvalidator/pull/1022): Add Portugal [postal code](http://bootstrapvalidator.com/validators/zipCode/) validator, thanks to [@zmira](https://github.com/zmira)
+* [#1033](https://github.com/nghuuphuoc/bootstrapvalidator/issues/1033), [#1043](https://github.com/nghuuphuoc/bootstrapvalidator/issues/1043): Add ```autoFocus``` option
 
 __Improvements__
 * [#823](https://github.com/nghuuphuoc/bootstrapvalidator/issues/823): The [hexColor](http://bootstrapvalidator.com/validators/hexColor/) validator only accepts 6 hex character values when using HTML 5 ```type='color'``` attribute
-* [#864](https://github.com/nghuuphuoc/bootstrapvalidator/pull/864): Coma separator handling in [greaterThan](http://bootstrapvalidator.com/validators/greaterThan/), [lessThan](http://bootstrapvalidator.com/validators/lessThan/) validators, thanks to [@mgibas](https://github.com/mgibas)
+* [#864](https://github.com/nghuuphuoc/bootstrapvalidator/pull/864): Comma separator handling in [greaterThan](http://bootstrapvalidator.com/validators/greaterThan/), [lessThan](http://bootstrapvalidator.com/validators/lessThan/) validators, thanks to [@mgibas](https://github.com/mgibas)
 * [#999](https://github.com/nghuuphuoc/bootstrapvalidator/pull/999), [#1048](https://github.com/nghuuphuoc/bootstrapvalidator/issues/1048): Replace ',' with '.' to validate decimal numbers correct, thanks to [@johanronn77](https://github.com/johanronn77)
 * [#1002](https://github.com/nghuuphuoc/bootstrapvalidator/pull/1002): Put tooltip/popover on bottom if there is not enough space on top, thanks to [@jazzzz](https://github.com/jazzzz)
 * [#1015](https://github.com/nghuuphuoc/bootstrapvalidator/pull/1015): The [remote](http://bootstrapvalidator.com/validators/remote/) validator allows to set ```data``` options via HTML attributes, thanks to [@jazzzz](https://github.com/jazzzz)
@@ -26,7 +27,6 @@ __Bug Fixes__
 * [#933](https://github.com/nghuuphuoc/bootstrapvalidator/issues/933), [#959](https://github.com/nghuuphuoc/bootstrapvalidator/issues/959), [#1047](https://github.com/nghuuphuoc/bootstrapvalidator/issues/1047): Tooltip/popover isn't destroyed when the field is valid
 * [#991](https://github.com/nghuuphuoc/bootstrapvalidator/issues/991): The field is validated only one time when setting ```trigger: 'blur'```, ```container: 'tooltip'```
 * [#1014](https://github.com/nghuuphuoc/bootstrapvalidator/pull/1014): Fix [isValidField()](http://bootstrapvalidator.com/api/#is-valid-field) and [validateField()](http://bootstrapvalidator.com/api/#validate-field) methods for fields without validators, thanks to [@jazzzz](https://github.com/jazzzz)
-* [#1040](https://github.com/nghuuphuoc/bootstrapvalidator/issues/1040), [#1041](https://github.com/nghuuphuoc/bootstrapvalidator/pull/1041): Fix the issue where input with placeholder is auto validated on IE 10, 11, thanks to [@jazzzz](https://github.com/jazzzz)
 * [#1050](https://github.com/nghuuphuoc/bootstrapvalidator/issues/1050): Fix the issue when using multiple fields with same name, the tooltip of the last element is always shown
 * [#1055](https://github.com/nghuuphuoc/bootstrapvalidator/issues/1055), [#1063](https://github.com/nghuuphuoc/bootstrapvalidator/pull/1063): The [error.field.bv](http://bootstrapvalidator.com/settings/#event-field) event isn't triggered if verbose is set to false, thanks to [@shineability](https://github.com/shineability)
 * [#1057](https://github.com/nghuuphuoc/bootstrapvalidator/issues/1057), [#1063](https://github.com/nghuuphuoc/bootstrapvalidator/pull/1063): The [verbose](http://bootstrapvalidator.com/settings/#field-verbose) option for field doesn't override the form level, thanks to [@shineability](https://github.com/shineability)

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

@@ -2,7 +2,7 @@
  * BootstrapValidator (http://bootstrapvalidator.com)
  * The best jQuery plugin to validate form fields. Designed to use with Bootstrap 3
  *
- * @version     v0.5.3-dev, built on 2014-11-03 10:35:05 AM
+ * @version     v0.5.3-dev, built on 2014-11-03 3:09:43 PM
  * @author      https://twitter.com/nghuuphuoc
  * @copyright   (c) 2013 - 2014 Nguyen Huu Phuoc
  * @license     MIT

+ 64 - 56
dist/js/bootstrapValidator.js

@@ -2,7 +2,7 @@
  * BootstrapValidator (http://bootstrapvalidator.com)
  * The best jQuery plugin to validate form fields. Designed to use with Bootstrap 3
  *
- * @version     v0.5.3-dev, built on 2014-11-03 10:35:05 AM
+ * @version     v0.5.3-dev, built on 2014-11-03 3:09:43 PM
  * @author      https://twitter.com/nghuuphuoc
  * @copyright   (c) 2013 - 2014 Nguyen Huu Phuoc
  * @license     MIT
@@ -58,6 +58,7 @@ if (typeof jQuery === 'undefined') {
         _init: function() {
             var that    = this,
                 options = {
+                    autoFocus:      this.$form.attr('data-bv-autofocus'),
                     container:      this.$form.attr('data-bv-container'),
                     events: {
                         formInit:         this.$form.attr('data-bv-events-form-init'),
@@ -214,6 +215,7 @@ if (typeof jQuery === 'undefined') {
             }
 
             var opts = {
+                    autoFocus:     $field.attr('data-bv-autofocus'),
                     container:     $field.attr('data-bv-container'),
                     excluded:      $field.attr('data-bv-excluded'),
                     feedbackIcons: $field.attr('data-bv-feedbackicons'),
@@ -457,11 +459,7 @@ if (typeof jQuery === 'undefined') {
                 case 'enabled':
                 /* falls through */
                 default:
-                    fields.off(events).on(events, function(e) {
-                        // #1040: The input with placeholder is auto validated on IE 10, 11
-                        if ('input' === e.type && document.activeElement !== this) {
-                            return;
-                        }
+                    fields.off(events).on(events, function() {
                         if (that._exceedThreshold($(this))) {
                             that.validateField($(this));
                         }
@@ -650,16 +648,21 @@ if (typeof jQuery === 'undefined') {
                 }
             }
 
-            var $invalidField = this.$invalidFields.eq(0);
-            if ($invalidField) {
-                // Activate the tab containing the invalid field if exists
-                var $tabPane = $invalidField.parents('.tab-pane'), tabId;
-                if ($tabPane && (tabId = $tabPane.attr('id'))) {
-                    $('a[href="#' + tabId + '"][data-toggle="tab"]').tab('show');
-                }
+            // Determined the first invalid field which will be focused on automatically
+            for (var i = 0; i < this.$invalidFields.length; i++) {
+                var $field    = this.$invalidFields.eq(i),
+                    autoFocus = this._isOptionEnabled($field.attr('data-bv-field'), 'autoFocus');
+                if (autoFocus) {
+                    // Activate the tab containing the field if exists
+                    var $tabPane = $field.parents('.tab-pane'), tabId;
+                    if ($tabPane && (tabId = $tabPane.attr('id'))) {
+                        $('a[href="#' + tabId + '"][data-toggle="tab"]').tab('show');
+                    }
 
-                // Focus to the first invalid field
-                $invalidField.focus();
+                    // Focus the field
+                    $field.focus();
+                    break;
+                }
             }
         },
 
@@ -735,7 +738,7 @@ if (typeof jQuery === 'undefined') {
                 $field.trigger($.Event(this.options.events.fieldSuccess), data);
             }
             // If all validators are completed and there is at least one validator which doesn't pass
-            else if ((counter[this.STATUS_NOT_VALIDATED] === 0 || !this._isVerboseField(field)) && counter[this.STATUS_VALIDATING] === 0 && counter[this.STATUS_INVALID] > 0) {
+            else if ((counter[this.STATUS_NOT_VALIDATED] === 0 || !this._isOptionEnabled(field, 'verbose')) && counter[this.STATUS_VALIDATING] === 0 && counter[this.STATUS_INVALID] > 0) {
                 // Add to the list of invalid fields
                 this.$invalidFields = this.$invalidFields.add($field);
 
@@ -744,19 +747,20 @@ if (typeof jQuery === 'undefined') {
         },
 
         /**
-         * Check whether or not a field is verbose
+         * Check whether or not a field option is enabled
          *
          * @param {String} field The field name
+         * @param {String} option The option name, "verbose", "autoFocus", for example
          * @returns {Boolean}
          */
-        _isVerboseField: function(field) {
-            if (this.options.fields[field].verbose === 'true' || this.options.fields[field].verbose === true) {
+        _isOptionEnabled: function(field, option) {
+            if (this.options.fields[field] && (this.options.fields[field][option] === 'true' || this.options.fields[field][option] === true)) {
                 return true;
             }
-            if (this.options.fields[field].verbose === 'false' || this.options.fields[field].verbose === false) {
+            if (this.options.fields[field] && (this.options.fields[field][option] === 'false' || this.options.fields[field][option] === false)) {
                 return false;
             }
-            return this.options.verbose === 'true' || this.options.verbose === true;
+            return this.options[option] === 'true' || this.options[option] === true;
         },
 
         // ---
@@ -789,7 +793,7 @@ if (typeof jQuery === 'undefined') {
          */
         getOptions: function(field, validator, option) {
             if (!field) {
-                return this.options;
+                return option ? this.options[option] : this.options;
             }
             if ('object' === typeof field) {
                 field = field.attr('data-bv-field');
@@ -877,7 +881,7 @@ if (typeof jQuery === 'undefined') {
                 total      = ('radio' === type || 'checkbox' === type) ? 1 : fields.length,
                 updateAll  = ('radio' === type || 'checkbox' === type),
                 validators = this.options.fields[field].validators,
-                verbose    = this._isVerboseField(field),
+                verbose    = this._isOptionEnabled(field, 'verbose'),
                 validatorName,
                 validateResult;
 
@@ -1709,17 +1713,10 @@ if (typeof jQuery === 'undefined') {
     };
 
     // The default options
+    // Sorted in alphabetical order
     $.fn.bootstrapValidator.DEFAULT_OPTIONS = {
-        // The form CSS class
-        elementClass: 'bv-form',
-
-        // Default invalid message
-        message: 'This value is not valid',
-
-        // The CSS selector for indicating the element consists the field
-        // By default, each field is placed inside the <div class="form-group"></div>
-        // You should adjust this option if your form group consists of many fields which not all of them need to be validated
-        group: '.form-group',
+        // The first invalid field will be focused automatically
+        autoFocus: true,
 
         //The error messages container. It can be:
         // - 'tooltip' if you want to use Bootstrap tooltip to show error messages
@@ -1729,8 +1726,24 @@ if (typeof jQuery === 'undefined') {
         // You also can define the message container for particular field
         container: null,
 
-        // The field will not be live validated if its length is less than this number of characters
-        threshold: null,
+        // The form CSS class
+        elementClass: 'bv-form',
+
+        // Use custom event name to avoid window.onerror being invoked by jQuery
+        // See https://github.com/nghuuphuoc/bootstrapvalidator/issues/630
+        events: {
+            formInit: 'init.form.bv',
+            formError: 'error.form.bv',
+            formSuccess: 'success.form.bv',
+            fieldAdded: 'added.field.bv',
+            fieldRemoved: 'removed.field.bv',
+            fieldInit: 'init.field.bv',
+            fieldError: 'error.field.bv',
+            fieldSuccess: 'success.field.bv',
+            fieldStatus: 'status.field.bv',
+            validatorError: 'error.validator.bv',
+            validatorSuccess: 'success.validator.bv'
+        },
 
         // Indicate fields which won't be validated
         // By default, the plugin will not validate the following kind of fields:
@@ -1781,9 +1794,13 @@ if (typeof jQuery === 'undefined') {
             validating: null
         },
 
-        // The submit buttons selector
-        // These buttons will be disabled to prevent the valid form from multiple submissions
-        submitButtons: '[type="submit"]',
+        // Map the field name with validator rules
+        fields: null,
+
+        // The CSS selector for indicating the element consists the field
+        // By default, each field is placed inside the <div class="form-group"></div>
+        // You should adjust this option if your form group consists of many fields which not all of them need to be validated
+        group: '.form-group',
 
         // Live validating option
         // Can be one of 3 values:
@@ -1792,25 +1809,16 @@ if (typeof jQuery === 'undefined') {
         // - submitted: The live validating is enabled after the form is submitted
         live: 'enabled',
 
-        // Map the field name with validator rules
-        fields: null,
+        // Default invalid message
+        message: 'This value is not valid',
+
+        // The submit buttons selector
+        // These buttons will be disabled to prevent the valid form from multiple submissions
+        submitButtons: '[type="submit"]',
+
+        // The field will not be live validated if its length is less than this number of characters
+        threshold: null,
 
-        // Use custom event name to avoid window.onerror being invoked by jQuery
-        // See https://github.com/nghuuphuoc/bootstrapvalidator/issues/630
-        events: {
-            formInit: 'init.form.bv',
-            formError: 'error.form.bv',
-            formSuccess: 'success.form.bv',
-            fieldAdded: 'added.field.bv',
-            fieldRemoved: 'removed.field.bv',
-            fieldInit: 'init.field.bv',
-            fieldError: 'error.field.bv',
-            fieldSuccess: 'success.field.bv',
-            fieldStatus: 'status.field.bv',
-            validatorError: 'error.validator.bv',
-            validatorSuccess: 'success.validator.bv'
-        },
-        
         // Whether to be verbose when validating a field or not.
         // Possible values:
         // - true:  when a field has multiple validators, all of them will be checked, and respectively - if errors occur in

文件差异内容过多而无法显示
+ 2 - 2
dist/js/bootstrapValidator.min.js


+ 63 - 55
src/js/bootstrapValidator.js

@@ -58,6 +58,7 @@ if (typeof jQuery === 'undefined') {
         _init: function() {
             var that    = this,
                 options = {
+                    autoFocus:      this.$form.attr('data-bv-autofocus'),
                     container:      this.$form.attr('data-bv-container'),
                     events: {
                         formInit:         this.$form.attr('data-bv-events-form-init'),
@@ -214,6 +215,7 @@ if (typeof jQuery === 'undefined') {
             }
 
             var opts = {
+                    autoFocus:     $field.attr('data-bv-autofocus'),
                     container:     $field.attr('data-bv-container'),
                     excluded:      $field.attr('data-bv-excluded'),
                     feedbackIcons: $field.attr('data-bv-feedbackicons'),
@@ -457,11 +459,7 @@ if (typeof jQuery === 'undefined') {
                 case 'enabled':
                 /* falls through */
                 default:
-                    fields.off(events).on(events, function(e) {
-                        // #1040: The input with placeholder is auto validated on IE 10, 11
-                        if ('input' === e.type && document.activeElement !== this) {
-                            return;
-                        }
+                    fields.off(events).on(events, function() {
                         if (that._exceedThreshold($(this))) {
                             that.validateField($(this));
                         }
@@ -650,16 +648,21 @@ if (typeof jQuery === 'undefined') {
                 }
             }
 
-            var $invalidField = this.$invalidFields.eq(0);
-            if ($invalidField) {
-                // Activate the tab containing the invalid field if exists
-                var $tabPane = $invalidField.parents('.tab-pane'), tabId;
-                if ($tabPane && (tabId = $tabPane.attr('id'))) {
-                    $('a[href="#' + tabId + '"][data-toggle="tab"]').tab('show');
-                }
+            // Determined the first invalid field which will be focused on automatically
+            for (var i = 0; i < this.$invalidFields.length; i++) {
+                var $field    = this.$invalidFields.eq(i),
+                    autoFocus = this._isOptionEnabled($field.attr('data-bv-field'), 'autoFocus');
+                if (autoFocus) {
+                    // Activate the tab containing the field if exists
+                    var $tabPane = $field.parents('.tab-pane'), tabId;
+                    if ($tabPane && (tabId = $tabPane.attr('id'))) {
+                        $('a[href="#' + tabId + '"][data-toggle="tab"]').tab('show');
+                    }
 
-                // Focus to the first invalid field
-                $invalidField.focus();
+                    // Focus the field
+                    $field.focus();
+                    break;
+                }
             }
         },
 
@@ -735,7 +738,7 @@ if (typeof jQuery === 'undefined') {
                 $field.trigger($.Event(this.options.events.fieldSuccess), data);
             }
             // If all validators are completed and there is at least one validator which doesn't pass
-            else if ((counter[this.STATUS_NOT_VALIDATED] === 0 || !this._isVerboseField(field)) && counter[this.STATUS_VALIDATING] === 0 && counter[this.STATUS_INVALID] > 0) {
+            else if ((counter[this.STATUS_NOT_VALIDATED] === 0 || !this._isOptionEnabled(field, 'verbose')) && counter[this.STATUS_VALIDATING] === 0 && counter[this.STATUS_INVALID] > 0) {
                 // Add to the list of invalid fields
                 this.$invalidFields = this.$invalidFields.add($field);
 
@@ -744,19 +747,20 @@ if (typeof jQuery === 'undefined') {
         },
 
         /**
-         * Check whether or not a field is verbose
+         * Check whether or not a field option is enabled
          *
          * @param {String} field The field name
+         * @param {String} option The option name, "verbose", "autoFocus", for example
          * @returns {Boolean}
          */
-        _isVerboseField: function(field) {
-            if (this.options.fields[field].verbose === 'true' || this.options.fields[field].verbose === true) {
+        _isOptionEnabled: function(field, option) {
+            if (this.options.fields[field] && (this.options.fields[field][option] === 'true' || this.options.fields[field][option] === true)) {
                 return true;
             }
-            if (this.options.fields[field].verbose === 'false' || this.options.fields[field].verbose === false) {
+            if (this.options.fields[field] && (this.options.fields[field][option] === 'false' || this.options.fields[field][option] === false)) {
                 return false;
             }
-            return this.options.verbose === 'true' || this.options.verbose === true;
+            return this.options[option] === 'true' || this.options[option] === true;
         },
 
         // ---
@@ -789,7 +793,7 @@ if (typeof jQuery === 'undefined') {
          */
         getOptions: function(field, validator, option) {
             if (!field) {
-                return this.options;
+                return option ? this.options[option] : this.options;
             }
             if ('object' === typeof field) {
                 field = field.attr('data-bv-field');
@@ -877,7 +881,7 @@ if (typeof jQuery === 'undefined') {
                 total      = ('radio' === type || 'checkbox' === type) ? 1 : fields.length,
                 updateAll  = ('radio' === type || 'checkbox' === type),
                 validators = this.options.fields[field].validators,
-                verbose    = this._isVerboseField(field),
+                verbose    = this._isOptionEnabled(field, 'verbose'),
                 validatorName,
                 validateResult;
 
@@ -1709,17 +1713,10 @@ if (typeof jQuery === 'undefined') {
     };
 
     // The default options
+    // Sorted in alphabetical order
     $.fn.bootstrapValidator.DEFAULT_OPTIONS = {
-        // The form CSS class
-        elementClass: 'bv-form',
-
-        // Default invalid message
-        message: 'This value is not valid',
-
-        // The CSS selector for indicating the element consists the field
-        // By default, each field is placed inside the <div class="form-group"></div>
-        // You should adjust this option if your form group consists of many fields which not all of them need to be validated
-        group: '.form-group',
+        // The first invalid field will be focused automatically
+        autoFocus: true,
 
         //The error messages container. It can be:
         // - 'tooltip' if you want to use Bootstrap tooltip to show error messages
@@ -1729,8 +1726,24 @@ if (typeof jQuery === 'undefined') {
         // You also can define the message container for particular field
         container: null,
 
-        // The field will not be live validated if its length is less than this number of characters
-        threshold: null,
+        // The form CSS class
+        elementClass: 'bv-form',
+
+        // Use custom event name to avoid window.onerror being invoked by jQuery
+        // See https://github.com/nghuuphuoc/bootstrapvalidator/issues/630
+        events: {
+            formInit: 'init.form.bv',
+            formError: 'error.form.bv',
+            formSuccess: 'success.form.bv',
+            fieldAdded: 'added.field.bv',
+            fieldRemoved: 'removed.field.bv',
+            fieldInit: 'init.field.bv',
+            fieldError: 'error.field.bv',
+            fieldSuccess: 'success.field.bv',
+            fieldStatus: 'status.field.bv',
+            validatorError: 'error.validator.bv',
+            validatorSuccess: 'success.validator.bv'
+        },
 
         // Indicate fields which won't be validated
         // By default, the plugin will not validate the following kind of fields:
@@ -1781,9 +1794,13 @@ if (typeof jQuery === 'undefined') {
             validating: null
         },
 
-        // The submit buttons selector
-        // These buttons will be disabled to prevent the valid form from multiple submissions
-        submitButtons: '[type="submit"]',
+        // Map the field name with validator rules
+        fields: null,
+
+        // The CSS selector for indicating the element consists the field
+        // By default, each field is placed inside the <div class="form-group"></div>
+        // You should adjust this option if your form group consists of many fields which not all of them need to be validated
+        group: '.form-group',
 
         // Live validating option
         // Can be one of 3 values:
@@ -1792,25 +1809,16 @@ if (typeof jQuery === 'undefined') {
         // - submitted: The live validating is enabled after the form is submitted
         live: 'enabled',
 
-        // Map the field name with validator rules
-        fields: null,
+        // Default invalid message
+        message: 'This value is not valid',
+
+        // The submit buttons selector
+        // These buttons will be disabled to prevent the valid form from multiple submissions
+        submitButtons: '[type="submit"]',
+
+        // The field will not be live validated if its length is less than this number of characters
+        threshold: null,
 
-        // Use custom event name to avoid window.onerror being invoked by jQuery
-        // See https://github.com/nghuuphuoc/bootstrapvalidator/issues/630
-        events: {
-            formInit: 'init.form.bv',
-            formError: 'error.form.bv',
-            formSuccess: 'success.form.bv',
-            fieldAdded: 'added.field.bv',
-            fieldRemoved: 'removed.field.bv',
-            fieldInit: 'init.field.bv',
-            fieldError: 'error.field.bv',
-            fieldSuccess: 'success.field.bv',
-            fieldStatus: 'status.field.bv',
-            validatorError: 'error.validator.bv',
-            validatorSuccess: 'success.validator.bv'
-        },
-        
         // Whether to be verbose when validating a field or not.
         // Possible values:
         // - true:  when a field has multiple validators, all of them will be checked, and respectively - if errors occur in

+ 97 - 39
test/spec.js

@@ -86,6 +86,99 @@ describe('api', function() {
     });
 });
 
+describe('autoFocus', function() {
+    beforeEach(function() {
+        $([
+            '<form class="form-horizontal" id="autoFocusForm">',
+                '<div class="form-group">',
+                    '<input type="text" name="username" required />',
+                '</div>',
+                '<div class="form-group">',
+                    '<input type="text" name="email" required data-bv-emailaddress />',
+                '</div>',
+                '<div class="form-group">',
+                    '<button type="submit" id="submitButton">Submit</button>',
+                '</div>',
+            '</form>'
+        ].join('')).appendTo('body');
+
+        this.bv        = $('#autoFocusForm')
+                            .bootstrapValidator()
+                            .submit(function(e) {
+                                e.preventDefault();
+                            })
+                            .data('bootstrapValidator');
+        this.$username = this.bv.getFieldElements('username');
+        this.$email    = this.bv.getFieldElements('email');
+    });
+
+    afterEach(function() {
+        $('#autoFocusForm').bootstrapValidator('destroy').remove();
+    });
+
+    it('default option (autoFocus=true)', function() {
+        $('#submitButton').click();
+        expect(this.$username.is(':focus')).toBeTruthy();
+        expect($(document.activeElement).attr('name')).toEqual('username');
+
+        this.bv.resetForm();
+        this.$username.val('user_name');
+        this.$email.val('');
+        $('#submitButton').click();
+        expect(this.$email.is(':focus')).toBeTruthy();
+        expect($(document.activeElement).attr('name')).toEqual('email');
+    });
+
+    it('set autoFocus=false for form', function() {
+        $('#autoFocusForm')
+                .bootstrapValidator('destroy')
+                .bootstrapValidator({
+                    autoFocus: false
+                });
+        this.$username.val('');
+        this.$email.val('invalid#email');
+        $('#submitButton').click();
+
+        expect(document.activeElement.tagName.toLowerCase()).toEqual('body');
+        expect(this.$username.is(':focus')).toBeFalsy();
+        expect(this.$email.is(':focus')).toBeFalsy();
+    });
+
+    it('set autoFocus=false for all fields', function() {
+        this.bv
+            .addField('username', {
+                autoFocus: false
+            })
+            .addField('email', {
+                autoFocus: false
+            });
+        this.$username.val('user_name');
+        this.$email.val('invalid#email');
+        $('#submitButton').click();
+
+        expect(document.activeElement.tagName.toLowerCase()).toEqual('body');
+        expect(this.$username.is(':focus')).toBeFalsy();
+        expect(this.$email.is(':focus')).toBeFalsy();
+    });
+
+    it('set different autoFocus value for fields', function() {
+        this.bv
+            .addField('username', {
+                autoFocus: false
+            })
+            .addField('email', {
+                autoFocus: true
+            });
+        this.$username.val('');
+        this.$email.val('invalid_email');
+        $('#submitButton').click();
+
+        expect(this.$username.is(':focus')).toBeFalsy();
+        expect(this.$email.is(':focus')).toBeTruthy();
+        expect($(document.activeElement).attr('name')).toEqual('email');
+    });
+});
+
 describe('container form option', function() {
     beforeEach(function() {
         $([
@@ -539,8 +632,6 @@ describe('enable validators', function() {
     });
 });
 
-var defaultOptions = $.fn.bootstrapValidator.DEFAULT_OPTIONS;
-
 TestSuite = $.extend({}, TestSuite, {
     Event: {
         onEmailValid: function(e, data) {
@@ -1026,6 +1117,8 @@ describe('event field trigger with default events', function() {
 });
 
 describe('event form trigger with events changed', function() {
+    var defaultOptions = $.fn.bootstrapValidator.DEFAULT_OPTIONS;
+
     beforeEach(function() {
         $.fn.bootstrapValidator.DEFAULT_OPTIONS = $.extend({}, $.fn.bootstrapValidator.DEFAULT_OPTIONS, {
             events: {
@@ -1100,6 +1193,8 @@ describe('event form trigger with events changed', function() {
 });
 
 describe('event field trigger with events changed', function() {
+    var defaultOptions = $.fn.bootstrapValidator.DEFAULT_OPTIONS;
+
     beforeEach(function() {
         $.fn.bootstrapValidator.DEFAULT_OPTIONS = $.extend({}, $.fn.bootstrapValidator.DEFAULT_OPTIONS, {
             events: {
@@ -1858,43 +1953,6 @@ describe('i18n', function() {
     });
 });
 
-describe('input', function() {
-    beforeEach(function(done) {
-        $([
-            '<form class="form-horizontal" id="inputForm">',
-                '<div class="form-group">',
-                    '<textarea name="text" data-bv-notempty placeholder="Text" />',
-                '</div>',
-                '<div class="form-group">',
-                    '<input type="text" name="input1" data-bv-notempty placeholder="Text" />',
-                '</div>',
-                '<div class="form-group">',
-                    '<input type="text" name="input2" data-bv-notempty placeholder="Text" />',
-                '</div>',
-            '</form>'
-        ].join('\n')).appendTo('body');
-
-        $('#inputForm').bootstrapValidator();
-
-        this.bv      = $('#inputForm').data('bootstrapValidator');
-        this.$text   = this.bv.getFieldElements('text');
-        this.$input1 = this.bv.getFieldElements('input1');
-        this.$input2 = this.bv.getFieldElements('input2');
-        setTimeout(done, 0);
-    });
-
-    afterEach(function() {
-        $('#inputForm').bootstrapValidator('destroy').remove();
-    });
-
-    // #1040, #1041
-    it('Fields should not be validated on init', function() {
-        expect(this.bv.getMessages(this.$text)).toEqual([]);
-        expect(this.bv.getMessages(this.$input1)).toEqual([]);
-        expect(this.bv.getMessages(this.$input2)).toEqual([]);
-    });
-});
-
 describe('message', function() {
     beforeEach(function() {
         var html = [

+ 92 - 0
test/spec/autoFocus.js

@@ -0,0 +1,92 @@
+describe('autoFocus', function() {
+    beforeEach(function() {
+        $([
+            '<form class="form-horizontal" id="autoFocusForm">',
+                '<div class="form-group">',
+                    '<input type="text" name="username" required />',
+                '</div>',
+                '<div class="form-group">',
+                    '<input type="text" name="email" required data-bv-emailaddress />',
+                '</div>',
+                '<div class="form-group">',
+                    '<button type="submit" id="submitButton">Submit</button>',
+                '</div>',
+            '</form>'
+        ].join('')).appendTo('body');
+
+        this.bv        = $('#autoFocusForm')
+                            .bootstrapValidator()
+                            .submit(function(e) {
+                                e.preventDefault();
+                            })
+                            .data('bootstrapValidator');
+        this.$username = this.bv.getFieldElements('username');
+        this.$email    = this.bv.getFieldElements('email');
+    });
+
+    afterEach(function() {
+        $('#autoFocusForm').bootstrapValidator('destroy').remove();
+    });
+
+    it('default option (autoFocus=true)', function() {
+        $('#submitButton').click();
+        expect(this.$username.is(':focus')).toBeTruthy();
+        expect($(document.activeElement).attr('name')).toEqual('username');
+
+        this.bv.resetForm();
+        this.$username.val('user_name');
+        this.$email.val('');
+        $('#submitButton').click();
+        expect(this.$email.is(':focus')).toBeTruthy();
+        expect($(document.activeElement).attr('name')).toEqual('email');
+    });
+
+    it('set autoFocus=false for form', function() {
+        $('#autoFocusForm')
+                .bootstrapValidator('destroy')
+                .bootstrapValidator({
+                    autoFocus: false
+                });
+        this.$username.val('');
+        this.$email.val('invalid#email');
+        $('#submitButton').click();
+
+        expect(document.activeElement.tagName.toLowerCase()).toEqual('body');
+        expect(this.$username.is(':focus')).toBeFalsy();
+        expect(this.$email.is(':focus')).toBeFalsy();
+    });
+
+    it('set autoFocus=false for all fields', function() {
+        this.bv
+            .addField('username', {
+                autoFocus: false
+            })
+            .addField('email', {
+                autoFocus: false
+            });
+        this.$username.val('user_name');
+        this.$email.val('invalid#email');
+        $('#submitButton').click();
+
+        expect(document.activeElement.tagName.toLowerCase()).toEqual('body');
+        expect(this.$username.is(':focus')).toBeFalsy();
+        expect(this.$email.is(':focus')).toBeFalsy();
+    });
+
+    it('set different autoFocus value for fields', function() {
+        this.bv
+            .addField('username', {
+                autoFocus: false
+            })
+            .addField('email', {
+                autoFocus: true
+            });
+        this.$username.val('');
+        this.$email.val('invalid_email');
+        $('#submitButton').click();
+
+        expect(this.$username.is(':focus')).toBeFalsy();
+        expect(this.$email.is(':focus')).toBeTruthy();
+        expect($(document.activeElement).attr('name')).toEqual('email');
+    });
+});

+ 4 - 2
test/spec/event.js

@@ -1,5 +1,3 @@
-var defaultOptions = $.fn.bootstrapValidator.DEFAULT_OPTIONS;
-
 TestSuite = $.extend({}, TestSuite, {
     Event: {
         onEmailValid: function(e, data) {
@@ -485,6 +483,8 @@ describe('event field trigger with default events', function() {
 });
 
 describe('event form trigger with events changed', function() {
+    var defaultOptions = $.fn.bootstrapValidator.DEFAULT_OPTIONS;
+
     beforeEach(function() {
         $.fn.bootstrapValidator.DEFAULT_OPTIONS = $.extend({}, $.fn.bootstrapValidator.DEFAULT_OPTIONS, {
             events: {
@@ -559,6 +559,8 @@ describe('event form trigger with events changed', function() {
 });
 
 describe('event field trigger with events changed', function() {
+    var defaultOptions = $.fn.bootstrapValidator.DEFAULT_OPTIONS;
+
     beforeEach(function() {
         $.fn.bootstrapValidator.DEFAULT_OPTIONS = $.extend({}, $.fn.bootstrapValidator.DEFAULT_OPTIONS, {
             events: {

+ 0 - 36
test/spec/input.js

@@ -1,36 +0,0 @@
-describe('input', function() {
-    beforeEach(function(done) {
-        $([
-            '<form class="form-horizontal" id="inputForm">',
-                '<div class="form-group">',
-                    '<textarea name="text" data-bv-notempty placeholder="Text" />',
-                '</div>',
-                '<div class="form-group">',
-                    '<input type="text" name="input1" data-bv-notempty placeholder="Text" />',
-                '</div>',
-                '<div class="form-group">',
-                    '<input type="text" name="input2" data-bv-notempty placeholder="Text" />',
-                '</div>',
-            '</form>'
-        ].join('\n')).appendTo('body');
-
-        $('#inputForm').bootstrapValidator();
-
-        this.bv      = $('#inputForm').data('bootstrapValidator');
-        this.$text   = this.bv.getFieldElements('text');
-        this.$input1 = this.bv.getFieldElements('input1');
-        this.$input2 = this.bv.getFieldElements('input2');
-        setTimeout(done, 0);
-    });
-
-    afterEach(function() {
-        $('#inputForm').bootstrapValidator('destroy').remove();
-    });
-
-    // #1040, #1041
-    it('Fields should not be validated on init', function() {
-        expect(this.bv.getMessages(this.$text)).toEqual([]);
-        expect(this.bv.getMessages(this.$input1)).toEqual([]);
-        expect(this.bv.getMessages(this.$input2)).toEqual([]);
-    });
-});