bootstrap-validator-rails 0.5.2 → 0.5.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (39) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +1 -1
  3. data/lib/bootstrap-validator-rails/version.rb +2 -2
  4. data/vendor/assets/javascripts/bootstrapValidator.js +539 -124
  5. data/vendor/assets/javascripts/bootstrapValidator.min.js +7 -6
  6. data/vendor/assets/javascripts/language/ar_MA.js +16 -3
  7. data/vendor/assets/javascripts/language/be_FR.js +370 -0
  8. data/vendor/assets/javascripts/language/be_NL.js +14 -1
  9. data/vendor/assets/javascripts/language/bg_BG.js +14 -1
  10. data/vendor/assets/javascripts/language/cs_CZ.js +15 -2
  11. data/vendor/assets/javascripts/language/da_DK.js +15 -2
  12. data/vendor/assets/javascripts/language/de_DE.js +15 -2
  13. data/vendor/assets/javascripts/language/en_US.js +15 -2
  14. data/vendor/assets/javascripts/language/es_CL.js +15 -2
  15. data/vendor/assets/javascripts/language/es_ES.js +14 -1
  16. data/vendor/assets/javascripts/language/fa_IR.js +370 -0
  17. data/vendor/assets/javascripts/language/fr_FR.js +17 -4
  18. data/vendor/assets/javascripts/language/gr_EL.js +16 -3
  19. data/vendor/assets/javascripts/language/hu_HU.js +190 -177
  20. data/vendor/assets/javascripts/language/id_ID.js +370 -0
  21. data/vendor/assets/javascripts/language/it_IT.js +15 -2
  22. data/vendor/assets/javascripts/language/ja_JP.js +370 -0
  23. data/vendor/assets/javascripts/language/nl_NL.js +14 -1
  24. data/vendor/assets/javascripts/language/no_NO.js +370 -0
  25. data/vendor/assets/javascripts/language/pl_PL.js +14 -1
  26. data/vendor/assets/javascripts/language/pt_BR.js +17 -4
  27. data/vendor/assets/javascripts/language/ro_RO.js +370 -0
  28. data/vendor/assets/javascripts/language/ru_RU.js +370 -0
  29. data/vendor/assets/javascripts/language/sr_RS.js +370 -0
  30. data/vendor/assets/javascripts/language/sv_SE.js +370 -0
  31. data/vendor/assets/javascripts/language/th_TH.js +370 -0
  32. data/vendor/assets/javascripts/language/tr_TR.js +15 -2
  33. data/vendor/assets/javascripts/language/ua_UA.js +370 -0
  34. data/vendor/assets/javascripts/language/vi_VN.js +14 -1
  35. data/vendor/assets/javascripts/language/zh_CN.js +14 -1
  36. data/vendor/assets/javascripts/language/zh_TW.js +14 -1
  37. data/vendor/assets/stylesheets/bootstrapValidator.css +2 -1
  38. data/vendor/assets/stylesheets/bootstrapValidator.min.css +3 -2
  39. metadata +13 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 38c37b4ddad28ac35bf3bb88f14ce65384010f42
4
- data.tar.gz: 333b2c34b2eec6756a853637ed149f2c742a9587
3
+ metadata.gz: cf2acca332fdc5b9ec005f09b2a0240bedc4613d
4
+ data.tar.gz: b4c44a5da71c12ab78e814e0d984a31969ab1159
5
5
  SHA512:
6
- metadata.gz: b55f2222d42ae011c4bbaf8adfc388aa48c59001054ca918f5e6ff4155e892a02813d8f1815646b5748c3bfe2774520bea8c38f3126c2323495be27b4c4cb52b
7
- data.tar.gz: 6414b5f3cca5ede7d41e76cf73653ef2e9c028950c88fedaf3d83fe504e2d5e714c03fe51176d4da599f314111ef5e887e0a8fabaaaf1d3831d210dd343d79a3
6
+ metadata.gz: c922b884ca534ea0685d4af36724da3f53c8ead9ba393f0fbc13d077d891f827dd6a157ba9f424f17a972c135b9ccf15cc45c64900641624e4945a536482f9f0
7
+ data.tar.gz: 4c6c8e98647989ff14ecef5ed6ddf5c9952346db1c799bc06043bf2db5b190422158c588b649e006209905e32db9e246b1fe094e2c2fceac127dd589338d5a5f
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- bootstrap-validator-rails (0.5.1)
1
+ bootstrap-validator-rails (0.5.2)
2
2
  =================================
3
3
 
4
4
  Gem version of bootstrapvalidator JavaScript library = a jQuery based field validator for Twitter Bootstrap 3.
@@ -1,6 +1,6 @@
1
1
  module BootstrapValidatorRails
2
2
  module Rails
3
- VERSION = "0.5.2"
4
- BOOTSTRAP_VALIDATOR_VERSION = "0.5.2"
3
+ VERSION = "0.5.3"
4
+ BOOTSTRAP_VALIDATOR_VERSION = "0.5.3"
5
5
  end
6
6
  end
