bootstrap-validator-rails 0.5.0.2 → 0.5.1

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.
checksums.yaml CHANGED
@@ -1,15 +1,7 @@
1
1
  ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- ZmE5ODE3NGI5MzI5YWU4M2EwMDQ4MDNhOTQyYTE1YzQ2ZWM0YTcxNg==
5
- data.tar.gz: !binary |-
6
- ZGI0OGQzNTgwMDRmOGVjZjAxNjRhYTRhNzg1YTg0YzI2NWM2ZDkwYQ==
2
+ SHA1:
3
+ metadata.gz: 993cafc397ed0f6251ab9e179ae990fdf959b23d
4
+ data.tar.gz: fba1ab25acc15ed0de59376b08cb6e951a9368e3
7
5
  SHA512:
8
- metadata.gz: !binary |-
9
- YWFlNDMyNjJjNmFmMTRhNWRkODI3MDY0OGU1YzZlZTZiYmExNmVhNjllMDRi
10
- YzdiOWFlMjYzYjg1YWQwZjQ3ZmVmMzQ2YTQ0YTExODJlMWRjNTFmZmM4NDlm
11
- NDU4NDVjMTQxOWJkNzI0NzExMTk1YmMxYmVmMzk1NTliMzcwY2I=
12
- data.tar.gz: !binary |-
13
- ODc0NGQ0ZTA1ZWJmZWVkMjA0MDhlYjcxMzQ5Njg2MmY0Yjk5YTAyMzA2MGNm
14
- YmY3MWY3MGE2ZDhhMDU0MzViZWEyMWY1M2Y4ZGM2OTVmNTMxMjBiNjVhY2U0
15
- YzM1NTk2NmE5NjExY2RmNzFhZjU3ZDhjYjhlODliOTExZGU4NzI=
6
+ metadata.gz: a4443faf6e9e915226f57ba38f9dba8daa324a9db901482d668e01f6651e9ca24d639342c1118d5b2be0d6eef84d2372f7f0e9ee0c0ff1d1d7de48de41254d86
7
+ data.tar.gz: 0e51a2bc522d55015c07c83dfaba355b933776b79d12716b94c7601e0d025d5a8c9b9185db9406c32e3f854716dd53e10f8443f38764d1825c5bc9f84591c3a3
data/README.md CHANGED
@@ -1,5 +1,5 @@
1
- bootstrap-validator-rails
2
- =========================
1
+ bootstrap-validator-rails (0.5.1)
2
+ =================================
3
3
 
4
4
  Gem version of bootstrapvalidator JavaScript library = a jQuery based field validator for Twitter Bootstrap 3.
5
5
 
@@ -1,6 +1,6 @@
1
1
  module BootstrapValidatorRails
2
2
  module Rails
3
- VERSION = "0.5.0.2"
4
- BOOTSTRAP_VALIDATOR_VERSION = "0.5.0"
3
+ VERSION = "0.5.1"
4
+ BOOTSTRAP_VALIDATOR_VERSION = "0.5.1"
5
5
  end
6
6
  end
@@ -2,7 +2,7 @@
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.0, built on 2014-07-14 4:31:02 PM
5
+ * @version v0.5.1, built on 2014-08-22 4:55:09 PM
6
6
  * @author https://twitter.com/nghuuphuoc
7
7
  * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc
8
8
  * @license MIT
@@ -14,6 +14,7 @@
14
14
 
15
15
  this.$invalidFields = $([]); // Array of invalid fields
16
16
  this.$submitButton = null; // The submit button which is clicked to submit form
17
+ this.$hiddenButton = null;
17
18
 
18
19
  // Validating status
19
20
  this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED';
@@ -68,6 +69,19 @@
68
69
  valid: this.$form.attr('data-bv-feedbackicons-valid'),
69
70
  invalid: this.$form.attr('data-bv-feedbackicons-invalid'),
70
71
  validating: this.$form.attr('data-bv-feedbackicons-validating')
72
+ },
73
+ events: {
74
+ formInit: this.$form.attr('data-bv-events-form-init'),
75
+ formError: this.$form.attr('data-bv-events-form-error'),
76
+ formSuccess: this.$form.attr('data-bv-events-form-success'),
77
+ fieldAdded: this.$form.attr('data-bv-events-field-added'),
78
+ fieldRemoved: this.$form.attr('data-bv-events-field-removed'),
79
+ fieldInit: this.$form.attr('data-bv-events-field-init'),
80
+ fieldError: this.$form.attr('data-bv-events-field-error'),
81
+ fieldSuccess: this.$form.attr('data-bv-events-field-success'),
82
+ fieldStatus: this.$form.attr('data-bv-events-field-status'),
83
+ validatorError: this.$form.attr('data-bv-events-validator-error'),
84
+ validatorSuccess: this.$form.attr('data-bv-events-validator-success')
71
85
  }
72
86
  };
73
87
 
@@ -98,23 +112,43 @@
98
112
  });
99
113
 
100
114
  this.options = $.extend(true, this.options, options);
115
+
116
+ // When pressing Enter on any field in the form, the first submit button will do its job.
117
+ // The form then will be submitted.
118
+ // I create a first hidden submit button
119
+ this.$hiddenButton = $('<button/>')
120
+ .attr('type', 'submit')
121
+ .prependTo(this.$form)
122
+ .addClass('bv-hidden-submit')
123
+ .css({ display: 'none', width: 0, height: 0 });
124
+
125
+ this.$form
126
+ .on('click.bv', '[type="submit"]', function(e) {
127
+ // Don't perform validation when clicking on the submit button/input
128
+ // which aren't defined by the 'submitButtons' option
129
+ var $button = $(e.target).eq(0);
130
+ if (that.options.submitButtons && !$button.is(that.options.submitButtons) && !$button.is(that.$hiddenButton)) {
131
+ that.$form.off('submit.bv').submit();
132
+ }
133
+ });
134
+
101
135
  for (var field in this.options.fields) {
102
136
  this._initField(field);
103
137
  }
104
138
 
