浏览代码

Merge branch 'master' into v0.5.0

Conflicts:
	CHANGELOG.md
	bootstrapValidator.jquery.json
	bower.json
	dist/css/bootstrapValidator.min.css
	dist/js/bootstrapValidator.js
	dist/js/bootstrapValidator.min.js
	package.json
	src/js/bootstrapValidator.js
phuoc 11 年之前
父节点
当前提交
69fdb60787

+ 16 - 3
CHANGELOG.md

@@ -8,9 +8,22 @@
 
 ## v0.4.5 (not released yet)
 
-* Add ```$.fn.bootstrapValidator.helpers.date``` for validating a date, re-used in ```date```, ```id```, [```vat```](http://bootstrapvalidator.com/validators/vat/) validators
+* Add ```$.fn.bootstrapValidator.helpers.date``` for validating a date, re-used in [```date```](http://bootstrapvalidator.com/validators/date/), [```id```](http://bootstrapvalidator.com/validators/id/), [```vat```](http://bootstrapvalidator.com/validators/vat/) validators
 * [#233](https://github.com/nghuuphuoc/bootstrapvalidator/issues/233): Add ```threshold``` option
-* [#232](https://github.com/nghuuphuoc/bootstrapvalidator/issues/232): Add ```id``` validator
+* [#232](https://github.com/nghuuphuoc/bootstrapvalidator/issues/232): Add [```id``` validator](http://bootstrapvalidator.com/validators/id/)
+* [#242](https://github.com/nghuuphuoc/bootstrapvalidator/issues/242): Add ```separator``` option to the [```numeric``` validator](http://bootstrapvalidator.com/validators/numeric/)
+* [#248](https://github.com/nghuuphuoc/bootstrapvalidator/issues/248): Add [```isin``` (International Securities Identification Number) validator](http://bootstrapvalidator.com/validators/issn/)
+* [#250](https://github.com/nghuuphuoc/bootstrapvalidator/issues/250): Add [```rtn``` (Routing transit number) validator](http://bootstrapvalidator.com/validators/rtn/)
+* [#251](https://github.com/nghuuphuoc/bootstrapvalidator/issues/251): Add [```cusip``` (North American Securities) validator](http://bootstrapvalidator.com/validators/cusip/)
+* [#252](https://github.com/nghuuphuoc/bootstrapvalidator/issues/252): Add [```sedol``` (Stock Exchange Daily Official List) validator](http://bootstrapvalidator.com/validators/sedol/)
+* The [```zipCode``` validator](http://bootstrapvalidator.com/validators/zipCode/) adds support for Italian, Dutch postcodes
+* [#245](https://github.com/nghuuphuoc/bootstrapvalidator/pull/245): The [```cvv``` validator](http://bootstrapvalidator.com/validators/cvv/) should support spaces in credit card, thanks to [@evilchili](https://github.com/evilchili)
+* Change default ```submitButtons``` to ```[type="submit"]``` to support ```input type="submit"```
+* [#226](https://github.com/nghuuphuoc/bootstrapvalidator/issues/226): Fix the conflict issue with MooTools
+* [#238](https://github.com/nghuuphuoc/bootstrapvalidator/issues/238): The submit buttons are not sent
+* [#253](https://github.com/nghuuphuoc/bootstrapvalidator/issues/253): The [```iban``` validator](http://bootstrapvalidator.com/validators/iban/) does not work on IE8
+* [#257](https://github.com/nghuuphuoc/bootstrapvalidator/issues/257): Plugin method invocation don't work
+* Fix the issue that the hidden fields generated by other plugins might not be validated
 * When parsing options from HTML attributes, don't add the field which hasn't validators. It improves fixes for [#191](https://github.com/nghuuphuoc/bootstrapvalidator/issues/191), [#223](https://github.com/nghuuphuoc/bootstrapvalidator/issues/223)
 
 ## v0.4.4 (2014-05-05)
@@ -26,7 +39,7 @@
 * [#206](https://github.com/nghuuphuoc/bootstrapvalidator/issues/206): Indicate success/error tab
 * [#220](https://github.com/nghuuphuoc/bootstrapvalidator/issues/220): Add UK postcode support for the [```zipCode``` validator](http://bootstrapvalidator.com/validators/zipCode/)
 * [#229](https://github.com/nghuuphuoc/bootstrapvalidator/issues/229): The [```date``` validator](http://bootstrapvalidator.com/validators/date/) supports seconds
-* [#231](https://github.com/nghuuphuoc/bootstrapvalidator/issues/231): Wrong prefix of Laser credit card number
+* [#231](https://github.com/nghuuphuoc/bootstrapvalidator/issues/231): Wrong prefix of Laser [credit card](http://bootstrapvalidator.com/validators/creditCard/) number
 
 ## v0.4.3 (2014-04-26)
 

+ 1 - 1
Gruntfile.js

@@ -8,7 +8,7 @@ module.exports = function(grunt) {
             '/**',
             ' * BootstrapValidator (<%= pkg.homepage %>)',
             ' *',
-            ' * A jQuery plugin to validate form fields. Use with Bootstrap 3',
+            ' * <%= pkg.description %>',
             ' *',
             ' * @version     v<%= pkg.version %>',
             ' * @author      <%= pkg.author.url %>',

+ 12 - 5
README.md

@@ -1,10 +1,16 @@
-# BootstrapValidator - [v0.4.4](https://github.com/nghuuphuoc/bootstrapvalidator/releases/download/v0.4.4/bootstrapvalidator-dist-0.4.4.zip)
+# BootstrapValidator - [v0.4.5](https://github.com/nghuuphuoc/bootstrapvalidator/releases/download/v0.4.5/bootstrapvalidator-dist-0.4.5.zip)
 
 [http://bootstrapvalidator.com](http://bootstrapvalidator.com) - The best jQuery plugin to validate form fields. Designed to use with [Bootstrap 3](http://getbootstrap.com)
 
+![Screenshot](screenshots/screenshot.png)
+
+## Help the project
+
+I've been spending a lot of time to work on this plugin. If it is useful to you, please consider to help the project by making a small donation:
+
 <a href="https://pledgie.com/campaigns/24885"><img alt="Click here to lend your support to: BootstrapValidator and make a donation at pledgie.com!" src="https://pledgie.com/campaigns/24885.png?skin_name=chrome" border="0" /></a>
 
-![Screenshot](screenshots/screenshot.png)
+Also, you can make me feel happy by [tweeting](https://twitter.com/intent/tweet?hashtags=javascript,jquery,twbootstrap&original_referer=http://github.com/nghuuphuoc/bootstrapvalidator&text=BootstrapValidator%20is%20the%20best%20jQuery%20plugin%20to%20validate%20form%20fields&url=http://bootstrapvalidator.com) about it and [staring](https://github.com/nghuuphuoc/bootstrapvalidator/stargazers) the project on Github.
 
 ## Live demo
 
@@ -19,7 +25,7 @@ __Code__
 
 __Bootstrap__
 * Designed to use with [Bootstrap 3](http://getbootstrap.com)
-* Support almost [Bootstrap forms](http://getbootstrap.com/css/#forms)
+* Support almost all [Bootstrap forms](http://getbootstrap.com/css/#forms)
 * Support Bootstrap form [validation states](http://getbootstrap.com/css/#forms-control-validation)
 
 __HTML 5__
@@ -28,7 +34,7 @@ __HTML 5__
 * Support [HTML 5 input types](http://bootstrapvalidator.com/examples#html5) such as ```color```, ```email```, ```range``` and ```url```
 
 __Validator__
-* [41 built-in validators](http://bootstrapvalidator.com/validators/) and counting!
+* [46 built-in validators](http://bootstrapvalidator.com/validators/) and counting!
 * Easy to [write a new validator](http://bootstrapvalidator.com/developing/)
  
 __Friendly__
@@ -60,7 +66,7 @@ __Compatibility__
  
 ## Download
 
-Latest version: [v0.4.4](https://github.com/nghuuphuoc/bootstrapvalidator/releases/download/v0.4.4/bootstrapvalidator-dist-0.4.4.zip), released on 2014-05-05.
+Latest version: [v0.4.5](https://github.com/nghuuphuoc/bootstrapvalidator/releases/download/v0.4.5/bootstrapvalidator-dist-0.4.5.zip), released on 2014-05-15.
 
 For older versions, look at the [Releases](https://github.com/nghuuphuoc/bootstrapvalidator/releases) page.
 
@@ -85,6 +91,7 @@ Big thanks to the contributors:
 * [@adgrafik](https://github.com/adgrafik)
 * [@easonhan007](https://github.com/easonhan007)
 * [@emilchristensen](https://github.com/emilchristensen)
+* [@evilchili](https://github.com/evilchili)
 * [@Francismori7](https://github.com/Francismori7)
 * [@gercheq](https://github.com/gercheq)
 * [@henningda](https://github.com/henningda)

+ 1 - 1
demo/index.html

@@ -176,7 +176,7 @@
 
                         <div class="form-group">
                             <div class="col-lg-9 col-lg-offset-3">
-                                <button type="submit" class="btn btn-primary">Sign up</button>
+                                <button type="submit" class="btn btn-primary" name="signup" value="Sign up">Sign up</button>
                                 <button type="button" class="btn btn-info" id="validateBtn">Manual validate</button>
                                 <button type="button" class="btn btn-info" id="resetBtn">Reset form</button>
                             </div>

+ 3 - 3
dist/css/bootstrapValidator.css

@@ -1,10 +1,10 @@
 /**
- * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator)
+ * BootstrapValidator (http://bootstrapvalidator.com)
  *
- * A jQuery plugin to validate form fields. Use with Bootstrap 3
+ * The best jQuery plugin to validate form fields. Designed to use with Bootstrap 3
  *
  * @author      http://twitter.com/nghuuphuoc
- * @copyright   (c) 2014 Nguyen Huu Phuoc
+ * @copyright   (c) 2013 - 2014 Nguyen Huu Phuoc
  * @license     MIT
  */
 

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

@@ -1,9 +1,9 @@
 /**
  * BootstrapValidator (http://bootstrapvalidator.com)
  *
- * A jQuery plugin to validate form fields. Use with Bootstrap 3
+ * The best jQuery plugin to validate form fields. Designed to use with Bootstrap 3
  *
- * @version     v0.5.0-dev
+ * @version     v0.4.5
  * @author      https://twitter.com/nghuuphuoc
  * @copyright   (c) 2013 - 2014 Nguyen Huu Phuoc
  * @license     MIT

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


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


+ 3 - 3
src/css/bootstrapValidator.css

@@ -1,10 +1,10 @@
 /**
- * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator)
+ * BootstrapValidator (http://bootstrapvalidator.com)
  *
- * A jQuery plugin to validate form fields. Use with Bootstrap 3
+ * The best jQuery plugin to validate form fields. Designed to use with Bootstrap 3
  *
  * @author      http://twitter.com/nghuuphuoc
- * @copyright   (c) 2014 Nguyen Huu Phuoc
+ * @copyright   (c) 2013 - 2014 Nguyen Huu Phuoc
  * @license     MIT
  */
 

+ 92 - 63
src/js/bootstrapValidator.js

@@ -1,7 +1,7 @@
 /**
- * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator)
+ * BootstrapValidator (http://bootstrapvalidator.com)
  *
- * A jQuery plugin to validate form fields. Use with Bootstrap 3
+ * The best jQuery plugin to validate form fields. Designed to use with Bootstrap 3
  *
  * @author      http://twitter.com/nghuuphuoc
  * @copyright   (c) 2013 - 2014 Nguyen Huu Phuoc
@@ -107,7 +107,7 @@
 
         // The submit buttons selector
         // These buttons will be disabled to prevent the valid form from multiple submissions
-        submitButtons: 'button[type="submit"]',
+        submitButtons: '[type="submit"]',
 
         // The custom submit handler
         // It will prevent the form from the default submission
@@ -174,65 +174,69 @@
 					that._submitIfValid = true;
                 })
                 // Find all fields which have either "name" or "data-bv-field" attribute
-                .find('[name], [data-bv-field]').each(function() {
-                    var $field = $(this);
-                    if (that._isExcluded($field)) {
-                        return;
-                    }
+                .find('[name], [data-bv-field]')
+                    .each(function() {
+                        var $field = $(this);
+                        if (that._isExcluded($field)) {
+                            return;
+                        }
 
-                    var field      = $field.attr('name') || $field.attr('data-bv-field'),
-                        validators = {};
-                    for (v in $.fn.bootstrapValidator.validators) {
-                        validator  = $.fn.bootstrapValidator.validators[v];
-                        enabled    = $field.attr('data-bv-' + v.toLowerCase()) + '';
-                        html5Attrs = ('function' == typeof validator.enableByHtml5) ? validator.enableByHtml5($(this)) : null;
-
-                        if ((html5Attrs && enabled != 'false')
-                            || (html5Attrs !== true && ('' == enabled || 'true' == enabled)))
-                        {
-                            // Try to parse the options via attributes
-                            validator.html5Attributes = validator.html5Attributes || { message: 'message' };
-                            validators[v] = $.extend({}, html5Attrs == true ? {} : html5Attrs, validators[v]);
-
-                            for (html5AttrName in validator.html5Attributes) {
-                                optionName  = validator.html5Attributes[html5AttrName];
-                                optionValue = $field.attr('data-bv-' + v.toLowerCase() + '-' + html5AttrName);
-                                if (optionValue) {
-                                    if ('true' == optionValue) {
-                                        optionValue = true;
-                                    } else if ('false' == optionValue) {
-                                        optionValue = false;
+                        var field      = $field.attr('name') || $field.attr('data-bv-field'),
+                            validators = {};
+                        for (v in $.fn.bootstrapValidator.validators) {
+                            validator  = $.fn.bootstrapValidator.validators[v];
+                            enabled    = $field.attr('data-bv-' + v.toLowerCase()) + '';
+                            html5Attrs = ('function' == typeof validator.enableByHtml5) ? validator.enableByHtml5($(this)) : null;
+
+                            if ((html5Attrs && enabled != 'false')
+                                || (html5Attrs !== true && ('' == enabled || 'true' == enabled)))
+                            {
+                                // Try to parse the options via attributes
+                                validator.html5Attributes = validator.html5Attributes || { message: 'message' };
+                                validators[v] = $.extend({}, html5Attrs == true ? {} : html5Attrs, validators[v]);
+
+                                for (html5AttrName in validator.html5Attributes) {
+                                    optionName  = validator.html5Attributes[html5AttrName];
+                                    optionValue = $field.attr('data-bv-' + v.toLowerCase() + '-' + html5AttrName);
+                                    if (optionValue) {
+                                        if ('true' == optionValue) {
+                                            optionValue = true;
+                                        } else if ('false' == optionValue) {
+                                            optionValue = false;
+                                        }
+                                        validators[v][optionName] = optionValue;
                                     }
-                                    validators[v][optionName] = optionValue;
                                 }
                             }
                         }
-                    }
-
-                    var opts = {
-                        trigger:    $field.attr('data-bv-trigger'),
-                        message:    $field.attr('data-bv-message'),
-                        container:  $field.attr('data-bv-container'),
-                        selector:   $field.attr('data-bv-selector'),
-                        threshold:  $field.attr('data-bv-threshold'),
-                        validators: validators
-                    };
 
-                    // Check if there is any validators set using HTML attributes
-                    if (!$.isEmptyObject(opts)) {
-                        $field.attr('data-bv-field', field);
-                        options.fields[field] = $.extend({}, opts, options.fields[field]);
-                    }
-                });
+                        var opts = {
+                            trigger:    $field.attr('data-bv-trigger'),
+                            message:    $field.attr('data-bv-message'),
+                            container:  $field.attr('data-bv-container'),
+                            selector:   $field.attr('data-bv-selector'),
+                            threshold:  $field.attr('data-bv-threshold'),
+                            validators: validators
+                        };
+
+                        // Check if there is any validators set using HTML attributes
+                        if (!$.isEmptyObject(opts.validators) && !$.isEmptyObject(opts)) {
+                            $field.attr('data-bv-field', field);
+                            options.fields[field] = $.extend({}, opts, options.fields[field]);
+                        }
+                    })
+                    .end()
+                // Create hidden inputs to send the submit buttons
+                .find(this.options.submitButtons)
+                    .each(function() {
+                        $('<input/>')
+                            .attr('type', 'hidden')
+                            .attr('name', $(this).attr('name'))
+                            .val($(this).val())
+                            .appendTo(that.$form);
+                    });
 
             this.options = $.extend(true, this.options, options);
-            if ('string' == typeof this.options.excluded) {
-                this.options.excluded = $.map(this.options.excluded.split(','), function(item) {
-                    // Trim the spaces
-                    return $.trim(item);
-                });
-            }
-
             for (var field in this.options.fields) {
                 this._initField(field);
             }
@@ -325,7 +329,7 @@
                 && (!updateAll || index == total - 1))
             {
                 $parent.removeClass('has-success').removeClass('has-error').addClass('has-feedback');
-                var $icon = $('<i/>').css('display', 'none').addClass('form-control-feedback').attr('data-bv-icon', field).insertAfter($field);
+                var $icon = $('<i/>').css('display', 'none').addClass('form-control-feedback').attr('data-bv-icon-for', 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) {
@@ -407,7 +411,16 @@
          */
         _isExcluded: function($field) {
             if (this.options.excluded) {
-                for (var i in this.options.excluded) {
+                // Convert to array first
+                if ('string' == typeof this.options.excluded) {
+                    this.options.excluded = $.map(this.options.excluded.split(','), function(item) {
+                        // Trim the spaces
+                        return $.trim(item);
+                    });
+                }
+
+                var length = this.options.excluded.length;
+                for (var i = 0; i < length; i++) {
                     if (('string' == typeof this.options.excluded[i] && $field.is(this.options.excluded[i]))
                         || ('function' == typeof this.options.excluded[i] && this.options.excluded[i].call(this, $field, this) == true))
                     {
@@ -700,7 +713,7 @@
                 $parent  = $field.parents('.form-group'),
                 $message = $field.data('bv.messages'),
                 $errors  = $message.find('.help-block[data-bv-validator]'),
-                $icon    = $parent.find('.form-control-feedback[data-bv-icon="' + field + '"]');
+                $icon    = $parent.find('.form-control-feedback[data-bv-icon-for="' + field + '"]');
 
             // Update status
             if (validatorName) {
@@ -755,7 +768,7 @@
                                         var v = $(this).attr('data-bv-validator');
                                         return $field.data('bv.result.' + v) != that.STATUS_VALID;
                                     }).length == 0;
-                    this.disableSubmitButtons(validField ? false : true);
+                    this.disableSubmitButtons(!validField);
                     if ($icon) {
                         $icon
                             .removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid)
@@ -910,7 +923,7 @@
          * Reset the form
          *
          * @param {Boolean} resetFormData Reset current form data
-         * @returns {BootstrapValidator}
+         * @return {BootstrapValidator}
          */
         resetForm: function(resetFormData) {
             var field, fields, total, type, validator;
@@ -958,7 +971,8 @@
     };
 
     // Plugin definition
-    $.fn.bootstrapValidator = function(option, params) {
+    $.fn.bootstrapValidator = function(option) {
+        var params = arguments;
         return this.each(function() {
             var $this   = $(this),
                 data    = $this.data('bootstrapValidator'),
@@ -970,7 +984,7 @@
 
             // Allow to call plugin method
             if ('string' == typeof option) {
-                data[option](params);
+                data[option].apply(data, Array.prototype.slice.call(params, 1));
             }
         });
     };
@@ -988,9 +1002,10 @@
          * @param {Number} year The full year in 4 digits
          * @param {Number} month The month number
          * @param {Number} day The day number
+         * @param {Boolean} [notInFuture] If true, the date must not be in the future
          * @returns {Boolean}
          */
-        date: function(year, month, day) {
+        date: function(year, month, day, notInFuture) {
             if (year < 1000 || year > 9999 || month == 0 || month > 12) {
                 return false;
             }
@@ -1001,7 +1016,21 @@
             }
 
             // Check the day
-            return (day > 0 && day <= numDays[month - 1]);
+            if (day < 0 || day > numDays[month - 1]) {
+                return false;
+            }
+
+            if (notInFuture === true) {
+                var currentDate  = new Date(),
+                    currentYear  = currentDate.getFullYear(),
+                    currentMonth = currentDate.getMonth(),
+                    currentDay   = currentDate.getDate();
+                return (year < currentYear
+                        || (year == currentYear && month - 1 < currentMonth)
+                        || (year == currentYear && month - 1 == currentMonth && day < currentDay));
+            }
+
+            return true;
         },
 
         /**

+ 51 - 0
src/js/validator/cusip.js

@@ -0,0 +1,51 @@
+(function($) {
+    $.fn.bootstrapValidator.validators.cusip = {
+        /**
+         * Validate a CUSIP
+         * Examples:
+         * - Valid: 037833100, 931142103, 14149YAR8, 126650BG6
+         * - Invalid: 31430F200, 022615AC2
+         *
+         * @see http://en.wikipedia.org/wiki/CUSIP
+         * @param {BootstrapValidator} validator The validator plugin instance
+         * @param {jQuery} $field Field element
+         * @param {Object} options Can consist of the following keys:
+         * - message: The invalid message
+         * @returns {Boolean}
+         */
+        validate: function(validator, $field, options) {
+            var value = $field.val();
+            if (value == '') {
+                return true;
+            }
+
+            value = value.toUpperCase();
+            if (!/^[0-9A-Z]{9}$/.test(value)) {
+                return false;
+            }
+
+            var converted = $.map(value.split(''), function(item) {
+                                var code = item.charCodeAt(0);
+                                return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0))
+                                            // Replace A, B, C, ..., Z with 10, 11, ..., 35
+                                            ? (code - 'A'.charCodeAt(0) + 10)
+                                            : item;
+                            }),
+                length    = converted.length,
+                sum       = 0;
+            for (var i = 0; i < length - 1; i++) {
+                var num = parseInt(converted[i]);
+                if (i % 2 != 0) {
+                    num *= 2;
+                }
+                if (num > 9) {
+                    num -= 9;
+                }
+                sum += num;
+            }
+
+            sum = (10 - (sum % 10)) % 10;
+            return sum == converted[length - 1];
+        }
+    };
+}(window.jQuery));

+ 2 - 0
src/js/validator/cvv.js

@@ -34,6 +34,8 @@
             if (creditCard == '') {
                 return true;
             }
+            
+            creditCard = creditCard.replace(/\D/g, '');
 
             // Supported credit card types
             var cards = {

+ 6 - 5
src/js/validator/iban.js

@@ -117,13 +117,14 @@
             }
 
             value = value.substr(4) + value.substr(0, 4);
-            value = value.split('').map(function(n) {
+            value = $.map(value.split(''), function(n) {
                 var code = n.charCodeAt(0);
                 return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0))
-                    // Replace A, B, C, ..., Z with 10, 11, ..., 35
-                    ? (code - 'A'.charCodeAt(0) + 10)
-                    : n;
-            }).join('');
+                        // Replace A, B, C, ..., Z with 10, 11, ..., 35
+                        ? (code - 'A'.charCodeAt(0) + 10)
+                        : n;
+            });
+            value = value.join('');
 
             var temp   = parseInt(value.substr(0, 1), 10),
                 length = value.length;

+ 378 - 11
src/js/validator/id.js

@@ -97,8 +97,6 @@
                 default:
                     return true;
             }
-
-            return true;
         },
 
         _ba: function(value) {
@@ -205,6 +203,63 @@
         },
 
         /**
+         * Validate Swiss Social Security Number (AHV-Nr/No AVS)
+         * Examples:
+         * - Valid: 756.1234.5678.95, 7561234567895
+         *
+         * @see http://en.wikipedia.org/wiki/National_identification_number#Switzerland
+         * @see http://www.bsv.admin.ch/themen/ahv/00011/02185/index.html?lang=de
+         * @param {String} value The ID
+         * @returns {Boolean}
+         */
+        _ch: function(value) {
+            if (!/^756[\.]{0,1}[0-9]{4}[\.]{0,1}[0-9]{4}[\.]{0,1}[0-9]{2}$/.test(value)) {
+                return false;
+            }
+            value = value.replace(/\D/g, '').substr(3);
+            var length = value.length,
+                sum    = 0,
+                weight = (length == 8) ? [3, 1] : [1, 3];
+            for (var i = 0; i < length - 1; i++) {
+                sum += parseInt(value.charAt(i)) * weight[i % 2];
+            }
+            sum = 10 - sum % 10;
+            return (sum == value.charAt(length - 1));
+        },
+
+        /**
+         * Validate Chilean national identification number (RUN/RUT)
+         * Examples:
+         * - Valid: 76086428-5, 22060449-7, 12531909-2
+         *
+         * @see http://en.wikipedia.org/wiki/National_identification_number#Chile
+         * @see https://palena.sii.cl/cvc/dte/ee_empresas_emisoras.html for samples
+         * @param {String} value The ID
+         * @returns {Boolean}
+         */
+        _cl: function(value) {
+            if (!/^\d{7,8}[-]{0,1}[0-9K]$/.test(value)) {
+                return false;
+            }
+            value = value.replace(/\D/g, '');
+            while (value.length < 9) {
+                value = '0' + value;
+            }
+            var sum    = 0,
+                weight = [3, 2, 7, 6, 5, 4, 3, 2];
+            for (var i = 0; i < 8; i++) {
+                sum += parseInt(value.charAt(i)) * weight[i];
+            }
+            sum = 11 - sum % 11;
+            if (sum == 11) {
+                sum = 0;
+            } else if (sum == 10) {
+                sum = 'K';
+            }
+            return sum == value.charAt(8);
+        },
+
+        /**
          * Validate Czech national identification number (RC)
          * Examples:
          * - Valid: 7103192745, 991231123
@@ -248,39 +303,121 @@
         },
 
         /**
-         * Validate Slovak national identifier number (RC)
+         * Validate Danish Personal Identification number (CPR)
          * Examples:
-         * - Valid: 7103192745, 991231123
-         * - Invalid: 7103192746, 1103492745
+         * - Valid: 2110625629, 211062-5629
+         * - Invalid: 511062-5629
          *
+         * @see https://en.wikipedia.org/wiki/Personal_identification_number_(Denmark)
          * @param {String} value The ID
          * @returns {Boolean}
          */
-        _sk: function(value) {
-            // Slovakia uses the same format as Czech Republic
-            return this._cz(value);
+        _dk: function(value) {
+            if (!/^[0-9]{6}[-]{0,1}[0-9]{4}$/.test(value)) {
+                return false;
+            }
+            value = value.replace(/-/g, '');
+            var day   = parseInt(value.substr(0, 2), 10),
+                month = parseInt(value.substr(2, 2), 10),
+                year  = parseInt(value.substr(4, 2), 10);
+
+            switch (true) {
+                case ('5678'.indexOf(value.charAt(6)) != -1 && year >= 58):
+                    year += 1800;
+                    break;
+                case ('0123'.indexOf(value.charAt(6)) != -1):
+                case ('49'.indexOf(value.charAt(6)) != -1 && year >= 37):
+                    year += 1900;
+                    break;
+                default:
+                    year += 2000;
+                    break;
+            }
+
+            return $.fn.bootstrapValidator.helpers.date(year, month, day);
+        },
+
+        /**
+         * Validate Estonian Personal Identification Code (isikukood)
+         * Examples:
+         * - Valid: 37605030299
+         *
+         * @see http://et.wikipedia.org/wiki/Isikukood
+         * @param {String} value The ID
+         * @returns {Boolean}
+         */
+        _ee: function(value) {
+            // Use the same format as Lithuanian Personal Code
+            return this._lt(value);
         },
 
         /**
          * Validate Spanish personal identity code (DNI)
+         * Support i) DNI (for Spanish citizens) and ii) NIE (for foreign people)
+         *
          * Examples:
-         * - Valid: 54362315K, 54362315-K
-         * - Invalid: 54362315Z
+         * - Valid: i) 54362315K, 54362315-K; ii) X2482300W, X-2482300W, X-2482300-W
+         * - Invalid: i) 54362315Z; ii) X-2482300A
          *
+         * @see https://en.wikipedia.org/wiki/National_identification_number#Spain
          * @param {String} value The ID
          * @returns {Boolean}
          */
         _es: function(value) {
-            if (!/^[0-9A-Z]{8}[-]{0,1}[0-9A-Z]{1}$/.test(value)) {
+            if (!/^[0-9A-Z]{8}[-]{0,1}[0-9A-Z]$/.test(value)                    // DNI
+                && !/^[XYZ][-]{0,1}[0-9]{7}[-]{0,1}[0-9A-Z]$/.test(value)) {    // NIE
                 return false;
             }
+
             value = value.replace(/-/g, '');
+            var index = 'XYZ'.indexOf(value.charAt(0));
+            if (index != -1) {
+                // It is NIE number
+                value = index + value.substr(1) + '';
+            }
+
             var check = parseInt(value.substr(0, 8), 10);
             check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23];
             return (check == value.substr(8, 1));
         },
 
         /**
+         * Validate Finnish Personal Identity Code (HETU)
+         * Examples:
+         * - Valid: 311280-888Y, 131052-308T
+         * - Invalid: 131052-308U, 310252-308Y
+         *
+         * @param {String} value The ID
+         * @returns {Boolean}
+         */
+        _fi: function(value) {
+            if (!/^[0-9]{6}[-+A][0-9]{3}[0-9ABCDEFHJKLMNPRSTUVWXY]$/.test(value)) {
+                return false;
+            }
+            var day       = parseInt(value.substr(0, 2), 10),
+                month     = parseInt(value.substr(2, 2), 10),
+                year      = parseInt(value.substr(4, 2), 10),
+                centuries = {
+                    '+': 1800,
+                    '-': 1900,
+                    'A': 2000
+                };
+            year = centuries[value.charAt(6)] + year;
+
+            if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) {
+                return false;
+            }
+
+            var individual = parseInt(value.substr(7, 3));
+            if (individual < 2) {
+                return false;
+            }
+            var n = value.substr(0, 6) + value.substr(7, 3) + '';
+            n = parseInt(n);
+            return '0123456789ABCDEFHJKLMNPRSTUVWXY'.charAt(n % 31) == value.charAt(10);
+        },
+
+        /**
          * Validate Croatian personal identification number (OIB)
          * Examples:
          * - Valid: 33392005961
@@ -297,6 +434,194 @@
         },
 
         /**
+         * Validate Irish Personal Public Service Number (PPS)
+         * Examples:
+         * - Valid: 6433435F, 6433435FT, 6433435FW, 6433435OA, 6433435IH, 1234567TW, 1234567FA
+         * - Invalid: 6433435E, 6433435VH
+         *
+         * @see https://en.wikipedia.org/wiki/Personal_Public_Service_Number
+         * @param {String} value The ID
+         * @returns {Boolean}
+         */
+        _ie: function(value) {
+            if (!/^\d{7}[A-W][AHWTX]?$/.test(value)) {
+                return false;
+            }
+
+            var getCheckDigit = function(value) {
+                while (value.length < 7) {
+                    value = '0' + value;
+                }
+                var alphabet = 'WABCDEFGHIJKLMNOPQRSTUV',
+                    sum      = 0;
+                for (var i = 0; i < 7; i++) {
+                    sum += parseInt(value.charAt(i)) * (8 - i);
+                }
+                sum += 9 * alphabet.indexOf(value.substr(7));
+                return alphabet[sum % 23];
+            };
+
+            // 2013 format
+            if (value.length == 9 && ('A' == value.charAt(8) || 'H' == value.charAt(8))) {
+                return value.charAt(7) == getCheckDigit(value.substr(0, 7) + value.substr(8) + '');
+            }
+            // The old format
+            else {
+                return value.charAt(7) == getCheckDigit(value.substr(0, 7));
+            }
+        },
+
+        /**
+         * Validate Iceland national identification number (Kennitala)
+         * Examples:
+         * - Valid: 120174-3399, 1201743399, 0902862349
+         *
+         * @see http://en.wikipedia.org/wiki/Kennitala
+         * @param {String} value The ID
+         * @returns {Boolean}
+         */
+        _is: function(value) {
+            if (!/^[0-9]{6}[-]{0,1}[0-9]{4}$/.test(value)) {
+                return false;
+            }
+            value = value.replace(/-/g, '');
+            var day     = parseInt(value.substr(0, 2), 10),
+                month   = parseInt(value.substr(2, 2), 10),
+                year    = parseInt(value.substr(4, 2), 10),
+                century = parseInt(value.charAt(9));
+
+            year = (century == 9) ? (1900 + year) : ((20 + century) * 100 + year);
+            if (!$.fn.bootstrapValidator.helpers.date(year, month, day, true)) {
+                return false;
+            }
+            // Validate the check digit
+            var sum    = 0,
+                weight = [3, 2, 7, 6, 5, 4, 3, 2];
+            for (var i = 0; i < 8; i++) {
+                sum += parseInt(value.charAt(i)) * weight[i];
+            }
+            sum = 11 - sum % 11;
+            return (sum == value.charAt(8));
+        },
+
+        /**
+         * Validate Lithuanian Personal Code (Asmens kodas)
+         * Examples:
+         * - Valid: 38703181745
+         * - Invalid: 38703181746, 78703181745, 38703421745
+         *
+         * @see http://en.wikipedia.org/wiki/National_identification_number#Lithuania
+         * @see http://www.adomas.org/midi2007/pcode.html
+         * @param {String} value The ID
+         * @returns {Boolean}
+         */
+        _lt: function(value) {
+            if (!/^[0-9]{11}$/.test(value)) {
+                return false;
+            }
+            var gender  = parseInt(value.charAt(0)),
+                year    = parseInt(value.substr(1, 2), 10),
+                month   = parseInt(value.substr(3, 2), 10),
+                day     = parseInt(value.substr(5, 2), 10),
+                century = (gender % 2 == 0) ? (17 + gender / 2) : (17 + (gender + 1) / 2);
+            year = century * 100 + year;
+            if (!$.fn.bootstrapValidator.helpers.date(year, month, day, true)) {
+                return false;
+            }
+
+            // Validate the check digit
+            var sum    = 0,
+                weight = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1];
+            for (var i = 0; i < 10; i++) {
+                sum += parseInt(value.charAt(i)) * weight[i];
+            }
+            sum = sum % 11;
+            if (sum != 10) {
+                return sum == value.charAt(10);
+            }
+
+            // Re-calculate the check digit
+            sum    = 0;
+            weight = [3, 4, 5, 6, 7, 8, 9, 1, 2, 3];
+            for (i = 0; i < 10; i++) {
+                sum += parseInt(value.charAt(i)) * weight[i];
+            }
+            sum = sum % 11;
+            if (sum == 10) {
+                sum = 0;
+            }
+            return (sum == value.charAt(10));
+        },
+
+        /**
+         * Validate Latvian Personal Code (Personas kods)
+         * Examples:
+         * - Valid: 161175-19997, 16117519997
+         * - Invalid: 161375-19997
+         *
+         * @see http://laacz.lv/2006/11/25/pk-parbaudes-algoritms/
+         * @param {String} value The ID
+         * @returns {Boolean}
+         */
+        _lv: function(value) {
+            if (!/^[0-9]{6}[-]{0,1}[0-9]{5}$/.test(value)) {
+                return false;
+            }
+            value = value.replace(/\D/g, '');
+            // Check birth date
+            var day   = parseInt(value.substr(0, 2)),
+                month = parseInt(value.substr(2, 2)),
+                year  = parseInt(value.substr(4, 2));
+            year = year + 1800 + parseInt(value.charAt(6)) * 100;
+
+            if (!$.fn.bootstrapValidator.helpers.date(year, month, day, true)) {
+                return false;
+            }
+
+            // Check personal code
+            var sum    = 0,
+                weight = [10, 5, 8, 4, 2, 1, 6, 3, 7, 9];
+            for (var i = 0; i < 10; i++) {
+                sum += parseInt(value.charAt(i)) * weight[i];
+            }
+            sum = (sum + 1) % 11 % 10;
+            return (sum == value.charAt(10));
+        },
+
+        /**
+         * Validate Dutch national identification number (BSN)
+         * Examples:
+         * - Valid: 111222333, 941331490, 9413.31.490
+         * - Invalid: 111252333
+         *
+         * @see https://nl.wikipedia.org/wiki/Burgerservicenummer
+         * @param {String} value The ID
+         * @returns {Boolean}
+         */
+        _nl: function(value) {
+            while (value.length < 9) {
+                value = '0' + value;
+            }
+            if (!/^[0-9]{4}[.]{0,1}[0-9]{2}[.]{0,1}[0-9]{3}$/.test(value)) {
+                return false;
+            }
+            value = value.replace(/\./g, '');
+            if (parseInt(value, 10) == 0) {
+                return false;
+            }
+            var sum    = 0,
+                length = value.length;
+            for (var i = 0; i < length - 1; i++) {
+                sum += (9 - i) * parseInt(value.charAt(i));
+            }
+            sum = sum % 11;
+            if (sum == 10) {
+                sum = 0;
+            }
+            return (sum == value.charAt(length - 1));
+        },
+
+        /**
          * Validate Romanian numerical personal code (CNP)
          * Examples:
          * - Valid: 1630615123457, 1800101221144
@@ -380,6 +705,20 @@
         },
 
         /**
+         * Validate Slovak national identifier number (RC)
+         * Examples:
+         * - Valid: 7103192745, 991231123
+         * - Invalid: 7103192746, 1103492745
+         *
+         * @param {String} value The ID
+         * @returns {Boolean}
+         */
+        _sk: function(value) {
+            // Slovakia uses the same format as Czech Republic
+            return this._cz(value);
+        },
+
+        /**
          * Validate San Marino citizen number
          *
          * @see http://en.wikipedia.org/wiki/National_identification_number#San_Marino
@@ -388,6 +727,34 @@
          */
         _sm: function(value) {
             return /^\d{5}$/.test(value);
+        },
+
+        /**
+         * Validate South African ID
+         * Example:
+         * - Valid: 8001015009087
+         * - Invalid: 8001015009287, 8001015009086
+         *
+         * @see http://en.wikipedia.org/wiki/National_identification_number#South_Africa
+         * @param {String} value The ID
+         * @returns {Boolean}
+         */
+        _za: function(value) {
+            if (!/^[0-9]{10}[0|1][8|9][0-9]$/.test(value)) {
+                return false;
+            }
+            var year        = parseInt(value.substr(0, 2)),
+                currentYear = new Date().getFullYear() % 100,
+                month       = parseInt(value.substr(2, 2)),
+                day         = parseInt(value.substr(4, 2));
+            year = (year >= currentYear) ? (year + 1900) : (year + 2000);
+
+            if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) {
+                return false;
+            }
+
+            // Validate the last check digit
+            return $.fn.bootstrapValidator.helpers.luhn(value);
         }
     };
 }(window.jQuery));

文件差异内容过多而无法显示
+ 55 - 0
src/js/validator/isin.js


+ 10 - 0
src/js/validator/numeric.js

@@ -1,5 +1,10 @@
 (function($) {
     $.fn.bootstrapValidator.validators.numeric = {
+        html5Attributes: {
+            message: 'message',
+            separator: 'separator'
+        },
+
         /**
          * Validate decimal number
          *
@@ -7,6 +12,7 @@
          * @param {jQuery} $field Field element
          * @param {Object} options Consist of key:
          * - message: The invalid message
+         * - separator: The decimal separator. Can be "." (default), ","
          * @returns {Boolean}
          */
         validate: function(validator, $field, options) {
@@ -14,6 +20,10 @@
             if (value == '') {
                 return true;
             }
+            var separator = options.separator || '.';
+            if (separator != '.') {
+                value = value.replace(separator, '.');
+            }
 
             return !isNaN(parseFloat(value)) && isFinite(value);
         }

+ 1 - 1
src/js/validator/remote.js

@@ -1,4 +1,4 @@
-(function ($) {
+(function($) {
     $.fn.bootstrapValidator.validators.remote = {
         html5Attributes: {
             message: 'message',

+ 34 - 0
src/js/validator/rtn.js

@@ -0,0 +1,34 @@
+(function($) {
+    $.fn.bootstrapValidator.validators.rtn = {
+        /**
+         * Validate a RTN (Routing transit number)
+         * Examples:
+         * - Valid: 021200025, 789456124
+         *
+         * @see http://en.wikipedia.org/wiki/Routing_transit_number
+         * @param {BootstrapValidator} validator The validator plugin instance
+         * @param {jQuery} $field Field element
+         * @param {Object} options Can consist of the following keys:
+         * - message: The invalid message
+         * @returns {Boolean}
+         */
+        validate: function(validator, $field, options) {
+            var value = $field.val();
+            if (value == '') {
+                return true;
+            }
+
+            if (!/^\d{9}$/.test(value)) {
+                return false;
+            }
+
+            var sum = 0;
+            for (var i = 0; i < value.length; i += 3) {
+                sum += parseInt(value.charAt(i),     10) * 3
+                    +  parseInt(value.charAt(i + 1), 10) * 7
+                    +  parseInt(value.charAt(i + 2), 10);
+            }
+            return (sum != 0 && sum % 10 == 0);
+        }
+    };
+}(window.jQuery));

+ 36 - 0
src/js/validator/sedol.js

@@ -0,0 +1,36 @@
+(function($) {
+    $.fn.bootstrapValidator.validators.sedol = {
+        /**
+         * Validate a SEDOL (Stock Exchange Daily Official List)
+         * Examples:
+         * - Valid: 0263494, B0WNLY7
+         *
+         * @see http://en.wikipedia.org/wiki/SEDOL
+         * @param {BootstrapValidator} validator The validator plugin instance
+         * @param {jQuery} $field Field element
+         * @param {Object} options Can consist of the following keys:
+         * - message: The invalid message
+         * @returns {Boolean}
+         */
+        validate: function(validator, $field, options) {
+            var value = $field.val();
+            if (value == '') {
+                return true;
+            }
+
+            value = value.toUpperCase();
+            if (!/^[0-9A-Z]{7}$/.test(value)) {
+                return false;
+            }
+
+            var sum    = 0,
+                weight = [1, 3, 1, 7, 3, 9, 1],
+                length = value.length;
+            for (var i = 0; i < length - 1; i++) {
+	            sum += weight[i] * parseInt(value.charAt(i), 36);
+	        }
+	        sum = (10 - sum % 10) % 10;
+            return sum == value.charAt(length - 1);
+        }
+    };
+}(window.jQuery));

+ 17 - 13
src/js/validator/zipCode.js

@@ -19,6 +19,8 @@
          * - CA (Canada)
          * - DK (Denmark)
          * - GB (United Kingdom)
+         * - IT (Italy)
+         * - NL (Netherlands)
          * - SE (Sweden)
          * @returns {Boolean}
          */
@@ -30,17 +32,19 @@
 
             var country = (options.country || 'US').toUpperCase();
             switch (country) {
-                case 'CA':
-                    return /(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}\s?[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}/i.test(value);
-                case 'DK':
-                    return /^(DK(-|\s)?)?\d{4}$/i.test(value);
-                case 'GB':
-                    return this._gb(value);
-                case 'SE':
-                    return /^(S-)?\d{3}\s?\d{2}$/i.test(value);
+                case 'CA': return /(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}\s?[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}/i.test(value);
+                case 'DK': return /^(DK(-|\s)?)?\d{4}$/i.test(value);
+                case 'GB': return this._gb(value);
+
+                // http://en.wikipedia.org/wiki/List_of_postal_codes_in_Italy
+                case 'IT': return /^(I-|IT-)?\d{5}$/i.test(value);
+
+                // http://en.wikipedia.org/wiki/Postal_codes_in_the_Netherlands
+                case 'NL': return /^[1-9][0-9]{3} ?(?!sa|sd|ss)[a-z]{2}$/i.test(value);
+
+                case 'SE': return /^(S-)?\d{3}\s?\d{2}$/i.test(value);
                 case 'US':
-                default:
-                    return /^\d{4,5}([\-]\d{4})?$/.test(value);
+                default: return /^\d{4,5}([\-]\d{4})?$/.test(value);
             }
         },
 
@@ -59,15 +63,15 @@
             var firstChar  = '[ABCDEFGHIJKLMNOPRSTUWYZ]',     // Does not accept QVX
                 secondChar = '[ABCDEFGHKLMNOPQRSTUVWXY]',     // Does not accept IJZ
                 thirdChar  = '[ABCDEFGHJKPMNRSTUVWXY]',
-                fouthChar  = '[ABEHMNPRVWXY]',
+                fourthChar = '[ABEHMNPRVWXY]',
                 fifthChar  = '[ABDEFGHJLNPQRSTUWXYZ]',
-                regexps = [
+                regexps    = [
                     // AN NAA, ANN NAA, AAN NAA, AANN NAA format
                     new RegExp('^(' + firstChar + '{1}' + secondChar + '?[0-9]{1,2})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'),
                     // ANA NAA
                     new RegExp('^(' + firstChar + '{1}[0-9]{1}' + thirdChar + '{1})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'),
                     // AANA NAA
-                    new RegExp('^(' + firstChar + '{1}' + secondChar + '{1}?[0-9]{1}' + fouthChar + '{1})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'),
+                    new RegExp('^(' + firstChar + '{1}' + secondChar + '{1}?[0-9]{1}' + fourthChar + '{1})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'),
 
                     new RegExp('^(BF1)(\\s*)([0-6]{1}[ABDEFGHJLNPQRST]{1}[ABDEFGHJLNPQRSTUWZYZ]{1})$', 'i'),        // BFPO postcodes
                     /^(GIR)(\s*)(0AA)$/i,                       // Special postcode GIR 0AA