@@ -2,15 +2,23 @@
2
2
  * BootstrapValidator (http://bootstrapvalidator.com)
3
3
  * The best jQuery plugin to validate form fields. Designed to use with Bootstrap 3
4
4
  *
5
- * @version v0.5.2, built on 2014-09-25 4:01:07 PM
5
+ * @version v0.5.3, built on 2014-11-05 9:14:18 PM
6
6
  * @author https://twitter.com/nghuuphuoc
7
7
  * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc
8
- * @license MIT
8
+ * @license Commercial: http://bootstrapvalidator.com/license/
9
+ * Non-commercial: http://creativecommons.org/licenses/by-nc-nd/3.0/
9
10
  */
10
11
  if (typeof jQuery === 'undefined') {
11
- throw new Error('BootstrapValidator\'s JavaScript requires jQuery');
12
+ throw new Error('BootstrapValidator requires jQuery');
12
13
  }
13
14
 
15
+ (function($) {
16
+ var version = $.fn.jquery.split(' ')[0].split('.');
17
+ if ((+version[0] < 2 && +version[1] < 9) || (+version[0] === 1 && +version[1] === 9 && +version[2] < 1)) {
18
+ throw new Error('BootstrapValidator requires jQuery version 1.9.1 or higher');
19
+ }
20
+ }(window.jQuery));
21
+
14
22
  (function($) {
15
23
  var BootstrapValidator = function(form, options) {
16
24
  this.$form = $(form);
@@ -58,6 +66,7 @@ if (typeof jQuery === 'undefined') {
58
66
  _init: function() {
59
67
  var that = this,
60
68
  options = {
69
+ autoFocus: this.$form.attr('data-bv-autofocus'),
61
70
  container: this.$form.attr('data-bv-container'),
62
71
  events: {
63
72
  formInit: this.$form.attr('data-bv-events-form-init'),
@@ -176,19 +185,22 @@ if (typeof jQuery === 'undefined') {
176
185
  validators = {},
177
186
  validator,
178
187
  v, // Validator name
188
+ attrName,
179
189
  enabled,
180
190
  optionName,
191
+ optionAttrName,
181
192
  optionValue,
182
193
  html5AttrName,
183
194
  html5AttrMap;
184
195
 
185
196
  for (v in $.fn.bootstrapValidator.validators) {
186
197
  validator = $.fn.bootstrapValidator.validators[v];
187
- enabled = $field.attr('data-bv-' + v.toLowerCase()) + '';
198
+ attrName = 'data-bv-' + v.toLowerCase(),
199
+ enabled = $field.attr(attrName) + '';
188
200
  html5AttrMap = ('function' === typeof validator.enableByHtml5) ? validator.enableByHtml5($field) : null;
189
201
 
190
202
  if ((html5AttrMap && enabled !== 'false')
191
- || (html5AttrMap !== true && ('' === enabled || 'true' === enabled)))
203
+ || (html5AttrMap !== true && ('' === enabled || 'true' === enabled || attrName === enabled.toLowerCase())))
192
204
  {
193
205
  // Try to parse the options via attributes
194
206
  validator.html5Attributes = $.extend({}, { message: 'message', onerror: 'onError', onsuccess: 'onSuccess' }, validator.html5Attributes);
@@ -196,9 +208,10 @@ if (typeof jQuery === 'undefined') {
196
208
 
197
209
  for (html5AttrName in validator.html5Attributes) {
198
210
  optionName = validator.html5Attributes[html5AttrName];
199
- optionValue = $field.attr('data-bv-' + v.toLowerCase() + '-' + html5AttrName);
211
+ optionAttrName = 'data-bv-' + v.toLowerCase() + '-' + html5AttrName,
212
+ optionValue = $field.attr(optionAttrName);
200
213
  if (optionValue) {
201
- if ('true' === optionValue) {
214
+ if ('true' === optionValue || optionAttrName === optionValue.toLowerCase()) {
202
215
  optionValue = true;
203
216
  } else if ('false' === optionValue) {
204
217
  optionValue = false;
@@ -210,6 +223,7 @@ if (typeof jQuery === 'undefined') {
210
223
  }
211
224
 
212
225
  var opts = {
226
+ autoFocus: $field.attr('data-bv-autofocus'),
213
227
  container: $field.attr('data-bv-container'),
214
228
  excluded: $field.attr('data-bv-excluded'),
215
229
  feedbackIcons: $field.attr('data-bv-feedbackicons'),
@@ -364,32 +378,40 @@ if (typeof jQuery === 'undefined') {
364
378
  $icon.addClass('bv-icon-input-group')
365
379
  .insertAfter($parent.find('.input-group').eq(0));
366
380
  }
381
+
382
+ // Store the icon as a data of field element
383
+ if (!updateAll) {
384
+ $field.data('bv.icon', $icon);
385
+ } else if (i === total - 1) {
386
+ // All fields with the same name have the same icon
387
+ fields.data('bv.icon', $icon);
388
+ }
367
389
 
368
390
  if (container) {
369
391
  $field
370
392
  // Show tooltip/popover message when field gets focus
371
- .off('focus.bv')
372
- .on('focus.bv', function() {
393
+ .off('focus.container.bv')
394
+ .on('focus.container.bv', function() {
373
395
  switch (container) {
374
396
  case 'tooltip':
375
- $icon.tooltip('show');
397
+ $(this).data('bv.icon').tooltip('show');
376
398
  break;
377
399
  case 'popover':
378
- $icon.popover('show');
400
+ $(this).data('bv.icon').popover('show');
379
401
  break;
380
402
  default:
381
403
  break;
382
404
  }
383
405
  })
384
406
  // and hide them when losing focus
385
- .off('blur.bv')
386
- .on('blur.bv', function() {
407
+ .off('blur.container.bv')
408
+ .on('blur.container.bv', function() {
387
409
  switch (container) {
388
410
  case 'tooltip':
389
- $icon.tooltip('hide');
411
+ $(this).data('bv.icon').tooltip('hide');
390
412
  break;
391
413
  case 'popover':
392
- $icon.popover('hide');
414
+ $(this).data('bv.icon').popover('hide');
393
415
  break;
394
416
  default:
395
417
  break;
@@ -634,16 +656,21 @@ if (typeof jQuery === 'undefined') {
634
656
  }
635
657
  }
636
658
 
637
- var $invalidField = this.$invalidFields.eq(0);
638
- if ($invalidField) {
639
- // Activate the tab containing the invalid field if exists
640
- var $tabPane = $invalidField.parents('.tab-pane'), tabId;
641
- if ($tabPane && (tabId = $tabPane.attr('id'))) {
642
- $('a[href="#' + tabId + '"][data-toggle="tab"]').tab('show');
643
- }
659
+ // Determined the first invalid field which will be focused on automatically
660
+ for (var i = 0; i < this.$invalidFields.length; i++) {
661
+ var $field = this.$invalidFields.eq(i),
662
+ autoFocus = this._isOptionEnabled($field.attr('data-bv-field'), 'autoFocus');
663
+ if (autoFocus) {
664
+ // Activate the tab containing the field if exists
665
+ var $tabPane = $field.parents('.tab-pane'), tabId;
666
+ if ($tabPane && (tabId = $tabPane.attr('id'))) {
667
+ $('a[href="#' + tabId + '"][data-toggle="tab"]').tab('show');
668
+ }
644
669
 
645
- // Focus to the first invalid field
646
- $invalidField.focus();
670
+ // Focus the field
671
+ $field.focus();
672
+ break;
673
+ }
647
674
  }
648
675
  },
649
676
 
@@ -719,7 +746,7 @@ if (typeof jQuery === 'undefined') {
719
746
  $field.trigger($.Event(this.options.events.fieldSuccess), data);
720
747
  }
721
748
  // If all validators are completed and there is at least one validator which doesn't pass
722
- else if (counter[this.STATUS_NOT_VALIDATED] === 0 && counter[this.STATUS_VALIDATING] === 0 && counter[this.STATUS_INVALID] > 0) {
749
+ else if ((counter[this.STATUS_NOT_VALIDATED] === 0 || !this._isOptionEnabled(field, 'verbose')) && counter[this.STATUS_VALIDATING] === 0 && counter[this.STATUS_INVALID] > 0) {
723
750
  // Add to the list of invalid fields
724
751
  this.$invalidFields = this.$invalidFields.add($field);
725
752
 
@@ -727,6 +754,23 @@ if (typeof jQuery === 'undefined') {
727
754
  }
728
755
  },
729
756
 
757
+ /**
758
+ * Check whether or not a field option is enabled
759
+ *
760
+ * @param {String} field The field name
761
+ * @param {String} option The option name, "verbose", "autoFocus", for example
762
+ * @returns {Boolean}
763
+ */
764
+ _isOptionEnabled: function(field, option) {
765
+ if (this.options.fields[field] && (this.options.fields[field][option] === 'true' || this.options.fields[field][option] === true)) {
766
+ return true;
767
+ }
768
+ if (this.options.fields[field] && (this.options.fields[field][option] === 'false' || this.options.fields[field][option] === false)) {
769
+ return false;
770
+ }
771
+ return this.options[option] === 'true' || this.options[option] === true;
772
+ },
773
+
730
774
  // ---
731
775
  // Public methods
732
776
  // ---
@@ -757,7 +801,7 @@ if (typeof jQuery === 'undefined') {
757
801
  */
758
802
  getOptions: function(field, validator, option) {
759
803
  if (!field) {
760
- return this.options;
804
+ return option ? this.options[option] : this.options;
761
805
  }
762
806
  if ('object' === typeof field) {
763
807
  field = field.attr('data-bv-field');
@@ -777,7 +821,6 @@ if (typeof jQuery === 'undefined') {
777
821
  return option ? options.validators[validator][option] : options.validators[validator];
778
822
  },
779
823
 
780
-
781
824
  /**
782
825
  * Disable/enable submit buttons
783
826
  *
@@ -806,11 +849,13 @@ if (typeof jQuery === 'undefined') {
806
849
  }
807
850
  this.disableSubmitButtons(true);
808
851
 
852
+ this._submitIfValid = false;
809
853
  for (var field in this.options.fields) {
810
854
  this.validateField(field);
811
855
  }
812
856
 
813
857
  this._submit();
858
+ this._submitIfValid = true;
814
859
 
815
860
  return this;
816
861
  },
@@ -835,7 +880,7 @@ if (typeof jQuery === 'undefined') {
835
880
  break;
836
881
  }
837
882
 
838
- if (fields.length === 0 || (this.options.fields[field] && this.options.fields[field].enabled === false)) {
883
+ if (fields.length === 0 || !this.options.fields[field] || this.options.fields[field].enabled === false) {
839
884
  return this;
840
885
  }
841
886
 
@@ -844,7 +889,7 @@ if (typeof jQuery === 'undefined') {
844
889
  total = ('radio' === type || 'checkbox' === type) ? 1 : fields.length,
845
890
  updateAll = ('radio' === type || 'checkbox' === type),
846
891
  validators = this.options.fields[field].validators,
847
- verbose = this.options.fields[field].verbose === 'true' || this.options.fields[field].verbose === true || this.options.verbose === 'true' || this.options.verbose === true,
892
+ verbose = this._isOptionEnabled(field, 'verbose'),
848
893
  validatorName,
849
894
  validateResult;
850
895
 
@@ -972,6 +1017,7 @@ if (typeof jQuery === 'undefined') {
972
1017
 
973
1018
  if (status === this.STATUS_NOT_VALIDATED) {
974
1019
  // Reset the flag
1020
+ // To prevent the form from doing submit when a deferred validator returns true while typing
975
1021
  this._submitIfValid = false;
976
1022
  }
977
1023
 
@@ -990,7 +1036,7 @@ if (typeof jQuery === 'undefined') {
990
1036
  $message = $field.data('bv.messages'),
991
1037
  $allErrors = $message.find('.help-block[data-bv-validator][data-bv-for="' + field + '"]'),
992
1038
  $errors = validatorName ? $allErrors.filter('[data-bv-validator="' + validatorName + '"]') : $allErrors,
993
- $icon = $parent.find('.form-control-feedback[data-bv-icon-for="' + field + '"]'),
1039
+ $icon = $field.data('bv.icon'),
994
1040
  container = ('function' === typeof (this.options.fields[field].container || this.options.container)) ? (this.options.fields[field].container || this.options.container).call(this, $field, this) : (this.options.fields[field].container || this.options.container),
995
1041
  isValidField = null;
996
1042
 
@@ -1081,10 +1127,10 @@ if (typeof jQuery === 'undefined') {
1081
1127
  ? $icon.css('cursor', 'pointer').tooltip('destroy').tooltip({
1082
1128
  container: 'body',
1083
1129
  html: true,
1084
- placement: 'top',
1130
+ placement: 'auto top',
1085
1131
  title: $allErrors.filter('[data-bv-result="' + that.STATUS_INVALID + '"]').eq(0).html()
1086
1132
  })
1087
- : $icon.tooltip('hide');
1133
+ : $icon.css('cursor', '').tooltip('destroy');
1088
1134
  break;
1089
1135
  // ... or popover
1090
1136
  case ($icon && 'popover' === container):
@@ -1093,10 +1139,10 @@ if (typeof jQuery === 'undefined') {
1093
1139
  container: 'body',
1094
1140
  content: $allErrors.filter('[data-bv-result="' + that.STATUS_INVALID + '"]').eq(0).html(),
1095
1141
  html: true,
1096
- placement: 'top',
1142
+ placement: 'auto top',
1097
1143
  trigger: 'hover click'
1098
1144
  })
1099
- : $icon.popover('hide');
1145
+ : $icon.css('cursor', '').popover('destroy');
1100
1146
  break;
1101
1147
  default:
1102
1148
  (status === this.STATUS_INVALID) ? $errors.show() : $errors.hide();
@@ -1150,7 +1196,7 @@ if (typeof jQuery === 'undefined') {
1150
1196
  default:
1151
1197
  break;
1152
1198
  }
1153
- if (fields.length === 0 || this.options.fields[field] === null || this.options.fields[field].enabled === false) {
1199
+ if (fields.length === 0 || !this.options.fields[field] || this.options.fields[field].enabled === false) {
1154
1200
  return true;
1155
1201
  }
1156
1202
 
@@ -1609,7 +1655,7 @@ if (typeof jQuery === 'undefined') {
1609
1655
  .removeAttr('data-bv-field');
1610
1656
 
1611
1657
  // Remove feedback icons, tooltip/popover container
1612
- $icon = $field.parents(group).find('i[data-bv-icon-for="' + field + '"]');
1658
+ $icon = $field.data('bv.icon');
1613
1659
  if ($icon) {
1614
1660
  var container = ('function' === typeof (this.options.fields[field].container || this.options.container)) ? (this.options.fields[field].container || this.options.container).call(this, $field, this) : (this.options.fields[field].container || this.options.container);
1615
1661
  switch (container) {
@@ -1624,6 +1670,7 @@ if (typeof jQuery === 'undefined') {
1624
1670
  break;
1625
1671
  }
1626
1672
  }
1673
+ $field.removeData('bv.icon');
1627
1674
 
1628
1675
  for (validator in this.options.fields[field].validators) {
1629
1676
  if ($field.data('bv.dfs.' + validator)) {
@@ -1674,17 +1721,10 @@ if (typeof jQuery === 'undefined') {
1674
1721
  };
1675
1722
 
1676
1723
  // The default options
1724
+ // Sorted in alphabetical order
1677
1725
  $.fn.bootstrapValidator.DEFAULT_OPTIONS = {
1678
- // The form CSS class
1679
- elementClass: 'bv-form',
1680
-
1681
- // Default invalid message
1682
- message: 'This value is not valid',
1683
-
1684
- // The CSS selector for indicating the element consists the field
1685
- // By default, each field is placed inside the <div class="form-group"></div>
1686
- // You should adjust this option if your form group consists of many fields which not all of them need to be validated
1687
- group: '.form-group',
1726
+ // The first invalid field will be focused automatically
1727
+ autoFocus: true,
1688
1728
 
1689
1729
  //The error messages container. It can be:
1690
1730
  // - 'tooltip' if you want to use Bootstrap tooltip to show error messages
@@ -1694,8 +1734,24 @@ if (typeof jQuery === 'undefined') {
1694
1734
  // You also can define the message container for particular field
1695
1735
  container: null,
1696
1736
 
1697
- // The field will not be live validated if its length is less than this number of characters
1698
- threshold: null,
1737
+ // The form CSS class
1738
+ elementClass: 'bv-form',
1739
+
1740
+ // Use custom event name to avoid window.onerror being invoked by jQuery
1741
+ // See https://github.com/nghuuphuoc/bootstrapvalidator/issues/630
1742
+ events: {
1743
+ formInit: 'init.form.bv',
1744
+ formError: 'error.form.bv',
1745
+ formSuccess: 'success.form.bv',
1746
+ fieldAdded: 'added.field.bv',
1747
+ fieldRemoved: 'removed.field.bv',
1748
+ fieldInit: 'init.field.bv',
1749
+ fieldError: 'error.field.bv',
1750
+ fieldSuccess: 'success.field.bv',
1751
+ fieldStatus: 'status.field.bv',
1752
+ validatorError: 'error.validator.bv',
1753
+ validatorSuccess: 'success.validator.bv'
1754
+ },
1699
1755
 
1700
1756
  // Indicate fields which won't be validated
1701
1757
  // By default, the plugin will not validate the following kind of fields:
@@ -1746,9 +1802,13 @@ if (typeof jQuery === 'undefined') {
1746
1802
  validating: null
1747
1803
  },
1748
1804
 
1749
- // The submit buttons selector
1750
- // These buttons will be disabled to prevent the valid form from multiple submissions
1751
- submitButtons: '[type="submit"]',
1805
+ // Map the field name with validator rules
1806
+ fields: null,
1807
+
1808
+ // The CSS selector for indicating the element consists the field
1809
+ // By default, each field is placed inside the <div class="form-group"></div>
1810
+ // You should adjust this option if your form group consists of many fields which not all of them need to be validated
1811
+ group: '.form-group',
1752
1812
 
1753
1813
  // Live validating option
1754
1814
  // Can be one of 3 values:
@@ -1757,25 +1817,16 @@ if (typeof jQuery === 'undefined') {
1757
1817
  // - submitted: The live validating is enabled after the form is submitted
1758
1818
  live: 'enabled',
1759
1819
 
1760
- // Map the field name with validator rules
1761
- fields: null,
1820
+ // Default invalid message
1821
+ message: 'This value is not valid',
1822
+
1823
+ // The submit buttons selector
1824
+ // These buttons will be disabled to prevent the valid form from multiple submissions
1825
+ submitButtons: '[type="submit"]',
1826
+
1827
+ // The field will not be live validated if its length is less than this number of characters
1828
+ threshold: null,
1762
1829
 
1763
- // Use custom event name to avoid window.onerror being invoked by jQuery
1764
- // See https://github.com/nghuuphuoc/bootstrapvalidator/issues/630
1765
- events: {
1766
- formInit: 'init.form.bv',
1767
- formError: 'error.form.bv',
1768
- formSuccess: 'success.form.bv',
1769
- fieldAdded: 'added.field.bv',
1770
- fieldRemoved: 'removed.field.bv',
1771
- fieldInit: 'init.field.bv',
1772
- fieldError: 'error.field.bv',
1773
- fieldSuccess: 'success.field.bv',
1774
- fieldStatus: 'status.field.bv',
1775
- validatorError: 'error.validator.bv',
1776
- validatorSuccess: 'success.validator.bv'
1777
- },
1778
-
1779
1830
  // Whether to be verbose when validating a field or not.
1780
1831
  // Possible values:
1781
1832
  // - true: when a field has multiple validators, all of them will be checked, and respectively - if errors occur in
@@ -2024,22 +2075,31 @@ if (typeof jQuery === 'undefined') {
2024
2075
  if (value === '') {
2025
2076
  return true;
2026
2077
  }
2078
+
2079
+ value = this._format(value);
2027
2080
  if (!$.isNumeric(value)) {
2028
2081
  return false;
2029
2082
  }
2030
2083
 
2031
- var min = $.isNumeric(options.min) ? options.min : validator.getDynamicOption($field, options.min),
2032
- max = $.isNumeric(options.max) ? options.max : validator.getDynamicOption($field, options.max);
2084
+ var min = $.isNumeric(options.min) ? options.min : validator.getDynamicOption($field, options.min),
2085
+ max = $.isNumeric(options.max) ? options.max : validator.getDynamicOption($field, options.max),
2086
+ minValue = this._format(min),
2087
+ maxValue = this._format(max);
2088
+
2033
2089
  value = parseFloat(value);
2034
2090
  return (options.inclusive === true || options.inclusive === undefined)
2035
2091
  ? {
2036
- valid: value >= min && value <= max,
2092
+ valid: value >= minValue && value <= maxValue,
2037
2093
  message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.between['default'], [min, max])
2038
2094
  }
2039
2095
  : {
2040
- valid: value > min && value < max,
2096
+ valid: value > minValue && value < maxValue,
2041
2097
  message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.between.notInclusive, [min, max])
2042
2098
  };
2099
+ },
2100
+
2101
+ _format: function(value) {
2102
+ return (value + '').replace(',', '.');
2043
2103
  }
2044
2104
  };
2045
2105
  }(window.jQuery));
@@ -2181,6 +2241,135 @@ if (typeof jQuery === 'undefined') {
2181
2241
  }
2182
2242
  };
2183
2243
  }(window.jQuery));
2244
+ ;(function($) {
2245
+ $.fn.bootstrapValidator.i18n.color = $.extend($.fn.bootstrapValidator.i18n.color || {}, {
2246
+ 'default': 'Please enter a valid color'
2247
+ });
2248
+
2249
+ $.fn.bootstrapValidator.validators.color = {
2250
+ SUPPORTED_TYPES: [
2251
+ 'hex', 'rgb', 'rgba', 'hsl', 'hsla', 'keyword'
2252
+ ],
2253
+
2254
+ KEYWORD_COLORS: [
2255
+ // Colors start with A
2256
+ 'aliceblue', 'antiquewhite', 'aqua', 'aquamarine', 'azure',
2257
+ // B
2258
+ 'beige', 'bisque', 'black', 'blanchedalmond', 'blue', 'blueviolet', 'brown', 'burlywood',
2259
+ // C
2260
+ 'cadetblue', 'chartreuse', 'chocolate', 'coral', 'cornflowerblue', 'cornsilk', 'crimson', 'cyan',
2261
+ // D
2262
+ 'darkblue', 'darkcyan', 'darkgoldenrod', 'darkgray', 'darkgreen', 'darkgrey', 'darkkhaki', 'darkmagenta',
2263
+ 'darkolivegreen', 'darkorange', 'darkorchid', 'darkred', 'darksalmon', 'darkseagreen', 'darkslateblue',
2264
+ 'darkslategray', 'darkslategrey', 'darkturquoise', 'darkviolet', 'deeppink', 'deepskyblue', 'dimgray',
2265
+ 'dimgrey', 'dodgerblue',
2266
+ // F
2267
+ 'firebrick', 'floralwhite', 'forestgreen', 'fuchsia',
2268
+ // G
2269
+ 'gainsboro', 'ghostwhite', 'gold', 'goldenrod', 'gray', 'green', 'greenyellow', 'grey',
2270
+ // H
2271
+ 'honeydew', 'hotpink',
2272
+ // I
2273
+ 'indianred', 'indigo', 'ivory',
2274
+ // K
2275
+ 'khaki',
2276
+ // L
2277
+ 'lavender', 'lavenderblush', 'lawngreen', 'lemonchiffon', 'lightblue', 'lightcoral', 'lightcyan',
2278
+ 'lightgoldenrodyellow', 'lightgray', 'lightgreen', 'lightgrey', 'lightpink', 'lightsalmon', 'lightseagreen',
2279
+ 'lightskyblue', 'lightslategray', 'lightslategrey', 'lightsteelblue', 'lightyellow', 'lime', 'limegreen',
2280
+ 'linen',
2281
+ // M
2282
+ 'magenta', 'maroon', 'mediumaquamarine', 'mediumblue', 'mediumorchid', 'mediumpurple', 'mediumseagreen',
2283
+ 'mediumslateblue', 'mediumspringgreen', 'mediumturquoise', 'mediumvioletred', 'midnightblue', 'mintcream',
2284
+ 'mistyrose', 'moccasin',
2285
+ // N
2286
+ 'navajowhite', 'navy',
2287
+ // O
2288
+ 'oldlace', 'olive', 'olivedrab', 'orange', 'orangered', 'orchid',
2289
+ // P
2290
+ 'palegoldenrod', 'palegreen', 'paleturquoise', 'palevioletred', 'papayawhip', 'peachpuff', 'peru', 'pink',
2291
+ 'plum', 'powderblue', 'purple',
2292
+ // R
2293
+ 'red', 'rosybrown', 'royalblue',
2294
+ // S
2295
+ 'saddlebrown', 'salmon', 'sandybrown', 'seagreen', 'seashell', 'sienna', 'silver', 'skyblue', 'slateblue',
2296
+ 'slategray', 'slategrey', 'snow', 'springgreen', 'steelblue',
2297
+ // T
2298
+ 'tan', 'teal', 'thistle', 'tomato', 'transparent', 'turquoise',
2299
+ // V
2300
+ 'violet',
2301
+ // W
2302
+ 'wheat', 'white', 'whitesmoke',
2303
+ // Y
2304
+ 'yellow', 'yellowgreen'
2305
+ ],
2306
+
2307
+ /**
2308
+ * Return true if the input value is a valid color
2309
+ *
2310
+ * @param {BootstrapValidator} validator The validator plugin instance
2311
+ * @param {jQuery} $field Field element
2312
+ * @param {Object} options Can consist of the following keys:
2313
+ * - message: The invalid message
2314
+ * - type: The array of valid color types
2315
+ * @returns {Boolean}
2316
+ */
2317
+ validate: function(validator, $field, options) {
2318
+ var value = $field.val();
2319
+ if (value === '') {
2320
+ return true;
2321
+ }
2322
+
2323
+ var types = options.type || this.SUPPORTED_TYPES;
2324
+ if (!$.isArray(types)) {
2325
+ types = types.replace(/s/g, '').split(',');
2326
+ }
2327
+
2328
+ var method,
2329
+ type,
2330
+ isValid = false;
2331
+
2332
+ for (var i = 0; i < types.length; i++) {
2333
+ type = types[i];
2334
+ method = '_' + type.toLowerCase();
2335
+ isValid = isValid || this[method](value);
2336
+ if (isValid) {
2337
+ return true;
2338
+ }
2339
+ }
2340
+
2341
+ return false;
2342
+ },
2343
+
2344
+ _hex: function(value) {
2345
+ return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value);
2346
+ },
2347
+
2348
+ _hsl: function(value) {
2349
+ return /^hsl\((\s*(-?\d+)\s*,)(\s*(\b(0?\d{1,2}|100)\b%)\s*,)(\s*(\b(0?\d{1,2}|100)\b%)\s*)\)$/.test(value);
2350
+ },
2351
+
2352
+ _hsla: function(value) {
2353
+ return /^hsla\((\s*(-?\d+)\s*,)(\s*(\b(0?\d{1,2}|100)\b%)\s*,){2}(\s*(0?(\.\d+)?|1(\.0+)?)\s*)\)$/.test(value);
2354
+ },
2355
+
2356
+ _keyword: function(value) {
2357
+ return $.inArray(value, this.KEYWORD_COLORS) >= 0;
2358
+ },
2359
+
2360
+ _rgb: function(value) {
2361
+ var regexInteger = /^rgb\((\s*(\b([01]?\d{1,2}|2[0-4]\d|25[0-5])\b)\s*,){2}(\s*(\b([01]?\d{1,2}|2[0-4]\d|25[0-5])\b)\s*)\)$/,
2362
+ regexPercent = /^rgb\((\s*(\b(0?\d{1,2}|100)\b%)\s*,){2}(\s*(\b(0?\d{1,2}|100)\b%)\s*)\)$/;
2363
+ return regexInteger.test(value) || regexPercent.test(value);
2364
+ },
2365
+
2366
+ _rgba: function(value) {
2367
+ var regexInteger = /^rgba\((\s*(\b([01]?\d{1,2}|2[0-4]\d|25[0-5])\b)\s*,){3}(\s*(0?(\.\d+)?|1(\.0+)?)\s*)\)$/,
2368
+ regexPercent = /^rgba\((\s*(\b(0?\d{1,2}|100)\b%)\s*,){3}(\s*(0?(\.\d+)?|1(\.0+)?)\s*)\)$/;
2369
+ return regexInteger.test(value) || regexPercent.test(value);
2370
+ }
2371
+ };
2372
+ }(window.jQuery));
2184
2373
  ;(function($) {
2185
2374
  $.fn.bootstrapValidator.i18n.creditCard = $.extend($.fn.bootstrapValidator.i18n.creditCard || {}, {
2186
2375
  'default': 'Please enter a valid credit card number'
@@ -2457,13 +2646,18 @@ if (typeof jQuery === 'undefined') {
2457
2646
  }(window.jQuery));
2458
2647
  ;(function($) {
2459
2648
  $.fn.bootstrapValidator.i18n.date = $.extend($.fn.bootstrapValidator.i18n.date || {}, {
2460
- 'default': 'Please enter a valid date'
2649
+ 'default': 'Please enter a valid date',
2650
+ min: 'Please enter a date after %s',
2651
+ max: 'Please enter a date before %s',
2652
+ range: 'Please enter a date in the range %s - %s'
2461
2653
  });
2462
2654
 
2463
2655
  $.fn.bootstrapValidator.validators.date = {
2464
2656
  html5Attributes: {
2465
2657
  message: 'message',
2466
2658
  format: 'format',
2659
+ min: 'min',
2660
+ max: 'max',
2467
2661
  separator: 'separator'
2468
2662
  },
2469
2663
 
@@ -2474,6 +2668,8 @@ if (typeof jQuery === 'undefined') {
2474
2668
  * @param {jQuery} $field Field element
2475
2669
  * @param {Object} options Can consist of the following keys:
2476
2670
  * - message: The invalid message
2671
+ * - min: the minimum date
2672
+ * - max: the maximum date
2477
2673
  * - separator: Use to separate the date, month, and year.
2478
2674
  * By default, it is /
2479
2675
  * - format: The date format. Default is MM/DD/YYYY
@@ -2483,7 +2679,7 @@ if (typeof jQuery === 'undefined') {
2483
2679
  * ii) date and time:
2484
2680
  * The time can consist of h, m, s parts which are separated by :
2485
2681
  * ii) date, time and A (indicating AM or PM)
2486
- * @returns {Boolean}
2682
+ * @returns {Boolean|Object}
2487
2683
  */
2488
2684
  validate: function(validator, $field, options) {
2489
2685
  var value = $field.val();
@@ -2507,7 +2703,10 @@ if (typeof jQuery === 'undefined') {
2507
2703
  time = (sections.length > 1) ? sections[1] : null;
2508
2704
 
2509
2705
  if (formats.length !== sections.length) {
2510
- return false;
2706
+ return {
2707
+ valid: false,
2708
+ message: options.message || $.fn.bootstrapValidator.i18n.date['default']
2709
+ };
2511
2710
  }
2512
2711
 
2513
2712
  // Determine the separator
@@ -2516,14 +2715,20 @@ if (typeof jQuery === 'undefined') {
2516
2715
  separator = (date.indexOf('/') !== -1) ? '/' : ((date.indexOf('-') !== -1) ? '-' : null);
2517
2716
  }
2518
2717
  if (separator === null || date.indexOf(separator) === -1) {
2519
- return false;
2718
+ return {
2719
+ valid: false,
2720
+ message: options.message || $.fn.bootstrapValidator.i18n.date['default']
2721
+ };
2520
2722
  }
2521
2723
 
2522
2724
  // Determine the date
2523
2725
  date = date.split(separator);
2524
2726
  dateFormat = dateFormat.split(separator);
2525
2727
  if (date.length !== dateFormat.length) {
2526
- return false;
2728
+ return {
2729
+ valid: false,
2730
+ message: options.message || $.fn.bootstrapValidator.i18n.date['default']
2731
+ };
2527
2732
  }
2528
2733
 
2529
2734
  var year = date[$.inArray('YYYY', dateFormat)],
@@ -2531,7 +2736,10 @@ if (typeof jQuery === 'undefined') {
2531
2736
  day = date[$.inArray('DD', dateFormat)];
2532
2737
 
2533
2738
  if (!year || !month || !day || year.length !== 4) {
2534
- return false;
2739
+ return {
2740
+ valid: false,
2741
+ message: options.message || $.fn.bootstrapValidator.i18n.date['default']
2742
+ };
2535
2743
  }
2536
2744
 
2537
2745
  // Determine the time
@@ -2541,7 +2749,10 @@ if (typeof jQuery === 'undefined') {
2541
2749
  time = time.split(':');
2542
2750
 
2543
2751
  if (timeFormat.length !== time.length) {
2544
- return false;
2752
+ return {
2753
+ valid: false,
2754
+ message: options.message || $.fn.bootstrapValidator.i18n.date['default']
2755
+ };
2545
2756
  }
2546
2757
 
2547
2758
  hours = time.length > 0 ? time[0] : null;
@@ -2551,39 +2762,137 @@ if (typeof jQuery === 'undefined') {
2551
2762
  // Validate seconds
2552
2763
  if (seconds) {
2553
2764
  if (isNaN(seconds) || seconds.length > 2) {
2554
- return false;
2765
+ return {
2766
+ valid: false,
2767
+ message: options.message || $.fn.bootstrapValidator.i18n.date['default']
2768
+ };
2555
2769
  }
2556
2770
  seconds = parseInt(seconds, 10);
2557
2771
  if (seconds < 0 || seconds > 60) {
2558
- return false;
2772
+ return {
2773
+ valid: false,
2774
+ message: options.message || $.fn.bootstrapValidator.i18n.date['default']
2775
+ };
2559
2776
  }
2560
2777
  }
2561
2778
 
2562
2779
  // Validate hours
2563
2780
  if (hours) {
2564
2781
  if (isNaN(hours) || hours.length > 2) {
2565
- return false;
2782
+ return {
2783
+ valid: false,
2784
+ message: options.message || $.fn.bootstrapValidator.i18n.date['default']
2785
+ };
2566
2786
  }
2567
2787
  hours = parseInt(hours, 10);
2568
2788
  if (hours < 0 || hours >= 24 || (amOrPm && hours > 12)) {
2569
- return false;
2789
+ return {
2790
+ valid: false,
2791
+ message: options.message || $.fn.bootstrapValidator.i18n.date['default']
2792
+ };
2570
2793
  }
2571
2794
  }
2572
2795
 
2573
2796
  // Validate minutes
2574
2797
  if (minutes) {
2575
2798
  if (isNaN(minutes) || minutes.length > 2) {
2576
- return false;
2799
+ return {
2800
+ valid: false,
2801
+ message: options.message || $.fn.bootstrapValidator.i18n.date['default']
2802
+ };
2577
2803
  }
2578
2804
  minutes = parseInt(minutes, 10);
2579
2805
  if (minutes < 0 || minutes > 59) {
2580
- return false;
2806
+ return {
2807
+ valid: false,
2808
+ message: options.message || $.fn.bootstrapValidator.i18n.date['default']
2809
+ };
2581
2810
  }
2582
2811
  }
2583
2812
  }
2584
2813
 
2585
2814
  // Validate day, month, and year
2586
- return $.fn.bootstrapValidator.helpers.date(year, month, day);
2815
+ var valid = $.fn.bootstrapValidator.helpers.date(year, month, day),
2816
+ message = options.message || $.fn.bootstrapValidator.i18n.date['default'];
2817
+
2818
+ // declare the date, min and max objects
2819
+ var min = null,
2820
+ max = null,
2821
+ minOption = options.min,
2822
+ maxOption = options.max;
2823
+
2824
+ if (minOption) {
2825
+ if (isNaN(Date.parse(minOption))) {
2826
+ minOption = validator.getDynamicOption($field, minOption);
2827
+ }
2828
+ min = this._parseDate(minOption, dateFormat, separator);
2829
+ }
2830
+
2831
+ if (maxOption) {
2832
+ if (isNaN(Date.parse(maxOption))) {
2833
+ maxOption = validator.getDynamicOption($field, maxOption);
2834
+ }
2835
+ max = this._parseDate(maxOption, dateFormat, separator);
2836
+ }
2837
+
2838
+ date = new Date(year, month, day, hours, minutes, seconds);
2839
+
2840
+ switch (true) {
2841
+ case (minOption && !maxOption && valid):
2842
+ valid = date.getTime() >= min.getTime();
2843
+ message = options.message || $.fn.bootstrapValidator.helpers.format($.fn.bootstrapValidator.i18n.date.min, minOption);
2844
+ break;
2845
+
2846
+ case (maxOption && !minOption && valid):
2847
+ valid = date.getTime() <= max.getTime();
2848
+ message = options.message || $.fn.bootstrapValidator.helpers.format($.fn.bootstrapValidator.i18n.date.max, maxOption);
2849
+ break;
2850
+
2851
+ case (maxOption && minOption && valid):
2852
+ valid = date.getTime() <= max.getTime() && date.getTime() >= min.getTime();
2853
+ message = options.message || $.fn.bootstrapValidator.helpers.format($.fn.bootstrapValidator.i18n.date.range, [minOption, maxOption]);
2854
+ break;
2855
+
2856
+ default:
2857
+ break;
2858
+ }
2859
+
2860
+ return {
2861
+ valid: valid,
2862
+ message: message
2863
+ };
2864
+ },
2865
+
2866
+ /**
2867
+ * Return a date object after parsing the date string
2868
+ *
2869
+ * @param {String} date The date string to parse
2870
+ * @param {String} format The date format
2871
+ * The format can be:
2872
+ * - date: Consist of DD, MM, YYYY parts which are separated by the separator option
2873
+ * - date and time:
2874
+ * The time can consist of h, m, s parts which are separated by :
2875
+ * @param {String} separator The separator used to separate the date, month, and year
2876
+ * @returns {Date}
2877
+ */
2878
+ _parseDate: function(date, format, separator) {
2879
+ var minutes = 0, hours = 0, seconds = 0,
2880
+ sections = date.split(' '),
2881
+ dateSection = sections[0],
2882
+ timeSection = (sections.length > 1) ? sections[1] : null;
2883
+
2884
+ dateSection = dateSection.split(separator);
2885
+ var year = dateSection[$.inArray('YYYY', format)],
2886
+ month = dateSection[$.inArray('MM', format)],
2887
+ day = dateSection[$.inArray('DD', format)];
2888
+ if (timeSection) {
2889
+ timeSection = timeSection.split(':');
2890
+ hours = timeSection.length > 0 ? timeSection[0] : null;
2891
+ minutes = timeSection.length > 1 ? timeSection[1] : null;
2892
+ seconds = timeSection.length > 2 ? timeSection[2] : null;
2893
+ }
2894
+
2895
+ return new Date(year, month, day, hours, minutes, seconds);
2587
2896
  }
2588
2897
  };
2589
2898
  }(window.jQuery));
@@ -2794,8 +3103,12 @@ if (typeof jQuery === 'undefined') {
2794
3103
  $.fn.bootstrapValidator.validators.file = {
2795
3104
  html5Attributes: {
2796
3105
  extension: 'extension',
3106
+ maxfiles: 'maxFiles',
3107
+ minfiles: 'minFiles',
2797
3108
  maxsize: 'maxSize',
2798
3109
  minsize: 'minSize',
3110
+ maxtotalsize: 'maxTotalSize',
3111
+ mintotalsize: 'minTotalSize',
2799
3112
  message: 'message',
2800
3113
  type: 'type'
2801
3114
  },
@@ -2807,8 +3120,12 @@ if (typeof jQuery === 'undefined') {
2807
3120
  * @param {jQuery} $field Field element
2808
3121
  * @param {Object} options Can consist of the following keys:
2809
3122
  * - extension: The allowed extensions, separated by a comma
3123
+ * - maxFiles: The maximum number of files
3124
+ * - minFiles: The minimum number of files
2810
3125
  * - maxSize: The maximum size in bytes
2811
- * - minSize: the minimum size in bytes
3126
+ * - minSize: The minimum size in bytes
3127
+ * - maxTotalSize: The maximum size in bytes for all files
3128
+ * - minTotalSize: The minimum size in bytes for all files
2812
3129
  * - message: The invalid message
2813
3130
  * - type: The allowed MIME type, separated by a comma
2814
3131
  * @returns {Boolean}
@@ -2826,29 +3143,33 @@ if (typeof jQuery === 'undefined') {
2826
3143
 
2827
3144
  if (html5) {
2828
3145
  // Get FileList instance
2829
- var files = $field.get(0).files,
2830
- total = files.length;
3146
+ var files = $field.get(0).files,
3147
+ total = files.length,
3148
+ totalSize = 0;
3149
+
3150
+ if ((options.maxFiles && total > parseInt(options.maxFiles, 10)) // Check the maxFiles
3151
+ || (options.minFiles && total < parseInt(options.minFiles, 10))) // Check the minFiles
3152
+ {
3153
+ return false;
3154
+ }
3155
+
2831
3156
  for (var i = 0; i < total; i++) {
2832
- // Check the minSize
2833
- if (options.minSize && files[i].size < parseInt(options.minSize, 10)) {
2834
- return false;
2835
- }
2836
-
2837
- // Check the maxSize
2838
- if (options.maxSize && files[i].size > parseInt(options.maxSize, 10)) {
2839
- return false;
2840
- }
3157
+ totalSize += files[i].size;
3158
+ ext = files[i].name.substr(files[i].name.lastIndexOf('.') + 1);
2841
3159
 
2842
- // Check file extension
2843
- ext = files[i].name.substr(files[i].name.lastIndexOf('.') + 1);
2844
- if (extensions && $.inArray(ext.toLowerCase(), extensions) === -1) {
3160
+ if ((options.minSize && files[i].size < parseInt(options.minSize, 10)) // Check the minSize
3161
+ || (options.maxSize && files[i].size > parseInt(options.maxSize, 10)) // Check the maxSize
3162
+ || (extensions && $.inArray(ext.toLowerCase(), extensions) === -1) // Check file extension
3163
+ || (files[i].type && types && $.inArray(files[i].type.toLowerCase(), types) === -1)) // Check file type
3164
+ {
2845
3165
  return false;
2846
3166
  }
3167
+ }
2847
3168
 
2848
- // Check file type
2849
- if (files[i].type && types && $.inArray(files[i].type.toLowerCase(), types) === -1) {
2850
- return false;
2851
- }
3169
+ if ((options.maxTotalSize && totalSize > parseInt(options.maxTotalSize, 10)) // Check the maxTotalSize
3170
+ || (options.minTotalSize && totalSize < parseInt(options.minTotalSize, 10))) // Check the minTotalSize
3171
+ {
3172
+ return false;
2852
3173
  }
2853
3174
  } else {
2854
3175
  // Check file extension
@@ -2908,21 +3229,29 @@ if (typeof jQuery === 'undefined') {
2908
3229
  if (value === '') {
2909
3230
  return true;
2910
3231
  }
3232
+
3233
+ value = this._format(value);
2911
3234
  if (!$.isNumeric(value)) {
2912
3235
  return false;
2913
3236
  }
2914
3237
 
2915
- var compareTo = $.isNumeric(options.value) ? options.value : validator.getDynamicOption($field, options.value);
3238
+ var compareTo = $.isNumeric(options.value) ? options.value : validator.getDynamicOption($field, options.value),
3239
+ compareToValue = this._format(compareTo);
3240
+
2916
3241
  value = parseFloat(value);
2917
3242
  return (options.inclusive === true || options.inclusive === undefined)
2918
3243
  ? {
2919
- valid: value >= compareTo,
3244
+ valid: value >= compareToValue,
2920
3245
  message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.greaterThan['default'], compareTo)
2921
3246
  }
2922
3247
  : {
2923
- valid: value > compareTo,
3248
+ valid: value > compareToValue,
2924
3249
  message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.greaterThan.notInclusive, compareTo)
2925
3250
  };
3251
+ },
3252
+
3253
+ _format: function(value) {
3254
+ return (value + '').replace(',', '.');
2926
3255
  }
2927
3256
  };
2928
3257
  }(window.jQuery));
@@ -3012,7 +3341,12 @@ if (typeof jQuery === 'undefined') {
3012
3341
  if (value === '') {
3013
3342
  return true;
3014
3343
  }
3015
- return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value);
3344
+
3345
+ return ('color' === $field.attr('type'))
3346
+ // Only accept 6 hex character values due to the HTML 5 spec
3347
+ // See http://www.w3.org/TR/html-markup/input.color.html#input.color.attrs.value
3348
+ ? /^#[0-9A-F]{6}$/i.test(value)
3349
+ : /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value);
3016
3350
  }
3017
3351
  };
3018
3352
  }(window.jQuery));
@@ -3045,7 +3379,7 @@ if (typeof jQuery === 'undefined') {
3045
3379
  CZ: 'Czech Republic',
3046
3380
  DE: 'Germany',
3047
3381
  DK: 'Denmark',
3048
- DO: 'Dominica',
3382
+ DO: 'Dominican Republic',
3049
3383
  DZ: 'Algeria',
3050
3384
  EE: 'Estonia',
3051
3385
  ES: 'Spain',
@@ -5157,21 +5491,29 @@ if (typeof jQuery === 'undefined') {
5157
5491
  if (value === '') {
5158
5492
  return true;
5159
5493
  }
5494
+
5495
+ value = this._format(value);
5160
5496
  if (!$.isNumeric(value)) {
5161
5497
  return false;
5162
5498
  }
5163
5499
 
5164
- var compareTo = $.isNumeric(options.value) ? options.value : validator.getDynamicOption($field, options.value);
5500
+ var compareTo = $.isNumeric(options.value) ? options.value : validator.getDynamicOption($field, options.value),
5501
+ compareToValue = this._format(compareTo);
5502
+
5165
5503
  value = parseFloat(value);
5166
5504
  return (options.inclusive === true || options.inclusive === undefined)
5167
5505
  ? {
5168
- valid: value <= compareTo,
5506
+ valid: value <= compareToValue,
5169
5507
  message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.lessThan['default'], compareTo)
5170
5508
  }
5171
5509
  : {
5172
- valid: value < compareTo,
5510
+ valid: value < compareToValue,
5173
5511
  message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.lessThan.notInclusive, compareTo)
5174
5512
  };
5513
+ },
5514
+
5515
+ _format: function(value) {
5516
+ return (value + '').replace(',', '.');
5175
5517
  }
5176
5518
  };
5177
5519
  }(window.jQuery));
@@ -5371,6 +5713,7 @@ if (typeof jQuery === 'undefined') {
5371
5713
  BR: 'Brazil',
5372
5714
  CN: 'China',
5373
5715
  CZ: 'Czech Republic',
5716
+ DE: 'Germany',
5374
5717
  DK: 'Denmark',
5375
5718
  ES: 'Spain',
5376
5719
  FR: 'France',
@@ -5393,7 +5736,7 @@ if (typeof jQuery === 'undefined') {
5393
5736
  },
5394
5737
 
5395
5738
  // The supported countries
5396
- COUNTRY_CODES: ['BR', 'CN', 'CZ', 'DK', 'ES', 'FR', 'GB', 'MA', 'PK', 'RO', 'RU', 'SK', 'TH', 'US', 'VE'],
5739
+ COUNTRY_CODES: ['BR', 'CN', 'CZ', 'DE', 'DK', 'ES', 'FR', 'GB', 'MA', 'PK', 'RO', 'RU', 'SK', 'TH', 'US', 'VE'],
5397
5740
 
5398
5741
  /**
5399
5742
  * Return true if the input value contains a valid phone number for the country
@@ -5449,6 +5792,12 @@ if (typeof jQuery === 'undefined') {
5449
5792
  isValid = /^(((00)([- ]?)|\+)(420)([- ]?))?((\d{3})([- ]?)){2}(\d{3})$/.test(value);
5450
5793
  break;
5451
5794
 
5795
+ case 'DE':
5796
+ // Test: http://regexr.com/39pkg
5797
+ value = $.trim(value);
5798
+ isValid = (/^(((((((00|\+)49[ \-/]?)|0)[1-9][0-9]{1,4})[ \-/]?)|((((00|\+)49\()|\(0)[1-9][0-9]{1,4}\)[ \-/]?))[0-9]{1,7}([ \-/]?[0-9]{1,5})?)$/).test(value);
5799
+ break;
5800
+
5452
5801
  case 'DK':
5453
5802
  // Mathing DK phone numbers with country code in 1 of 3 formats and an
5454
5803
  // 8 digit phone number not starting with a 0 or 1. Can have 1 space
@@ -5589,6 +5938,7 @@ if (typeof jQuery === 'undefined') {
5589
5938
  name: 'name',
5590
5939
  type: 'type',
5591
5940
  url: 'url',
5941
+ data: 'data',
5592
5942
  delay: 'delay'
5593
5943
  },
5594
5944
 
@@ -5639,6 +5989,11 @@ if (typeof jQuery === 'undefined') {
5639
5989
  data = data.call(this, validator);
5640
5990
  }
5641
5991
 
5992
+ // Parse string data from HTML5 attribute
5993
+ if ('string' === typeof data) {
5994
+ data = JSON.parse(data);
5995
+ }
5996
+
5642
5997
  // Support dynamic url
5643
5998
  if ('function' === typeof url) {
5644
5999
  url = url.call(this, validator);
@@ -5936,7 +6291,9 @@ if (typeof jQuery === 'undefined') {
5936
6291
  html5Attributes: {
5937
6292
  message: 'message',
5938
6293
  min: 'min',
5939
- max: 'max'
6294
+ max: 'max',
6295
+ trim: 'trim',
6296
+ utf8bytes: 'utf8Bytes'
5940
6297
  },
5941
6298
 
5942
6299
  enableByHtml5: function($field) {
@@ -5969,19 +6326,41 @@ if (typeof jQuery === 'undefined') {
5969
6326
  * - A callback function that returns the number
5970
6327
  *
5971
6328
  * - message: The invalid message
6329
+ * - trim: Indicate the length will be calculated after trimming the value or not. It is false, by default
6330
+ * - utf8bytes: Evaluate string length in UTF-8 bytes, default to false
5972
6331
  * @returns {Object}
5973
6332
  */
5974
6333
  validate: function(validator, $field, options) {
5975
6334
  var value = $field.val();
6335
+ if (options.trim === true || options.trim === 'true') {
6336
+ value = $.trim(value);
6337
+ }
6338
+
5976
6339
  if (value === '') {
5977
6340
  return true;
5978
6341
  }
5979
6342
 
5980
- var min = $.isNumeric(options.min) ? options.min : validator.getDynamicOption($field, options.min),
5981
- max = $.isNumeric(options.max) ? options.max : validator.getDynamicOption($field, options.max),
5982
- length = value.length,
5983
- isValid = true,
5984
- message = options.message || $.fn.bootstrapValidator.i18n.stringLength['default'];
6343
+ var min = $.isNumeric(options.min) ? options.min : validator.getDynamicOption($field, options.min),
6344
+ max = $.isNumeric(options.max) ? options.max : validator.getDynamicOption($field, options.max),
6345
+ // Credit to http://stackoverflow.com/a/23329386 (@lovasoa) for UTF-8 byte length code
6346
+ utf8Length = function(str) {
6347
+ var s = str.length;
6348
+ for (var i = str.length - 1; i >= 0; i--) {
6349
+ var code = str.charCodeAt(i);
6350
+ if (code > 0x7f && code <= 0x7ff) {
6351
+ s++;
6352
+ } else if (code > 0x7ff && code <= 0xffff) {
6353
+ s += 2;
6354
+ }
6355
+ if (code >= 0xDC00 && code <= 0xDFFF) {
6356
+ i--;
6357
+ }
6358
+ }
6359
+ return s;
6360
+ },
6361
+ length = options.utf8Bytes ? utf8Length(value) : value.length,
6362
+ isValid = true,
6363
+ message = options.message || $.fn.bootstrapValidator.i18n.stringLength['default'];
5985
6364
 
5986
6365
  if ((min && length < parseInt(min, 10)) || (max && length > parseInt(max, 10))) {
5987
6366
  isValid = false;
@@ -7635,14 +8014,20 @@ if (typeof jQuery === 'undefined') {
7635
8014
  countryNotSupported: 'The country code %s is not supported',
7636
8015
  country: 'Please enter a valid postal code in %s',
7637
8016
  countries: {
8017
+ AT: 'Austria',
7638
8018
  BR: 'Brazil',
7639
8019
  CA: 'Canada',
8020
+ CH: 'Switzerland',
7640
8021
  CZ: 'Czech Republic',
8022
+ DE: 'Germany',
7641
8023
  DK: 'Denmark',
8024
+ FR: 'France',
7642
8025
  GB: 'United Kingdom',
8026
+ IE: 'Ireland',
7643
8027
  IT: 'Italy',
7644
8028
  MA: 'Morocco',
7645
8029
  NL: 'Netherlands',
8030
+ PT: 'Portugal',
7646
8031
  RO: 'Romania',
7647
8032
  RU: 'Russia',
7648
8033
  SE: 'Sweden',
@@ -7658,7 +8043,7 @@ if (typeof jQuery === 'undefined') {
7658
8043
  country: 'country'
7659
8044
  },
7660
8045
 
7661
- COUNTRY_CODES: ['BR', 'CA', 'CZ', 'DK', 'GB', 'IT', 'MA', 'NL', 'RO', 'RU', 'SE', 'SG', 'SK', 'US'],
8046
+ COUNTRY_CODES: [ 'AT', 'BR', 'CA', 'CH', 'CZ', 'DE', 'DK', 'FR', 'GB', 'IE', 'IT', 'MA', 'NL', 'PT', 'RO', 'RU', 'SE', 'SG', 'SK', 'US'],
7662
8047
 
7663
8048
  /**
7664
8049
  * Return true if and only if the input value is a valid country zip code
@@ -7702,6 +8087,11 @@ if (typeof jQuery === 'undefined') {
7702
8087
  var isValid = false;
7703
8088
  country = country.toUpperCase();
7704
8089
  switch (country) {
8090
+ // http://en.wikipedia.org/wiki/List_of_postal_codes_in_Austria
8091
+ case 'AT':
8092
+ isValid = /^([1-9]{1})(\d{3})$/.test(value);
8093
+ break;
8094
+
7705
8095
  case 'BR':
7706
8096
  isValid = /^(\d{2})([\.]?)(\d{3})([\-]?)(\d{3})$/.test(value);
7707
8097
  break;
@@ -7710,19 +8100,39 @@ if (typeof jQuery === 'undefined') {
7710
8100
  isValid = /^(?:A|B|C|E|G|H|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}(?:A|B|C|E|G|H|J|K|L|M|N|P|R|S|T|V|W|X|Y|Z){1}\s?[0-9]{1}(?:A|B|C|E|G|H|J|K|L|M|N|P|R|S|T|V|W|X|Y|Z){1}[0-9]{1}$/i.test(value);
7711
8101
  break;
7712
8102
 
8103
+ case 'CH':
8104
+ isValid = /^([1-9]{1})(\d{3})$/.test(value);
8105
+ break;
8106
+
7713
8107
  case 'CZ':
7714
8108
  // Test: http://regexr.com/39hhr
7715
8109
  isValid = /^(\d{3})([ ]?)(\d{2})$/.test(value);
7716
8110
  break;
7717
8111
 
8112
+ // http://stackoverflow.com/questions/7926687/regular-expression-german-zip-codes
8113
+ case 'DE':
8114
+ isValid = /^(?!01000|99999)(0[1-9]\d{3}|[1-9]\d{4})$/.test(value);
8115
+ break;
8116
+
7718
8117
  case 'DK':
7719
8118
  isValid = /^(DK(-|\s)?)?\d{4}$/i.test(value);
7720
8119
  break;
7721
8120
 
8121
+ // http://en.wikipedia.org/wiki/Postal_codes_in_France
8122
+ case 'FR':
8123
+ isValid = /^[0-9]{5}$/i.test(value);
8124
+ break;
8125
+
7722
8126
  case 'GB':
7723
8127
  isValid = this._gb(value);
7724
8128
  break;
7725
8129
 
8130
+ // http://www.eircode.ie/docs/default-source/Common/prepare-your-business-for-eircode---published-v2.pdf?sfvrsn=2
8131
+ // Test: http://refiddle.com/1kpl
8132
+ case 'IE':
8133
+ isValid = /^(D6W|[ACDEFHKNPRTVWXY]\d{2})\s[0-9ACDEFHKNPRTVWXY]{4}$/.test(value);
8134
+ break;
8135
+
7726
8136
  // http://en.wikipedia.org/wiki/List_of_postal_codes_in_Italy
7727
8137
  case 'IT':
7728
8138
  isValid = /^(I-|IT-)?\d{5}$/i.test(value);
@@ -7737,7 +8147,12 @@ if (typeof jQuery === 'undefined') {
7737
8147
  case 'NL':
7738
8148
  isValid = /^[1-9][0-9]{3} ?(?!sa|sd|ss)[a-z]{2}$/i.test(value);
7739
8149
  break;
7740
-
8150
+
8151
+ // Test: http://refiddle.com/1l2t
8152
+ case 'PT':
8153
+ isValid = /^[1-9]\d{3}-\d{3}$/.test(value);
8154
+ break;
8155
+
7741
8156
  case 'RO':
7742
8157
  isValid = /^(0[1-8]{1}|[1-9]{1}[0-5]{1})?[0-9]{4}$/i.test(value);
7743
8158
  break;
@@ -7752,7 +8167,7 @@ if (typeof jQuery === 'undefined') {
7752
8167
 
7753
8168
  case 'SG':
7754
8169
  isValid = /^([0][1-9]|[1-6][0-9]|[7]([0-3]|[5-9])|[8][0-2])(\d{4})$/i.test(value);
7755
- break;
8170
+ break;
7756
8171
 
7757
8172
  case 'SK':
7758
8173
  // Test: http://regexr.com/39hhr