105
- this.$form.trigger($.Event('init.form.bv'), {
139
+ this.$form.trigger($.Event(this.options.events.formInit), {
106
140
  bv: this,
107
141
  options: this.options
108
142
  });
109
143
 
110
144
  // Prepare the events
111
145
  if (this.options.onSuccess) {
112
- this.$form.on('success.form.bv', function(e) {
146
+ this.$form.on(this.options.events.formSuccess, function(e) {
113
147
  $.fn.bootstrapValidator.helpers.call(that.options.onSuccess, [e]);
114
148
  });
115
149
  }
116
150
  if (this.options.onError) {
117
- this.$form.on('error.form.bv', function(e) {
151
+ this.$form.on(this.options.events.formError, function(e) {
118
152
  $.fn.bootstrapValidator.helpers.call(that.options.onError, [e]);
119
153
  });
120
154
  }
@@ -277,12 +311,12 @@
277
311
 
278
312
  // Prepare the validator events
279
313
  if (this.options.fields[field].validators[validatorName].onSuccess) {
280
- $field.on('success.validator.bv', function(e, data) {
314
+ $field.on(this.options.events.validatorSuccess, function(e, data) {
281
315
  $.fn.bootstrapValidator.helpers.call(that.options.fields[field].validators[validatorName].onSuccess, [e, data]);
282
316
  });
283
317
  }
284
318
  if (this.options.fields[field].validators[validatorName].onError) {
285
- $field.on('error.validator.bv', function(e, data) {
319
+ $field.on(this.options.events.validatorError, function(e, data) {
286
320
  $.fn.bootstrapValidator.helpers.call(that.options.fields[field].validators[validatorName].onError, [e, data]);
287
321
  });
288
322
  }
@@ -300,9 +334,18 @@
300
334
  .css('display', 'none')
301
335
  .addClass('form-control-feedback')
302
336
  .attr('data-bv-icon-for', field)
303
- // Place it after the label containing the checkbox/radio
304
- // so when clicking the icon, it doesn't effect to the checkbox/radio element
305
- .insertAfter(('checkbox' === type || 'radio' === type) ? $field.parent() : $field);
337
+ .insertAfter($field);
338
+
339
+ // Place it after the container of checkbox/radio
340
+ // so when clicking the icon, it doesn't effect to the checkbox/radio element
341
+ if ('checkbox' === type || 'radio' === type) {
342
+ var $fieldParent = $field.parent();
343
+ if ($fieldParent.hasClass(type)) {
344
+ $icon.insertAfter($fieldParent);
345
+ } else if ($fieldParent.parent().hasClass(type)) {
346
+ $icon.insertAfter($fieldParent.parent());
347
+ }
348
+ }
306
349
 
307
350
  // The feedback icon does not render correctly if there is no label
308
351
  // https://github.com/twbs/bootstrap/issues/12873
@@ -321,17 +364,17 @@
321
364
 
322
365
  // Prepare the events
323
366
  if (this.options.fields[field].onSuccess) {
324
- fields.on('success.field.bv', function(e, data) {
367
+ fields.on(this.options.events.fieldSuccess, function(e, data) {
325
368
  $.fn.bootstrapValidator.helpers.call(that.options.fields[field].onSuccess, [e, data]);
326
369
  });
327
370
  }
328
371
  if (this.options.fields[field].onError) {
329
- fields.on('error.field.bv', function(e, data) {
372
+ fields.on(this.options.events.fieldError, function(e, data) {
330
373
  $.fn.bootstrapValidator.helpers.call(that.options.fields[field].onError, [e, data]);
331
374
  });
332
375
  }
333
376
  if (this.options.fields[field].onStatus) {
334
- fields.on('status.field.bv', function(e, data) {
377
+ fields.on(this.options.events.fieldStatus, function(e, data) {
335
378
  $.fn.bootstrapValidator.helpers.call(that.options.fields[field].onStatus, [e, data]);
336
379
  });
337
380
  }
@@ -357,7 +400,7 @@
357
400
  break;
358
401
  }
359
402
 
360
- fields.trigger($.Event('init.field.bv'), {
403
+ fields.trigger($.Event(this.options.events.fieldInit), {
361
404
  bv: this,
362
405
  field: field,
363
406
  element: fields
@@ -425,7 +468,7 @@
425
468
  */
426
469
  _submit: function() {
427
470
  var isValid = this.isValid(),
428
- eventType = isValid ? 'success.form.bv' : 'error.form.bv',
471
+ eventType = isValid ? this.options.events.formSuccess : this.options.events.formError,
429
472
  e = $.Event(eventType);
430
473
 
431
474
  this.$form.trigger(e);
@@ -588,10 +631,10 @@
588
631
  if (validatorName) {
589
632
  switch ($field.data('bv.result.' + validatorName)) {
590
633
  case this.STATUS_INVALID:
591
- $field.trigger($.Event('error.validator.bv'), data);
634
+ $field.trigger($.Event(this.options.events.validatorError), data);
592
635
  break;
593
636
  case this.STATUS_VALID:
594
- $field.trigger($.Event('success.validator.bv'), data);
637
+ $field.trigger($.Event(this.options.events.validatorSuccess), data);
595
638
  break;
596
639
  default:
597
640
  break;
@@ -619,14 +662,14 @@
619
662
  // Remove from the list of invalid fields
620
663
  this.$invalidFields = this.$invalidFields.not($field);
621
664
 
622
- $field.trigger($.Event('success.field.bv'), data);
665
+ $field.trigger($.Event(this.options.events.fieldSuccess), data);
623
666
  }
624
667
  // If all validators are completed and there is at least one validator which doesn't pass
625
668
  else if (counter[this.STATUS_NOT_VALIDATED] === 0 && counter[this.STATUS_VALIDATING] === 0 && counter[this.STATUS_INVALID] > 0) {
626
669
  // Add to the list of invalid fields
627
670
  this.$invalidFields = this.$invalidFields.add($field);
628
671
 
629
- $field.trigger($.Event('error.field.bv'), data);
672
+ $field.trigger($.Event(this.options.events.fieldError), data);
630
673
  }
631
674
  },
632
675
 
@@ -956,7 +999,7 @@
956
999
  }
957
1000
 
958
1001
  // Trigger an event
959
- $field.trigger($.Event('status.field.bv'), {
1002
+ $field.trigger($.Event(this.options.events.fieldStatus), {
960
1003
  bv: this,
961
1004
  field: field,
962
1005
  element: $field,
@@ -1258,7 +1301,7 @@
1258
1301
 
1259
1302
  this.disableSubmitButtons(false);
1260
1303
  // Trigger an event
1261
- this.$form.trigger($.Event('added.field.bv'), {
1304
+ this.$form.trigger($.Event(this.options.events.fieldAdded), {
1262
1305
  field: field,
1263
1306
  element: fields,
1264
1307
  options: this.options.fields[field]
@@ -1314,7 +1357,7 @@
1314
1357
 
1315
1358
  this.disableSubmitButtons(false);
1316
1359
  // Trigger an event
1317
- this.$form.trigger($.Event('removed.field.bv'), {
1360
+ this.$form.trigger($.Event(this.options.events.fieldRemoved), {
1318
1361
  field: field,
1319
1362
  element: fields
1320
1363
  });
@@ -1464,7 +1507,7 @@
1464
1507
  }
1465
1508
  // ... return value of callback
1466
1509
  else {
1467
- return $.fn.bootstrapValidator.helpers.call(option, [value, this, $field]);
1510
+ return $.fn.bootstrapValidator.helpers.call(option, [value, this, $field]) || option;
1468
1511
  }
1469
1512
  }
1470
1513
 
@@ -1522,15 +1565,16 @@
1522
1565
  }
1523
1566
  }
1524
1567
 
1525
- // Enable submit buttons
1526
- this.disableSubmitButtons(false);
1568
+ this.disableSubmitButtons(false); // Enable submit buttons
1569
+ this.$hiddenButton.remove(); // Remove the hidden button
1527
1570
 
1528
1571
  this.$form
1529
1572
  .removeClass(this.options.elementClass)
1530
1573
  .off('.bv')
1531
1574
  .removeData('bootstrapValidator')
1532
1575
  // Remove generated hidden elements
1533
- .find('[data-bv-submit-hidden]').remove();
1576
+ .find('[data-bv-submit-hidden]').remove().end()
1577
+ .find('[type="submit"]').off('click.bv');
1534
1578
  }
1535
1579
  };
1536
1580
 
@@ -1638,7 +1682,23 @@
1638
1682
  live: 'enabled',
1639
1683
 
1640
1684
  // Map the field name with validator rules
1641
- fields: null
1685
+ fields: null,
1686
+
1687
+ // Use custom event name to avoid window.onerror being invoked by jQuery
1688
+ // See https://github.com/nghuuphuoc/bootstrapvalidator/issues/630
1689
+ events: {
1690
+ formInit: 'init.form.bv',
1691
+ formError: 'error.form.bv',
1692
+ formSuccess: 'success.form.bv',
1693
+ fieldAdded: 'added.field.bv',
1694
+ fieldRemoved: 'removed.field.bv',
1695
+ fieldInit: 'init.field.bv',
1696
+ fieldError: 'error.field.bv',
1697
+ fieldSuccess: 'success.field.bv',
1698
+ fieldStatus: 'status.field.bv',
1699
+ validatorError: 'error.validator.bv',
1700
+ validatorSuccess: 'success.validator.bv'
1701
+ }
1642
1702
  };
1643
1703
 
1644
1704
  // Available validators
@@ -1673,7 +1733,8 @@
1673
1733
  for (var i = 0; i < ns.length; i++) {
1674
1734
  context = context[ns[i]];
1675
1735
  }
1676
- return context[func].apply(this, args);
1736
+
1737
+ return (typeof context[func] === 'undefined') ? null : context[func].apply(this, args);
1677
1738
  }
1678
1739
  },
1679
1740
 
@@ -1711,6 +1772,9 @@
1711
1772
  if (isNaN(year) || isNaN(month) || isNaN(day)) {
1712
1773
  return false;
1713
1774
  }
1775
+ if (day.length > 2 || month.length > 2 || year.length > 4) {
1776
+ return false;
1777
+ }
1714
1778
 
1715
1779
  day = parseInt(day, 10);
1716
1780
  month = parseInt(month, 10);
@@ -1876,10 +1940,12 @@
1876
1940
  if (value === '') {
1877
1941
  return true;
1878
1942
  }
1943
+ if (!$.isNumeric(value)) {
1944
+ return false;
1945
+ }
1879
1946
 
1880
1947
  var min = $.isNumeric(options.min) ? options.min : validator.getDynamicOption($field, options.min),
1881
1948
  max = $.isNumeric(options.max) ? options.max : validator.getDynamicOption($field, options.max);
1882
-
1883
1949
  value = parseFloat(value);
1884
1950
  return (options.inclusive === true || options.inclusive === undefined)
1885
1951
  ? {
@@ -2313,6 +2379,11 @@
2313
2379
 
2314
2380
  options.format = options.format || 'MM/DD/YYYY';
2315
2381
 
2382
+ // #683: Force the format to YYYY-MM-DD as the default browser behaviour when using type="date" attribute
2383
+ if ($field.attr('type') === 'date') {
2384
+ options.format = 'YYYY-MM-DD';
2385
+ }
2386
+
2316
2387
  var formats = options.format.split(' '),
2317
2388
  dateFormat = formats[0],
2318
2389
  timeFormat = (formats.length > 1) ? formats[1] : null,
@@ -2345,7 +2416,7 @@
2345
2416
  month = date[$.inArray('MM', dateFormat)],
2346
2417
  day = date[$.inArray('DD', dateFormat)];
2347
2418
 
2348
- if (!year || !month || !day) {
2419
+ if (!year || !month || !day || year.length !== 4) {
2349
2420
  return false;
2350
2421
  }
2351
2422
 
@@ -2365,24 +2436,33 @@
2365
2436
 
2366
2437
  // Validate seconds
2367
2438
  if (seconds) {
2439
+ if (isNaN(seconds) || seconds.length > 2) {
2440
+ return false;
2441
+ }
2368
2442
  seconds = parseInt(seconds, 10);
2369
- if (isNaN(seconds) || seconds < 0 || seconds > 60) {
2443
+ if (seconds < 0 || seconds > 60) {
2370
2444
  return false;
2371
2445
  }
2372
2446
  }
2373
2447
 
2374
2448
  // Validate hours
2375
2449
  if (hours) {
2450
+ if (isNaN(hours) || hours.length > 2) {
2451
+ return false;
2452
+ }
2376
2453
  hours = parseInt(hours, 10);
2377
- if (isNaN(hours) || hours < 0 || hours >= 24 || (amOrPm && hours > 12)) {
2454
+ if (hours < 0 || hours >= 24 || (amOrPm && hours > 12)) {
2378
2455
  return false;
2379
2456
  }
2380
2457
  }
2381
2458
 
2382
2459
  // Validate minutes
2383
2460
  if (minutes) {
2461
+ if (isNaN(minutes) || minutes.length > 2) {
2462
+ return false;
2463
+ }
2384
2464
  minutes = parseInt(minutes, 10);
2385
- if (isNaN(minutes) || minutes < 0 || minutes > 59) {
2465
+ if (minutes < 0 || minutes > 59) {
2386
2466
  return false;
2387
2467
  }
2388
2468
  }
@@ -2421,7 +2501,7 @@
2421
2501
  }
2422
2502
 
2423
2503
  var compareWith = validator.getFieldElements(options.field);
2424
- if (compareWith === null) {
2504
+ if (compareWith === null || compareWith.length === 0) {
2425
2505
  return true;
2426
2506
  }
2427
2507
 
@@ -2582,7 +2662,7 @@
2582
2662
  }
2583
2663
 
2584
2664
  // Check file type
2585
- if (types && $.inArray(files[i].type.toLowerCase(), types) === -1) {
2665
+ if (files[i].type && types && $.inArray(files[i].type.toLowerCase(), types) === -1) {
2586
2666
  return false;
2587
2667
  }
2588
2668
  }
@@ -2612,8 +2692,9 @@
2612
2692
  },
2613
2693
 
2614
2694
  enableByHtml5: function($field) {
2615
- var min = $field.attr('min');
2616
- if (min) {
2695
+ var type = $field.attr('type'),
2696
+ min = $field.attr('min');
2697
+ if (min && type !== 'date') {
2617
2698
  return {
2618
2699
  value: min
2619
2700
  };
@@ -2643,9 +2724,11 @@
2643
2724
  if (value === '') {
2644
2725
  return true;
2645
2726
  }
2727
+ if (!$.isNumeric(value)) {
2728
+ return false;
2729
+ }
2646
2730
 
2647
2731
  var compareTo = $.isNumeric(options.value) ? options.value : validator.getDynamicOption($field, options.value);
2648
-
2649
2732
  value = parseFloat(value);
2650
2733
  return (options.inclusive === true || options.inclusive === undefined)
2651
2734
  ? {
@@ -2846,85 +2929,85 @@
2846
2929
  // http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf
2847
2930
  // http://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country
2848
2931
  REGEX: {
2849
- 'AD': 'AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}', // Andorra
2850
- 'AE': 'AE[0-9]{2}[0-9]{3}[0-9]{16}', // United Arab Emirates
2851
- 'AL': 'AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}', // Albania
2852
- 'AO': 'AO[0-9]{2}[0-9]{21}', // Angola
2853
- 'AT': 'AT[0-9]{2}[0-9]{5}[0-9]{11}', // Austria
2854
- 'AZ': 'AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}', // Azerbaijan
2855
- 'BA': 'BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}', // Bosnia and Herzegovina
2856
- 'BE': 'BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}', // Belgium
2857
- 'BF': 'BF[0-9]{2}[0-9]{23}', // Burkina Faso
2858
- 'BG': 'BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}', // Bulgaria
2859
- 'BH': 'BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}', // Bahrain
2860
- 'BI': 'BI[0-9]{2}[0-9]{12}', // Burundi
2861
- 'BJ': 'BJ[0-9]{2}[A-Z]{1}[0-9]{23}', // Benin
2862
- 'BR': 'BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]', // Brazil
2863
- 'CH': 'CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}', // Switzerland
2864
- 'CI': 'CI[0-9]{2}[A-Z]{1}[0-9]{23}', // Ivory Coast
2865
- 'CM': 'CM[0-9]{2}[0-9]{23}', // Cameroon
2866
- 'CR': 'CR[0-9]{2}[0-9]{3}[0-9]{14}', // Costa Rica
2867
- 'CV': 'CV[0-9]{2}[0-9]{21}', // Cape Verde
2868
- 'CY': 'CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}', // Cyprus
2869
- 'CZ': 'CZ[0-9]{2}[0-9]{20}', // Czech Republic
2870
- 'DE': 'DE[0-9]{2}[0-9]{8}[0-9]{10}', // Germany
2871
- 'DK': 'DK[0-9]{2}[0-9]{14}', // Denmark
2872
- 'DO': 'DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}', // Dominican Republic
2873
- 'DZ': 'DZ[0-9]{2}[0-9]{20}', // Algeria
2874
- 'EE': 'EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}', // Estonia
2875
- 'ES': 'ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}', // Spain
2876
- 'FI': 'FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}', // Finland
2877
- 'FO': 'FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', // Faroe Islands
2878
- 'FR': 'FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', // France
2879
- 'GB': 'GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', // United Kingdom
2880
- 'GE': 'GE[0-9]{2}[A-Z]{2}[0-9]{16}', // Georgia
2881
- 'GI': 'GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}', // Gibraltar
2882
- 'GL': 'GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', // Greenland
2883
- 'GR': 'GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}', // Greece
2884
- 'GT': 'GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}', // Guatemala
2885
- 'HR': 'HR[0-9]{2}[0-9]{7}[0-9]{10}', // Croatia
2886
- 'HU': 'HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}', // Hungary
2887
- 'IE': 'IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', // Ireland
2888
- 'IL': 'IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}', // Israel
2889
- 'IR': 'IR[0-9]{2}[0-9]{22}', // Iran
2890
- 'IS': 'IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}', // Iceland
2891
- 'IT': 'IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', // Italy
2892
- 'JO': 'JO[0-9]{2}[A-Z]{4}[0-9]{4}[0]{8}[A-Z0-9]{10}', // Jordan
2893
- 'KW': 'KW[0-9]{2}[A-Z]{4}[0-9]{22}', // Kuwait
2894
- 'KZ': 'KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}', // Kazakhstan
2895
- 'LB': 'LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}', // Lebanon
2896
- 'LI': 'LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}', // Liechtenstein
2897
- 'LT': 'LT[0-9]{2}[0-9]{5}[0-9]{11}', // Lithuania
2898
- 'LU': 'LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}', // Luxembourg
2899
- 'LV': 'LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}', // Latvia
2900
- 'MC': 'MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', // Monaco
2901
- 'MD': 'MD[0-9]{2}[A-Z0-9]{20}', // Moldova
2902
- 'ME': 'ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Montenegro
2903
- 'MG': 'MG[0-9]{2}[0-9]{23}', // Madagascar
2904
- 'MK': 'MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}', // Macedonia
2905
- 'ML': 'ML[0-9]{2}[A-Z]{1}[0-9]{23}', // Mali
2906
- 'MR': 'MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}', // Mauritania
2907
- 'MT': 'MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}', // Malta
2908
- 'MU': 'MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}',// Mauritius
2909
- 'MZ': 'MZ[0-9]{2}[0-9]{21}', // Mozambique
2910
- 'NL': 'NL[0-9]{2}[A-Z]{4}[0-9]{10}', // Netherlands
2911
- 'NO': 'NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}', // Norway
2912
- 'PK': 'PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', // Pakistan
2913
- 'PL': 'PL[0-9]{2}[0-9]{8}[0-9]{16}', // Poland
2914
- 'PS': 'PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', // Palestinian
2915
- 'PT': 'PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}', // Portugal
2916
- 'QA': 'QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', // Qatar
2917
- 'RO': 'RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', // Romania
2918
- 'RS': 'RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Serbia
2919
- 'SA': 'SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}', // Saudi Arabia
2920
- 'SE': 'SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}', // Sweden
2921
- 'SI': 'SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}', // Slovenia
2922
- 'SK': 'SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}', // Slovakia
2923
- 'SM': 'SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', // San Marino
2924
- 'SN': 'SN[0-9]{2}[A-Z]{1}[0-9]{23}', // Senegal
2925
- 'TN': 'TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Tunisia
2926
- 'TR': 'TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}', // Turkey
2927
- 'VG': 'VG[0-9]{2}[A-Z]{4}[0-9]{16}' // Virgin Islands, British
2932
+ AD: 'AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}', // Andorra
2933
+ AE: 'AE[0-9]{2}[0-9]{3}[0-9]{16}', // United Arab Emirates
2934
+ AL: 'AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}', // Albania
2935
+ AO: 'AO[0-9]{2}[0-9]{21}', // Angola
2936
+ AT: 'AT[0-9]{2}[0-9]{5}[0-9]{11}', // Austria
2937
+ AZ: 'AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}', // Azerbaijan
2938
+ BA: 'BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}', // Bosnia and Herzegovina
2939
+ BE: 'BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}', // Belgium
2940
+ BF: 'BF[0-9]{2}[0-9]{23}', // Burkina Faso
2941
+ BG: 'BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}', // Bulgaria
2942
+ BH: 'BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}', // Bahrain
2943
+ BI: 'BI[0-9]{2}[0-9]{12}', // Burundi
2944
+ BJ: 'BJ[0-9]{2}[A-Z]{1}[0-9]{23}', // Benin
2945
+ BR: 'BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]', // Brazil
2946
+ CH: 'CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}', // Switzerland
2947
+ CI: 'CI[0-9]{2}[A-Z]{1}[0-9]{23}', // Ivory Coast
2948
+ CM: 'CM[0-9]{2}[0-9]{23}', // Cameroon
2949
+ CR: 'CR[0-9]{2}[0-9]{3}[0-9]{14}', // Costa Rica
2950
+ CV: 'CV[0-9]{2}[0-9]{21}', // Cape Verde
2951
+ CY: 'CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}', // Cyprus
2952
+ CZ: 'CZ[0-9]{2}[0-9]{20}', // Czech Republic
2953
+ DE: 'DE[0-9]{2}[0-9]{8}[0-9]{10}', // Germany
2954
+ DK: 'DK[0-9]{2}[0-9]{14}', // Denmark
2955
+ DO: 'DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}', // Dominican Republic
2956
+ DZ: 'DZ[0-9]{2}[0-9]{20}', // Algeria
2957
+ EE: 'EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}', // Estonia
2958
+ ES: 'ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}', // Spain
2959
+ FI: 'FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}', // Finland
2960
+ FO: 'FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', // Faroe Islands
2961
+ FR: 'FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', // France
2962
+ GB: 'GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', // United Kingdom
2963
+ GE: 'GE[0-9]{2}[A-Z]{2}[0-9]{16}', // Georgia
2964
+ GI: 'GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}', // Gibraltar
2965
+ GL: 'GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', // Greenland
2966
+ GR: 'GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}', // Greece
2967
+ GT: 'GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}', // Guatemala
2968
+ HR: 'HR[0-9]{2}[0-9]{7}[0-9]{10}', // Croatia
2969
+ HU: 'HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}', // Hungary
2970
+ IE: 'IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', // Ireland
2971
+ IL: 'IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}', // Israel
2972
+ IR: 'IR[0-9]{2}[0-9]{22}', // Iran
2973
+ IS: 'IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}', // Iceland
2974
+ IT: 'IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', // Italy
2975
+ JO: 'JO[0-9]{2}[A-Z]{4}[0-9]{4}[0]{8}[A-Z0-9]{10}', // Jordan
2976
+ KW: 'KW[0-9]{2}[A-Z]{4}[0-9]{22}', // Kuwait
2977
+ KZ: 'KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}', // Kazakhstan
2978
+ LB: 'LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}', // Lebanon
2979
+ LI: 'LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}', // Liechtenstein
2980
+ LT: 'LT[0-9]{2}[0-9]{5}[0-9]{11}', // Lithuania
2981
+ LU: 'LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}', // Luxembourg
2982
+ LV: 'LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}', // Latvia
2983
+ MC: 'MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', // Monaco
2984
+ MD: 'MD[0-9]{2}[A-Z0-9]{20}', // Moldova
2985
+ ME: 'ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Montenegro
2986
+ MG: 'MG[0-9]{2}[0-9]{23}', // Madagascar
2987
+ MK: 'MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}', // Macedonia
2988
+ ML: 'ML[0-9]{2}[A-Z]{1}[0-9]{23}', // Mali
2989
+ MR: 'MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}', // Mauritania
2990
+ MT: 'MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}', // Malta
2991
+ MU: 'MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}', // Mauritius
2992
+ MZ: 'MZ[0-9]{2}[0-9]{21}', // Mozambique
2993
+ NL: 'NL[0-9]{2}[A-Z]{4}[0-9]{10}', // Netherlands
2994
+ NO: 'NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}', // Norway
2995
+ PK: 'PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', // Pakistan
2996
+ PL: 'PL[0-9]{2}[0-9]{8}[0-9]{16}', // Poland
2997
+ PS: 'PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', // Palestinian
2998
+ PT: 'PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}', // Portugal
2999
+ QA: 'QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', // Qatar
3000
+ RO: 'RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', // Romania
3001
+ RS: 'RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Serbia
3002
+ SA: 'SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}', // Saudi Arabia
3003
+ SE: 'SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}', // Sweden
3004
+ SI: 'SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}', // Slovenia
3005
+ SK: 'SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}', // Slovakia
3006
+ SM: 'SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', // San Marino
3007
+ SN: 'SN[0-9]{2}[A-Z]{1}[0-9]{23}', // Senegal
3008
+ TN: 'TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Tunisia
3009
+ TR: 'TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}', // Turkey
3010
+ VG: 'VG[0-9]{2}[A-Z]{4}[0-9]{16}' // Virgin Islands, British
2928
3011
  },
2929
3012
 
2930
3013
  /**
@@ -3837,7 +3920,7 @@
3837
3920
  }
3838
3921
 
3839
3922
  var compareWith = validator.getFieldElements(options.field);
3840
- if (compareWith === null) {
3923
+ if (compareWith === null || compareWith.length === 0) {
3841
3924
  return true;
3842
3925
  }
3843
3926
 
@@ -3894,6 +3977,51 @@
3894
3977
  }
3895
3978
  };
3896
3979
  }(window.jQuery));
3980
+ ;(function($) {
3981
+ $.fn.bootstrapValidator.i18n.imo = $.extend($.fn.bootstrapValidator.i18n.imo || {}, {
3982
+ 'default': 'Please enter a valid IMO number'
3983
+ });
3984
+
3985
+ $.fn.bootstrapValidator.validators.imo = {
3986
+ /**
3987
+ * Validate IMO (International Maritime Organization)
3988
+ * Examples:
3989
+ * - Valid: IMO 8814275, IMO 9176187
3990
+ * - Invalid: IMO 8814274
3991
+ *
3992
+ * @see http://en.wikipedia.org/wiki/IMO_Number
3993
+ * @param {BootstrapValidator} validator The validator plugin instance
3994
+ * @param {jQuery} $field Field element
3995
+ * @param {Object} options Can consist of the following keys:
3996
+ * - message: The invalid message
3997
+ * @returns {Boolean}
3998
+ */
3999
+ validate: function(validator, $field, options) {
4000
+ var value = $field.val();
4001
+ if (value === '') {
4002
+ return true;
4003
+ }
4004
+
4005
+ if (!/^IMO \d{7}$/i.test(value)) {
4006
+ return false;
4007
+ }
4008
+
4009
+ // Grab just the digits
4010
+ var sum = 0,
4011
+ digits = value.replace(/^.*(\d{7})$/, '$1');
4012
+
4013
+ // Go over each char, multiplying by the inverse of it's position
4014
+ // IMO 9176187
4015
+ // (9 * 7) + (1 * 6) + (7 * 5) + (6 * 4) + (1 * 3) + (8 * 2) = 147
4016
+ // Take the last digit of that, that's the check digit (7)
4017
+ for (var i = 6; i >= 1; i--) {
4018
+ sum += (digits.slice((6 - i), -i) * (i + 1));
4019
+ }
4020
+
4021
+ return sum % 10 === parseInt(digits.charAt(6), 10);
4022
+ }
4023
+ };
4024
+ }(window.jQuery));
3897
4025
  ;(function($) {
3898
4026
  $.fn.bootstrapValidator.i18n.integer = $.extend($.fn.bootstrapValidator.i18n.integer || {}, {
3899
4027
  'default': 'Please enter a valid number'
@@ -3914,6 +4042,10 @@
3914
4042
  * @returns {Boolean}
3915
4043
  */
3916
4044
  validate: function(validator, $field, options) {
4045
+ if (this.enableByHtml5($field) && $field.get(0).validity && $field.get(0).validity.badInput === true) {
4046
+ return false;
4047
+ }
4048
+
3917
4049
  var value = $field.val();
3918
4050
  if (value === '') {
3919
4051
  return true;
@@ -3954,23 +4086,37 @@
3954
4086
  }
3955
4087
  options = $.extend({}, { ipv4: true, ipv6: true }, options);
3956
4088
 
3957
- if (options.ipv4) {
3958
- return {
3959
- valid: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(value),
3960
- message: options.message || $.fn.bootstrapValidator.i18n.ip.ipv4
3961
- };
3962
- } else if (options.ipv6) {
3963
- return {
3964
- valid: /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/.test(value),
3965
- message: options.message || $.fn.bootstrapValidator.i18n.ip.ipv6
3966
- };
4089
+ var ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
4090
+ ipv6Regex = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,
4091
+ valid = false,
4092
+ message;
4093
+
4094
+ switch (true) {
4095
+ case (options.ipv4 && !options.ipv6):
4096
+ valid = ipv4Regex.test(value);
4097
+ message = options.message || $.fn.bootstrapValidator.i18n.ip.ipv4;
4098
+ break;
4099
+
4100
+ case (!options.ipv4 && options.ipv6):
4101
+ valid = ipv6Regex.test(value);
4102
+ message = options.message || $.fn.bootstrapValidator.i18n.ip.ipv6;
4103
+ break;
4104
+
4105
+ case (options.ipv4 && options.ipv6):
4106
+ /* falls through */
4107
+ default:
4108
+ valid = ipv4Regex.test(value) && ipv6Regex.test(value);
4109
+ message = options.message || $.fn.bootstrapValidator.i18n.ip['default'];
4110
+ break;
3967
4111
  }
3968
4112
 
3969
- return false;
4113
+ return {
4114
+ valid: valid,
4115
+ message: message
4116
+ };
3970
4117
  }
3971
4118
  };
3972
- }(window.jQuery));
3973
- ;(function($) {
4119
+ }(window.jQuery));;(function($) {
3974
4120
  $.fn.bootstrapValidator.i18n.isbn = $.extend($.fn.bootstrapValidator.i18n.isbn || {}, {
3975
4121
  'default': 'Please enter a valid ISBN number'
3976
4122
  });
@@ -4234,8 +4380,9 @@
4234
4380
  },
4235
4381
 
4236
4382
  enableByHtml5: function($field) {
4237
- var max = $field.attr('max');
4238
- if (max) {
4383
+ var type = $field.attr('type'),
4384
+ max = $field.attr('max');
4385
+ if (max && type !== 'date') {
4239
4386
  return {
4240
4387
  value: max
4241
4388
  };
@@ -4265,9 +4412,11 @@
4265
4412
  if (value === '') {
4266
4413
  return true;
4267
4414
  }
4415
+ if (!$.isNumeric(value)) {
4416
+ return false;
4417
+ }
4268
4418
 
4269
4419
  var compareTo = $.isNumeric(options.value) ? options.value : validator.getDynamicOption($field, options.value);
4270
-
4271
4420
  value = parseFloat(value);
4272
4421
  return (options.inclusive === true || options.inclusive === undefined)
4273
4422
  ? {
@@ -4306,6 +4455,89 @@
4306
4455
  }
4307
4456
  };
4308
4457
  }(window.jQuery));
4458
+ ;(function($) {
4459
+ $.fn.bootstrapValidator.i18n.meid = $.extend($.fn.bootstrapValidator.i18n.meid || {}, {
4460
+ 'default': 'Please enter a valid MEID number'
4461
+ });
4462
+
4463
+ $.fn.bootstrapValidator.validators.meid = {
4464
+ /**
4465
+ * Validate MEID (Mobile Equipment Identifier)
4466
+ * Examples:
4467
+ * - Valid: 293608736500703710, 29360-87365-0070-3710, AF0123450ABCDE, AF-012345-0ABCDE
4468
+ * - Invalid: 2936087365007037101
4469
+ *
4470
+ * @see http://en.wikipedia.org/wiki/Mobile_equipment_identifier
4471
+ * @param {BootstrapValidator} validator The validator plugin instance
4472
+ * @param {jQuery} $field Field element
4473
+ * @param {Object} options Can consist of the following keys:
4474
+ * - message: The invalid message
4475
+ * @returns {Boolean}
4476
+ */
4477
+ validate: function(validator, $field, options) {
4478
+ var value = $field.val();
4479
+ if (value === '') {
4480
+ return true;
4481
+ }
4482
+
4483
+ switch (true) {
4484
+ // 14 digit hex representation (no check digit)
4485
+ case /^[0-9A-F]{15}$/i.test(value):
4486
+ // 14 digit hex representation + dashes or spaces (no check digit)
4487
+ case /^[0-9A-F]{2}[- ][0-9A-F]{6}[- ][0-9A-F]{6}[- ][0-9A-F]$/i.test(value):
4488
+ // 18 digit decimal representation (no check digit)
4489
+ case /^\d{19}$/.test(value):
4490
+ // 18 digit decimal representation + dashes or spaces (no check digit)
4491
+ case /^\d{5}[- ]\d{5}[- ]\d{4}[- ]\d{4}[- ]\d$/.test(value):
4492
+ // Grab the check digit
4493
+ var cd = value.charAt(value.length - 1);
4494
+
4495
+ // Strip any non-hex chars
4496
+ value = value.replace(/[- ]/g, '');
4497
+
4498
+ // If it's all digits, luhn base 10 is used
4499
+ if (value.match(/^\d*$/i)) {
4500
+ return $.fn.bootstrapValidator.helpers.luhn(value);
4501
+ }
4502
+
4503
+ // Strip the check digit
4504
+ value = value.slice(0, -1);
4505
+
4506
+ // Get every other char, and double it
4507
+ var cdCalc = '';
4508
+ for (var i = 1; i <= 13; i += 2) {
4509
+ cdCalc += (parseInt(value.charAt(i), 16) * 2).toString(16);
4510
+ }
4511
+
4512
+ // Get the sum of each char in the string
4513
+ var sum = 0;
4514
+ for (i = 0; i < cdCalc.length; i++) {
4515
+ sum += parseInt(cdCalc.charAt(i), 16);
4516
+ }
4517
+
4518
+ // If the last digit of the calc is 0, the check digit is 0
4519
+ return (sum % 10 === 0)
4520
+ ? (cd === '0')
4521
+ // Subtract it from the next highest 10s number (64 goes to 70) and subtract the sum
4522
+ // Double it and turn it into a hex char
4523
+ : (cd === ((Math.floor((sum + 10) / 10) * 10 - sum) * 2).toString(16));
4524
+
4525
+ // 14 digit hex representation (no check digit)
4526
+ case /^[0-9A-F]{14}$/i.test(value):
4527
+ // 14 digit hex representation + dashes or spaces (no check digit)
4528
+ case /^[0-9A-F]{2}[- ][0-9A-F]{6}[- ][0-9A-F]{6}$/i.test(value):
4529
+ // 18 digit decimal representation (no check digit)
4530
+ case /^\d{18}$/.test(value):
4531
+ // 18 digit decimal representation + dashes or spaces (no check digit)
4532
+ case /^\d{5}[- ]\d{5}[- ]\d{4}[- ]\d{4}$/.test(value):
4533
+ return true;
4534
+
4535
+ default:
4536
+ return false;
4537
+ }
4538
+ }
4539
+ };
4540
+ }(window.jQuery));
4309
4541
  ;(function($) {
4310
4542
  $.fn.bootstrapValidator.i18n.notEmpty = $.extend($.fn.bootstrapValidator.i18n.notEmpty || {}, {
4311
4543
  'default': 'Please enter a value'
@@ -4364,6 +4596,10 @@
4364
4596
  * @returns {Boolean}
4365
4597
  */
4366
4598
  validate: function(validator, $field, options) {
4599
+ if (this.enableByHtml5($field) && $field.get(0).validity && $field.get(0).validity.badInput === true) {
4600
+ return false;
4601
+ }
4602
+
4367
4603
  var value = $field.val();
4368
4604
  if (value === '') {
4369
4605
  return true;
@@ -4383,7 +4619,12 @@
4383
4619
  countryNotSupported: 'The country code %s is not supported',
4384
4620
  country: 'Please enter a valid phone number in %s',
4385
4621
  countries: {
4622
+ BR: 'Brazil',
4623
+ ES: 'Spain',
4624
+ FR: 'France',
4386
4625
  GB: 'United Kingdom',
4626
+ MA: 'Morocco',
4627
+ PK: 'Pakistan',
4387
4628
  US: 'USA'
4388
4629
  }
4389
4630
  });
@@ -4395,7 +4636,7 @@
4395
4636
  },
4396
4637
 
4397
4638
  // The supported countries
4398
- COUNTRY_CODES: ['GB', 'US'],
4639
+ COUNTRY_CODES: ['BR', 'ES', 'FR', 'GB', 'MA', 'PK', 'US'],
4399
4640
 
4400
4641
  /**
4401
4642
  * Return true if the input value contains a valid phone number for the country
@@ -4411,7 +4652,6 @@
4411
4652
  * - Name of callback function that returns the country code
4412
4653
  * - A callback function that returns the country code
4413
4654
  *
4414
- * Currently it only supports United State (US) or United Kingdom (GB) countries
4415
4655
  * @returns {Boolean|Object}
4416
4656
  */
4417
4657
  validate: function(validator, $field, options) {
@@ -4435,6 +4675,24 @@
4435
4675
 
4436
4676
  var isValid = true;
4437
4677
  switch (country.toUpperCase()) {
4678
+ case 'BR':
4679
+ // Test: http://regexr.com/399m1
4680
+ value = $.trim(value);
4681
+ isValid = (/^(([\d]{4}[-.\s]{1}[\d]{2,3}[-.\s]{1}[\d]{2}[-.\s]{1}[\d]{2})|([\d]{4}[-.\s]{1}[\d]{3}[-.\s]{1}[\d]{4})|((\(?\+?[0-9]{2}\)?\s?)?(\(?\d{2}\)?\s?)?\d{4,5}[-.\s]?\d{4}))$/).test(value);
4682
+ break;
4683
+
4684
+ case 'ES':
4685
+ // http://regex101.com/r/rB9mA9/1
4686
+ value = $.trim(value);
4687
+ isValid = (/^(?:(?:(?:\+|00)34\D?))?(?:9|6)(?:\d\D?){8}$/).test(value);
4688
+ break;
4689
+
4690
+ case 'FR':
4691
+ // http://regexr.com/39a2p
4692
+ value = $.trim(value);
4693
+ isValid = (/^(?:(?:(?:\+|00)33[ ]?(?:\(0\)[ ]?)?)|0){1}[1-9]{1}([ .-]?)(?:\d{2}\1?){3}\d{2}$/).test(value);
4694
+ break;
4695
+
4438
4696
  case 'GB':
4439
4697
  // http://aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers#Match_GB_telephone_number_in_any_format
4440
4698
  // Test: http://regexr.com/38uhv
@@ -4442,6 +4700,19 @@
4442
4700
  isValid = (/^\(?(?:(?:0(?:0|11)\)?[\s-]?\(?|\+)44\)?[\s-]?\(?(?:0\)?[\s-]?\(?)?|0)(?:\d{2}\)?[\s-]?\d{4}[\s-]?\d{4}|\d{3}\)?[\s-]?\d{3}[\s-]?\d{3,4}|\d{4}\)?[\s-]?(?:\d{5}|\d{3}[\s-]?\d{3})|\d{5}\)?[\s-]?\d{4,5}|8(?:00[\s-]?11[\s-]?11|45[\s-]?46[\s-]?4\d))(?:(?:[\s-]?(?:x|ext\.?\s?|\#)\d+)?)$/).test(value);
4443
4701
  break;
4444
4702
 
4703
+ case 'MA':
4704
+ // http://en.wikipedia.org/wiki/Telephone_numbers_in_Morocco
4705
+ // Test: http://regexr.com/399n8
4706
+ value = $.trim(value);
4707
+ isValid = (/^(?:(?:(?:\+|00)212[\s]?(?:[\s]?\(0\)[\s]?)?)|0){1}(?:5[\s.-]?[2-3]|6[\s.-]?[13-9]){1}[0-9]{1}(?:[\s.-]?\d{2}){3}$/).test(value);
4708
+ break;
4709
+
4710
+ case 'PK':
4711
+ // http://regex101.com/r/yH8aV9/2
4712
+ value = $.trim(value);
4713
+ isValid = (/^0?3[0-9]{2}[0-9]{7}$/).test(value);
4714
+ break;
4715
+
4445
4716
  case 'US':
4446
4717
  /* falls through */
4447
4718
  default:
@@ -4511,8 +4782,9 @@
4511
4782
  $.fn.bootstrapValidator.validators.remote = {
4512
4783
  html5Attributes: {
4513
4784
  message: 'message',
4514
- url: 'url',
4515
- name: 'name'
4785
+ name: 'name',
4786
+ type: 'type',
4787
+ url: 'url'
4516
4788
  },
4517
4789
 
4518
4790
  /**
@@ -4529,6 +4801,7 @@
4529
4801
  * }
4530
4802
  * - name {String} [optional]: Override the field name for the request.
4531
4803
  * - message: The invalid message
4804
+ * - headers: Additional headers
4532
4805
  * @returns {Boolean|Deferred}
4533
4806
  */
4534
4807
  validate: function(validator, $field, options) {
@@ -4537,10 +4810,11 @@
4537
4810
  return true;
4538
4811
  }
4539
4812
 
4540
- var name = $field.attr('data-bv-field'),
4541
- data = options.data || {},
4542
- url = options.url,
4543
- type = options.type || 'POST';
4813
+ var name = $field.attr('data-bv-field'),
4814
+ data = options.data || {},
4815
+ url = options.url,
4816
+ type = options.type || 'POST',
4817
+ headers = options.headers || {};
4544
4818
 
4545
4819
  // Support dynamic data
4546
4820
  if ('function' === typeof data) {
@@ -4557,6 +4831,7 @@
4557
4831
  var dfd = new $.Deferred();
4558
4832
  var xhr = $.ajax({
4559
4833
  type: type,
4834
+ headers: headers,
4560
4835
  url: url,
4561
4836
  dataType: 'json',
4562
4837
  data: data
@@ -4946,7 +5221,7 @@
4946
5221
  // Notes on possible differences from a standard/generic validation:
4947
5222
  //
4948
5223
  // - utf-8 char class take in consideration the full Unicode range
4949
- // - TLDs have been made mandatory so single names like "localhost" fails
5224
+ // - TLDs are mandatory unless `allowLocal` is true
4950
5225
  // - protocols have been restricted to ftp, http and https only as requested
4951
5226
  //
4952
5227
  // Changes:
@@ -4956,6 +5231,7 @@
4956
5231
  // (since they are broadcast/network addresses)
4957
5232
  //
4958
5233
  // - Added exclusion of private, reserved and/or local networks ranges
5234
+ // unless `allowLocal` is true
4959
5235
  //
4960
5236
  var allowLocal = options.allowLocal === true || options.allowLocal === 'true',
4961
5237
  urlExp = new RegExp(
@@ -4987,6 +5263,8 @@
4987
5263
  "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*" +
4988
5264
  // TLD identifier
4989
5265
  "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
5266
+ // Allow intranet sites (no TLD) if `allowLocal` is true
5267
+ (allowLocal ? '?' : '') +
4990
5268
  ")" +
4991
5269
  // port number
4992
5270
  "(?::\\d{2,5})?" +
@@ -5054,6 +5332,7 @@
5054
5332
  AT: 'Austrian',
5055
5333
  BE: 'Belgian',
5056
5334
  BG: 'Bulgarian',
5335
+ BR: 'Brazilian',
5057
5336
  CH: 'Swiss',
5058
5337
  CY: 'Cypriot',
5059
5338
  CZ: 'Czech',
@@ -5069,6 +5348,7 @@
5069
5348
  HU: 'Hungarian',
5070
5349
  HR: 'Croatian',
5071
5350
  IE: 'Irish',
5351
+ IS: 'Iceland',
5072
5352
  IT: 'Italian',
5073
5353
  LT: 'Lithuanian',
5074
5354
  LU: 'Luxembourg',
@@ -5083,7 +5363,8 @@
5083
5363
  RS: 'Serbian',
5084
5364
  SE: 'Swedish',
5085
5365
  SI: 'Slovenian',
5086
- SK: 'Slovak'
5366
+ SK: 'Slovak',
5367
+ ZA: 'South African'
5087
5368
  }
5088
5369
  });
5089
5370
 
@@ -5095,8 +5376,8 @@
5095
5376
 
5096
5377
  // Supported country codes
5097
5378
  COUNTRY_CODES: [
5098
- 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'EL', 'HU', 'IE', 'IT',
5099
- 'LV', 'LT', 'LU', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'RS', 'SK', 'SI', 'ES', 'SE', 'CH', 'GB'
5379
+ 'AT', 'BE', 'BG', 'BR', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'EL', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU',
5380
+ 'IE', 'IS', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'RS', 'SE', 'SK', 'SI', 'ZA'
5100
5381
  ],
5101
5382
 
5102
5383
  /**
@@ -5301,6 +5582,64 @@
5301
5582
 
5302
5583
  return false;
5303
5584
  },
5585
+
5586
+ /**
5587
+ * Validate Brazilian VAT number (CNPJ)
5588
+ *
5589
+ * @param {String} value VAT number
5590
+ * @returns {Boolean}
5591
+ */
5592
+ _br: function(value) {
5593
+ if (value === '') {
5594
+ return true;
5595
+ }
5596
+ var cnpj = value.replace(/[^\d]+/g, '');
5597
+ if (cnpj === '' || cnpj.length !== 14) {
5598
+ return false;
5599
+ }
5600
+
5601
+ // Remove invalids CNPJs
5602
+ if (cnpj === '00000000000000' || cnpj === '11111111111111' || cnpj === '22222222222222' ||
5603
+ cnpj === '33333333333333' || cnpj === '44444444444444' || cnpj === '55555555555555' ||
5604
+ cnpj === '66666666666666' || cnpj === '77777777777777' || cnpj === '88888888888888' ||
5605
+ cnpj === '99999999999999')
5606
+ {
5607
+ return false;
5608
+ }
5609
+
5610
+ // Validate verification digits
5611
+ var length = cnpj.length - 2,
5612
+ numbers = cnpj.substring(0, length),
5613
+ digits = cnpj.substring(length),
5614
+ sum = 0,
5615
+ pos = length - 7;
5616
+
5617
+ for (var i = length; i >= 1; i--) {
5618
+ sum += parseInt(numbers.charAt(length - i), 10) * pos--;
5619
+ if (pos < 2) {
5620
+ pos = 9;
5621
+ }
5622
+ }
5623
+
5624
+ var result = sum % 11 < 2 ? 0 : 11 - sum % 11;
5625
+ if (result !== parseInt(digits.charAt(0), 10)) {
5626
+ return false;
5627
+ }
5628
+
5629
+ length = length + 1;
5630
+ numbers = cnpj.substring(0, length);
5631
+ sum = 0;
5632
+ pos = length - 7;
5633
+ for (i = length; i >= 1; i--) {
5634
+ sum += parseInt(numbers.charAt(length - i), 10) * pos--;
5635
+ if (pos < 2) {
5636
+ pos = 9;
5637
+ }
5638
+ }
5639
+
5640
+ result = sum % 11 < 2 ? 0 : 11 - sum % 11;
5641
+ return (result === parseInt(digits.charAt(1), 10));
5642
+ },
5304
5643
 
5305
5644
  /**
5306
5645
  * Validate Swiss VAT number
@@ -5641,7 +5980,7 @@
5641
5980
 
5642
5981
  value = value.substr(2);
5643
5982
 
5644
- if (!$.fn.bootstrapValidator.helpers.luhn(value.substr(2))) {
5983
+ if (!$.fn.bootstrapValidator.helpers.luhn(value.substr(2))) {
5645
5984
  return false;
5646
5985
  }
5647
5986
 
@@ -5834,6 +6173,19 @@
5834
6173
  return true;
5835
6174
  },
5836
6175
 
6176
+ /**
6177
+ * Validate Icelandic VAT (VSK) number
6178
+ * Examples:
6179
+ * - Valid: 12345, 123456
6180
+ * - Invalid: 1234567
6181
+ *
6182
+ * @params {String} value VAT number
6183
+ * @returns {Boolean}
6184
+ */
6185
+ _is: function(value) {
6186
+ return /^IS\d{5,6}$/.test(value);
6187
+ },
6188
+
5837
6189
  /**
5838
6190
  * Validate Italian VAT number, which consists of 11 digits.
5839
6191
  * - First 7 digits are a company identifier
@@ -6262,6 +6614,19 @@
6262
6614
  }
6263
6615
 
6264
6616
  return (parseInt(value.substr(2), 10) % 11 === 0);
6617
+ },
6618
+
6619
+ /**
6620
+ * Validate South African VAT number
6621
+ * Examples:
6622
+ * - Valid: 4012345678
6623
+ * - Invalid: 40123456789, 3012345678
6624
+ *
6625
+ * @params {String} value VAT number
6626
+ * @returns {Boolean}
6627
+ */
6628
+ _za: function(value) {
6629
+ return /^ZA4\d{9}$/.test(value);
6265
6630
  }
6266
6631
  };
6267
6632
  }(window.jQuery));
@@ -6320,14 +6685,16 @@
6320
6685
  countryNotSupported: 'The country code %s is not supported',
6321
6686
  country: 'Please enter a valid %s',
6322
6687
  countries: {
6323
- 'CA': 'Canadian postal code',
6324
- 'DK': 'Danish postal code',
6325
- 'GB': 'United Kingdom postal code',
6326
- 'IT': 'Italian postal code',
6327
- 'NL': 'Dutch postal code',
6328
- 'SE': 'Swiss postal code',
6329
- 'SG': 'Singapore postal code',
6330
- 'US': 'US zip code'
6688
+ BR: 'Brazilian postal code',
6689
+ CA: 'Canadian postal code',
6690
+ DK: 'Danish postal code',
6691
+ GB: 'United Kingdom postal code',
6692
+ IT: 'Italian postal code',
6693
+ MA: 'Moroccan postal code',
6694
+ NL: 'Dutch postal code',
6695
+ SE: 'Swiss postal code',
6696
+ SG: 'Singapore postal code',
6697
+ US: 'US zip code'
6331
6698
  }
6332
6699
  });
6333
6700
 
@@ -6337,7 +6704,7 @@
6337
6704
  country: 'country'
6338
6705
  },
6339
6706
 
6340
- COUNTRY_CODES: ['CA', 'DK', 'GB', 'IT', 'NL', 'SE', 'SG', 'US'],
6707
+ COUNTRY_CODES: ['BR', 'CA', 'DK', 'GB', 'IT', 'MA', 'NL', 'SE', 'SG', 'US'],
6341
6708
 
6342
6709
  /**
6343
6710
  * Return true if and only if the input value is a valid country zip code
@@ -6350,16 +6717,6 @@
6350
6717
  *
6351
6718
  * The country can be defined by:
6352
6719
  * - An ISO 3166 country code
6353
- * Currently it supports the following countries:
6354
- * - US (United States)
6355
- * - CA (Canada)
6356
- * - DK (Denmark)
6357
- * - GB (United Kingdom)
6358
- * - IT (Italy)
6359
- * - NL (Netherlands)
6360
- * - SE (Sweden)
6361
- * - SG (Singapore)
6362
- *
6363
6720
  * - Name of field which its value defines the country code
6364
6721
  * - Name of callback function that returns the country code
6365
6722
  * - A callback function that returns the country code
@@ -6391,6 +6748,10 @@
6391
6748
  var isValid = false;
6392
6749
  country = country.toUpperCase();
6393
6750
  switch (country) {
6751
+ case 'BR':
6752
+ isValid = /^(\d{2})([\.]?)(\d{3})([\-]?)(\d{3})$/.test(value);
6753
+ break;
6754
+
6394
6755
  case 'CA':
6395
6756
  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);
6396
6757
  break;
@@ -6408,6 +6769,11 @@
6408
6769
  isValid = /^(I-|IT-)?\d{5}$/i.test(value);
6409
6770
  break;
6410
6771
 
6772
+ // http://en.wikipedia.org/wiki/List_of_postal_codes_in_Morocco
6773
+ case 'MA':
6774
+ isValid = /^[1-9][0-9]{4}$/i.test(value);
6775
+ break;
6776
+
6411
6777
  // http://en.wikipedia.org/wiki/Postal_codes_in_the_Netherlands
6412
6778
  case 'NL':
6413
6779
  isValid = /^[1-9][0-9]{3} ?(?!sa|sd|ss)[a-z]{2}$/i.test(value);
@@ -6419,8 +6785,8 @@
6419
6785
 
6420
6786
  case 'SG':
6421
6787
  isValid = /^([0][1-9]|[1-6][0-9]|[7]([0-3]|[5-9])|[8][0-2])(\d{4})$/i.test(value);
6422
- break;
6423
-
6788
+ break;
6789
+
6424
6790
  case 'US':
6425
6791
  /* falls through */
6426
6792
  default: