bootstrap-validator-rails 0.5.2 → 0.5.3

Sign up to get free protection for your applications and to get access to all the features.
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