vendor/assets/javascripts/bootstrapValidator.js in bootstrap-validator-rails-0.5.0.2 vs vendor/assets/javascripts/bootstrapValidator.js in bootstrap-validator-rails-0.5.1
- old
+ new
@@ -1,10 +1,10 @@
/*!
* BootstrapValidator (http://bootstrapvalidator.com)
* The best jQuery plugin to validate form fields. Designed to use with Bootstrap 3
*
- * @version v0.5.0, built on 2014-07-14 4:31:02 PM
+ * @version v0.5.1, built on 2014-08-22 4:55:09 PM
* @author https://twitter.com/nghuuphuoc
* @copyright (c) 2013 - 2014 Nguyen Huu Phuoc
* @license MIT
*/
(function($) {
@@ -12,10 +12,11 @@
this.$form = $(form);
this.options = $.extend({}, $.fn.bootstrapValidator.DEFAULT_OPTIONS, options);
this.$invalidFields = $([]); // Array of invalid fields
this.$submitButton = null; // The submit button which is clicked to submit form
+ this.$hiddenButton = null;
// Validating status
this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED';
this.STATUS_VALIDATING = 'VALIDATING';
this.STATUS_INVALID = 'INVALID';
@@ -66,10 +67,23 @@
fields: {},
feedbackIcons: {
valid: this.$form.attr('data-bv-feedbackicons-valid'),
invalid: this.$form.attr('data-bv-feedbackicons-invalid'),
validating: this.$form.attr('data-bv-feedbackicons-validating')
+ },
+ events: {
+ formInit: this.$form.attr('data-bv-events-form-init'),
+ formError: this.$form.attr('data-bv-events-form-error'),
+ formSuccess: this.$form.attr('data-bv-events-form-success'),
+ fieldAdded: this.$form.attr('data-bv-events-field-added'),
+ fieldRemoved: this.$form.attr('data-bv-events-field-removed'),
+ fieldInit: this.$form.attr('data-bv-events-field-init'),
+ fieldError: this.$form.attr('data-bv-events-field-error'),
+ fieldSuccess: this.$form.attr('data-bv-events-field-success'),
+ fieldStatus: this.$form.attr('data-bv-events-field-status'),
+ validatorError: this.$form.attr('data-bv-events-validator-error'),
+ validatorSuccess: this.$form.attr('data-bv-events-validator-success')
}
};
this.$form
// Disable client side validation in HTML 5
@@ -96,27 +110,47 @@
options.fields[field] = $.extend({}, opts, options.fields[field]);
}
});
this.options = $.extend(true, this.options, options);
+
+ // When pressing Enter on any field in the form, the first submit button will do its job.
+ // The form then will be submitted.
+ // I create a first hidden submit button
+ this.$hiddenButton = $('<button/>')
+ .attr('type', 'submit')
+ .prependTo(this.$form)
+ .addClass('bv-hidden-submit')
+ .css({ display: 'none', width: 0, height: 0 });
+
+ this.$form
+ .on('click.bv', '[type="submit"]', function(e) {
+ // Don't perform validation when clicking on the submit button/input
+ // which aren't defined by the 'submitButtons' option
+ var $button = $(e.target).eq(0);
+ if (that.options.submitButtons && !$button.is(that.options.submitButtons) && !$button.is(that.$hiddenButton)) {
+ that.$form.off('submit.bv').submit();
+ }
+ });
+
for (var field in this.options.fields) {
this._initField(field);
}
- this.$form.trigger($.Event('init.form.bv'), {
+ this.$form.trigger($.Event(this.options.events.formInit), {
bv: this,
options: this.options
});
// Prepare the events
if (this.options.onSuccess) {
- this.$form.on('success.form.bv', function(e) {
+ this.$form.on(this.options.events.formSuccess, function(e) {
$.fn.bootstrapValidator.helpers.call(that.options.onSuccess, [e]);
});
}
if (this.options.onError) {
- this.$form.on('error.form.bv', function(e) {
+ this.$form.on(this.options.events.formError, function(e) {
$.fn.bootstrapValidator.helpers.call(that.options.onError, [e]);
});
}
},
@@ -275,16 +309,16 @@
.appendTo($message);
}
// Prepare the validator events
if (this.options.fields[field].validators[validatorName].onSuccess) {
- $field.on('success.validator.bv', function(e, data) {
+ $field.on(this.options.events.validatorSuccess, function(e, data) {
$.fn.bootstrapValidator.helpers.call(that.options.fields[field].validators[validatorName].onSuccess, [e, data]);
});
}
if (this.options.fields[field].validators[validatorName].onError) {
- $field.on('error.validator.bv', function(e, data) {
+ $field.on(this.options.events.validatorError, function(e, data) {
$.fn.bootstrapValidator.helpers.call(that.options.fields[field].validators[validatorName].onError, [e, data]);
});
}
}
@@ -298,14 +332,23 @@
$parent.removeClass('has-success').removeClass('has-error').addClass('has-feedback');
var $icon = $('<i/>')
.css('display', 'none')
.addClass('form-control-feedback')
.attr('data-bv-icon-for', field)
- // Place it after the label containing the checkbox/radio
- // so when clicking the icon, it doesn't effect to the checkbox/radio element
- .insertAfter(('checkbox' === type || 'radio' === type) ? $field.parent() : $field);
+ .insertAfter($field);
+ // Place it after the container of checkbox/radio
+ // so when clicking the icon, it doesn't effect to the checkbox/radio element
+ if ('checkbox' === type || 'radio' === type) {
+ var $fieldParent = $field.parent();
+ if ($fieldParent.hasClass(type)) {
+ $icon.insertAfter($fieldParent);
+ } else if ($fieldParent.parent().hasClass(type)) {
+ $icon.insertAfter($fieldParent.parent());
+ }
+ }
+
// The feedback icon does not render correctly if there is no label
// https://github.com/twbs/bootstrap/issues/12873
if ($parent.find('label').length === 0) {
$icon.css('top', 0);
}
@@ -319,21 +362,21 @@
}
}
// Prepare the events
if (this.options.fields[field].onSuccess) {
- fields.on('success.field.bv', function(e, data) {
+ fields.on(this.options.events.fieldSuccess, function(e, data) {
$.fn.bootstrapValidator.helpers.call(that.options.fields[field].onSuccess, [e, data]);
});
}
if (this.options.fields[field].onError) {
- fields.on('error.field.bv', function(e, data) {
+ fields.on(this.options.events.fieldError, function(e, data) {
$.fn.bootstrapValidator.helpers.call(that.options.fields[field].onError, [e, data]);
});
}
if (this.options.fields[field].onStatus) {
- fields.on('status.field.bv', function(e, data) {
+ fields.on(this.options.events.fieldStatus, function(e, data) {
$.fn.bootstrapValidator.helpers.call(that.options.fields[field].onStatus, [e, data]);
});
}
// Set live mode
@@ -355,11 +398,11 @@
}
});
break;
}
- fields.trigger($.Event('init.field.bv'), {
+ fields.trigger($.Event(this.options.events.fieldInit), {
bv: this,
field: field,
element: fields
});
},
@@ -423,11 +466,11 @@
/**
* Called when all validations are completed
*/
_submit: function() {
var isValid = this.isValid(),
- eventType = isValid ? 'success.form.bv' : 'error.form.bv',
+ eventType = isValid ? this.options.events.formSuccess : this.options.events.formError,
e = $.Event(eventType);
this.$form.trigger(e);
// Call default handler
@@ -586,14 +629,14 @@
// Trigger an event after given validator completes
if (validatorName) {
switch ($field.data('bv.result.' + validatorName)) {
case this.STATUS_INVALID:
- $field.trigger($.Event('error.validator.bv'), data);
+ $field.trigger($.Event(this.options.events.validatorError), data);
break;
case this.STATUS_VALID:
- $field.trigger($.Event('success.validator.bv'), data);
+ $field.trigger($.Event(this.options.events.validatorSuccess), data);
break;
default:
break;
}
}
@@ -617,18 +660,18 @@
if (counter[this.STATUS_VALID] === numValidators) {
// Remove from the list of invalid fields
this.$invalidFields = this.$invalidFields.not($field);
- $field.trigger($.Event('success.field.bv'), data);
+ $field.trigger($.Event(this.options.events.fieldSuccess), data);
}
// If all validators are completed and there is at least one validator which doesn't pass
else if (counter[this.STATUS_NOT_VALIDATED] === 0 && counter[this.STATUS_VALIDATING] === 0 && counter[this.STATUS_INVALID] > 0) {
// Add to the list of invalid fields
this.$invalidFields = this.$invalidFields.add($field);
- $field.trigger($.Event('error.field.bv'), data);
+ $field.trigger($.Event(this.options.events.fieldError), data);
}
},
// ---
// Public methods
@@ -954,11 +997,11 @@
(status === this.STATUS_INVALID) ? $errors.show() : $errors.hide();
break;
}
// Trigger an event
- $field.trigger($.Event('status.field.bv'), {
+ $field.trigger($.Event(this.options.events.fieldStatus), {
bv: this,
field: field,
element: $field,
status: status
});
@@ -1256,11 +1299,11 @@
this._initField(('checkbox' === type || 'radio' === type) ? field : $field);
}
this.disableSubmitButtons(false);
// Trigger an event
- this.$form.trigger($.Event('added.field.bv'), {
+ this.$form.trigger($.Event(this.options.events.fieldAdded), {
field: field,
element: fields,
options: this.options.fields[field]
});
@@ -1312,11 +1355,11 @@
this._initField(field);
}
this.disableSubmitButtons(false);
// Trigger an event
- this.$form.trigger($.Event('removed.field.bv'), {
+ this.$form.trigger($.Event(this.options.events.fieldRemoved), {
field: field,
element: fields
});
return this;
@@ -1462,11 +1505,11 @@
if ($f.length) {
return $f.val();
}
// ... return value of callback
else {
- return $.fn.bootstrapValidator.helpers.call(option, [value, this, $field]);
+ return $.fn.bootstrapValidator.helpers.call(option, [value, this, $field]) || option;
}
}
return null;
},
@@ -1520,19 +1563,20 @@
$field.removeData('bv.result.' + validator).removeData('bv.dfs.' + validator);
}
}
}
- // Enable submit buttons
- this.disableSubmitButtons(false);
+ this.disableSubmitButtons(false); // Enable submit buttons
+ this.$hiddenButton.remove(); // Remove the hidden button
this.$form
.removeClass(this.options.elementClass)
.off('.bv')
.removeData('bootstrapValidator')
// Remove generated hidden elements
- .find('[data-bv-submit-hidden]').remove();
+ .find('[data-bv-submit-hidden]').remove().end()
+ .find('[type="submit"]').off('click.bv');
}
};
// Plugin definition
$.fn.bootstrapValidator = function(option) {
@@ -1636,11 +1680,27 @@
// - disabled: Disable the live validating. The error messages are only shown after the form is submitted
// - submitted: The live validating is enabled after the form is submitted
live: 'enabled',
// Map the field name with validator rules
- fields: null
+ fields: null,
+
+ // Use custom event name to avoid window.onerror being invoked by jQuery
+ // See https://github.com/nghuuphuoc/bootstrapvalidator/issues/630
+ events: {
+ formInit: 'init.form.bv',
+ formError: 'error.form.bv',
+ formSuccess: 'success.form.bv',
+ fieldAdded: 'added.field.bv',
+ fieldRemoved: 'removed.field.bv',
+ fieldInit: 'init.field.bv',
+ fieldError: 'error.field.bv',
+ fieldSuccess: 'success.field.bv',
+ fieldStatus: 'status.field.bv',
+ validatorError: 'error.validator.bv',
+ validatorSuccess: 'success.validator.bv'
+ }
};
// Available validators
$.fn.bootstrapValidator.validators = {};
@@ -1671,11 +1731,12 @@
func = ns.pop(),
context = window;
for (var i = 0; i < ns.length; i++) {
context = context[ns[i]];
}
- return context[func].apply(this, args);
+
+ return (typeof context[func] === 'undefined') ? null : context[func].apply(this, args);
}
},
/**
* Format a string
@@ -1709,10 +1770,13 @@
*/
date: function(year, month, day, notInFuture) {
if (isNaN(year) || isNaN(month) || isNaN(day)) {
return false;
}
+ if (day.length > 2 || month.length > 2 || year.length > 4) {
+ return false;
+ }
day = parseInt(day, 10);
month = parseInt(month, 10);
year = parseInt(year, 10);
@@ -1874,14 +1938,16 @@
validate: function(validator, $field, options) {
var value = $field.val();
if (value === '') {
return true;
}
+ if (!$.isNumeric(value)) {
+ return false;
+ }
var min = $.isNumeric(options.min) ? options.min : validator.getDynamicOption($field, options.min),
max = $.isNumeric(options.max) ? options.max : validator.getDynamicOption($field, options.max);
-
value = parseFloat(value);
return (options.inclusive === true || options.inclusive === undefined)
? {
valid: value >= min && value <= max,
message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.between['default'], [min, max])
@@ -2311,10 +2377,15 @@
return true;
}
options.format = options.format || 'MM/DD/YYYY';
+ // #683: Force the format to YYYY-MM-DD as the default browser behaviour when using type="date" attribute
+ if ($field.attr('type') === 'date') {
+ options.format = 'YYYY-MM-DD';
+ }
+
var formats = options.format.split(' '),
dateFormat = formats[0],
timeFormat = (formats.length > 1) ? formats[1] : null,
amOrPm = (formats.length > 2) ? formats[2] : null,
sections = value.split(' '),
@@ -2343,11 +2414,11 @@
var year = date[$.inArray('YYYY', dateFormat)],
month = date[$.inArray('MM', dateFormat)],
day = date[$.inArray('DD', dateFormat)];
- if (!year || !month || !day) {
+ if (!year || !month || !day || year.length !== 4) {
return false;
}
// Determine the time
var minutes = null, hours = null, seconds = null;
@@ -2363,28 +2434,37 @@
minutes = time.length > 1 ? time[1] : null;
seconds = time.length > 2 ? time[2] : null;
// Validate seconds
if (seconds) {
+ if (isNaN(seconds) || seconds.length > 2) {
+ return false;
+ }
seconds = parseInt(seconds, 10);
- if (isNaN(seconds) || seconds < 0 || seconds > 60) {
+ if (seconds < 0 || seconds > 60) {
return false;
}
}
// Validate hours
if (hours) {
+ if (isNaN(hours) || hours.length > 2) {
+ return false;
+ }
hours = parseInt(hours, 10);
- if (isNaN(hours) || hours < 0 || hours >= 24 || (amOrPm && hours > 12)) {
+ if (hours < 0 || hours >= 24 || (amOrPm && hours > 12)) {
return false;
}
}
// Validate minutes
if (minutes) {
+ if (isNaN(minutes) || minutes.length > 2) {
+ return false;
+ }
minutes = parseInt(minutes, 10);
- if (isNaN(minutes) || minutes < 0 || minutes > 59) {
+ if (minutes < 0 || minutes > 59) {
return false;
}
}
}
@@ -2419,11 +2499,11 @@
if (value === '') {
return true;
}
var compareWith = validator.getFieldElements(options.field);
- if (compareWith === null) {
+ if (compareWith === null || compareWith.length === 0) {
return true;
}
if (value !== compareWith.val()) {
validator.updateStatus(options.field, validator.STATUS_VALID, 'different');
@@ -2580,11 +2660,11 @@
if (extensions && $.inArray(ext.toLowerCase(), extensions) === -1) {
return false;
}
// Check file type
- if (types && $.inArray(files[i].type.toLowerCase(), types) === -1) {
+ if (files[i].type && types && $.inArray(files[i].type.toLowerCase(), types) === -1) {
return false;
}
}
} else {
// Check file extension
@@ -2610,12 +2690,13 @@
value: 'value',
inclusive: 'inclusive'
},
enableByHtml5: function($field) {
- var min = $field.attr('min');
- if (min) {
+ var type = $field.attr('type'),
+ min = $field.attr('min');
+ if (min && type !== 'date') {
return {
value: min
};
}
@@ -2641,13 +2722,15 @@
validate: function(validator, $field, options) {
var value = $field.val();
if (value === '') {
return true;
}
+ if (!$.isNumeric(value)) {
+ return false;
+ }
var compareTo = $.isNumeric(options.value) ? options.value : validator.getDynamicOption($field, options.value);
-
value = parseFloat(value);
return (options.inclusive === true || options.inclusive === undefined)
? {
valid: value >= compareTo,
message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.greaterThan['default'], compareTo)
@@ -2844,89 +2927,89 @@
},
// http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf
// http://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country
REGEX: {
- 'AD': 'AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}', // Andorra
- 'AE': 'AE[0-9]{2}[0-9]{3}[0-9]{16}', // United Arab Emirates
- 'AL': 'AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}', // Albania
- 'AO': 'AO[0-9]{2}[0-9]{21}', // Angola
- 'AT': 'AT[0-9]{2}[0-9]{5}[0-9]{11}', // Austria
- 'AZ': 'AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}', // Azerbaijan
- 'BA': 'BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}', // Bosnia and Herzegovina
- 'BE': 'BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}', // Belgium
- 'BF': 'BF[0-9]{2}[0-9]{23}', // Burkina Faso
- 'BG': 'BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}', // Bulgaria
- 'BH': 'BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}', // Bahrain
- 'BI': 'BI[0-9]{2}[0-9]{12}', // Burundi
- 'BJ': 'BJ[0-9]{2}[A-Z]{1}[0-9]{23}', // Benin
- 'BR': 'BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]', // Brazil
- 'CH': 'CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}', // Switzerland
- 'CI': 'CI[0-9]{2}[A-Z]{1}[0-9]{23}', // Ivory Coast
- 'CM': 'CM[0-9]{2}[0-9]{23}', // Cameroon
- 'CR': 'CR[0-9]{2}[0-9]{3}[0-9]{14}', // Costa Rica
- 'CV': 'CV[0-9]{2}[0-9]{21}', // Cape Verde
- 'CY': 'CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}', // Cyprus
- 'CZ': 'CZ[0-9]{2}[0-9]{20}', // Czech Republic
- 'DE': 'DE[0-9]{2}[0-9]{8}[0-9]{10}', // Germany
- 'DK': 'DK[0-9]{2}[0-9]{14}', // Denmark
- 'DO': 'DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}', // Dominican Republic
- 'DZ': 'DZ[0-9]{2}[0-9]{20}', // Algeria
- 'EE': 'EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}', // Estonia
- 'ES': 'ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}', // Spain
- 'FI': 'FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}', // Finland
- 'FO': 'FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', // Faroe Islands
- 'FR': 'FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', // France
- 'GB': 'GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', // United Kingdom
- 'GE': 'GE[0-9]{2}[A-Z]{2}[0-9]{16}', // Georgia
- 'GI': 'GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}', // Gibraltar
- 'GL': 'GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', // Greenland
- 'GR': 'GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}', // Greece
- 'GT': 'GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}', // Guatemala
- 'HR': 'HR[0-9]{2}[0-9]{7}[0-9]{10}', // Croatia
- 'HU': 'HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}', // Hungary
- 'IE': 'IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', // Ireland
- 'IL': 'IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}', // Israel
- 'IR': 'IR[0-9]{2}[0-9]{22}', // Iran
- 'IS': 'IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}', // Iceland
- 'IT': 'IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', // Italy
- 'JO': 'JO[0-9]{2}[A-Z]{4}[0-9]{4}[0]{8}[A-Z0-9]{10}', // Jordan
- 'KW': 'KW[0-9]{2}[A-Z]{4}[0-9]{22}', // Kuwait
- 'KZ': 'KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}', // Kazakhstan
- 'LB': 'LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}', // Lebanon
- 'LI': 'LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}', // Liechtenstein
- 'LT': 'LT[0-9]{2}[0-9]{5}[0-9]{11}', // Lithuania
- 'LU': 'LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}', // Luxembourg
- 'LV': 'LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}', // Latvia
- 'MC': 'MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', // Monaco
- 'MD': 'MD[0-9]{2}[A-Z0-9]{20}', // Moldova
- 'ME': 'ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Montenegro
- 'MG': 'MG[0-9]{2}[0-9]{23}', // Madagascar
- 'MK': 'MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}', // Macedonia
- 'ML': 'ML[0-9]{2}[A-Z]{1}[0-9]{23}', // Mali
- 'MR': 'MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}', // Mauritania
- 'MT': 'MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}', // Malta
- 'MU': 'MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}',// Mauritius
- 'MZ': 'MZ[0-9]{2}[0-9]{21}', // Mozambique
- 'NL': 'NL[0-9]{2}[A-Z]{4}[0-9]{10}', // Netherlands
- 'NO': 'NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}', // Norway
- 'PK': 'PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', // Pakistan
- 'PL': 'PL[0-9]{2}[0-9]{8}[0-9]{16}', // Poland
- 'PS': 'PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', // Palestinian
- 'PT': 'PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}', // Portugal
- 'QA': 'QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', // Qatar
- 'RO': 'RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', // Romania
- 'RS': 'RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Serbia
- 'SA': 'SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}', // Saudi Arabia
- 'SE': 'SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}', // Sweden
- 'SI': 'SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}', // Slovenia
- 'SK': 'SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}', // Slovakia
- 'SM': 'SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', // San Marino
- 'SN': 'SN[0-9]{2}[A-Z]{1}[0-9]{23}', // Senegal
- 'TN': 'TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Tunisia
- 'TR': 'TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}', // Turkey
- 'VG': 'VG[0-9]{2}[A-Z]{4}[0-9]{16}' // Virgin Islands, British
+ AD: 'AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}', // Andorra
+ AE: 'AE[0-9]{2}[0-9]{3}[0-9]{16}', // United Arab Emirates
+ AL: 'AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}', // Albania
+ AO: 'AO[0-9]{2}[0-9]{21}', // Angola
+ AT: 'AT[0-9]{2}[0-9]{5}[0-9]{11}', // Austria
+ AZ: 'AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}', // Azerbaijan
+ BA: 'BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}', // Bosnia and Herzegovina
+ BE: 'BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}', // Belgium
+ BF: 'BF[0-9]{2}[0-9]{23}', // Burkina Faso
+ BG: 'BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}', // Bulgaria
+ BH: 'BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}', // Bahrain
+ BI: 'BI[0-9]{2}[0-9]{12}', // Burundi
+ BJ: 'BJ[0-9]{2}[A-Z]{1}[0-9]{23}', // Benin
+ BR: 'BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]', // Brazil
+ CH: 'CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}', // Switzerland
+ CI: 'CI[0-9]{2}[A-Z]{1}[0-9]{23}', // Ivory Coast
+ CM: 'CM[0-9]{2}[0-9]{23}', // Cameroon
+ CR: 'CR[0-9]{2}[0-9]{3}[0-9]{14}', // Costa Rica
+ CV: 'CV[0-9]{2}[0-9]{21}', // Cape Verde
+ CY: 'CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}', // Cyprus
+ CZ: 'CZ[0-9]{2}[0-9]{20}', // Czech Republic
+ DE: 'DE[0-9]{2}[0-9]{8}[0-9]{10}', // Germany
+ DK: 'DK[0-9]{2}[0-9]{14}', // Denmark
+ DO: 'DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}', // Dominican Republic
+ DZ: 'DZ[0-9]{2}[0-9]{20}', // Algeria
+ EE: 'EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}', // Estonia
+ ES: 'ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}', // Spain
+ FI: 'FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}', // Finland
+ FO: 'FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', // Faroe Islands
+ FR: 'FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', // France
+ GB: 'GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', // United Kingdom
+ GE: 'GE[0-9]{2}[A-Z]{2}[0-9]{16}', // Georgia
+ GI: 'GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}', // Gibraltar
+ GL: 'GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', // Greenland
+ GR: 'GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}', // Greece
+ GT: 'GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}', // Guatemala
+ HR: 'HR[0-9]{2}[0-9]{7}[0-9]{10}', // Croatia
+ HU: 'HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}', // Hungary
+ IE: 'IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', // Ireland
+ IL: 'IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}', // Israel
+ IR: 'IR[0-9]{2}[0-9]{22}', // Iran
+ IS: 'IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}', // Iceland
+ IT: 'IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', // Italy
+ JO: 'JO[0-9]{2}[A-Z]{4}[0-9]{4}[0]{8}[A-Z0-9]{10}', // Jordan
+ KW: 'KW[0-9]{2}[A-Z]{4}[0-9]{22}', // Kuwait
+ KZ: 'KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}', // Kazakhstan
+ LB: 'LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}', // Lebanon
+ LI: 'LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}', // Liechtenstein
+ LT: 'LT[0-9]{2}[0-9]{5}[0-9]{11}', // Lithuania
+ LU: 'LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}', // Luxembourg
+ LV: 'LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}', // Latvia
+ MC: 'MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', // Monaco
+ MD: 'MD[0-9]{2}[A-Z0-9]{20}', // Moldova
+ ME: 'ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Montenegro
+ MG: 'MG[0-9]{2}[0-9]{23}', // Madagascar
+ MK: 'MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}', // Macedonia
+ ML: 'ML[0-9]{2}[A-Z]{1}[0-9]{23}', // Mali
+ MR: 'MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}', // Mauritania
+ MT: 'MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}', // Malta
+ MU: 'MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}', // Mauritius
+ MZ: 'MZ[0-9]{2}[0-9]{21}', // Mozambique
+ NL: 'NL[0-9]{2}[A-Z]{4}[0-9]{10}', // Netherlands
+ NO: 'NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}', // Norway
+ PK: 'PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', // Pakistan
+ PL: 'PL[0-9]{2}[0-9]{8}[0-9]{16}', // Poland
+ PS: 'PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', // Palestinian
+ PT: 'PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}', // Portugal
+ QA: 'QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', // Qatar
+ RO: 'RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', // Romania
+ RS: 'RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Serbia
+ SA: 'SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}', // Saudi Arabia
+ SE: 'SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}', // Sweden
+ SI: 'SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}', // Slovenia
+ SK: 'SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}', // Slovakia
+ SM: 'SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', // San Marino
+ SN: 'SN[0-9]{2}[A-Z]{1}[0-9]{23}', // Senegal
+ TN: 'TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Tunisia
+ TR: 'TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}', // Turkey
+ VG: 'VG[0-9]{2}[A-Z]{4}[0-9]{16}' // Virgin Islands, British
},
/**
* Validate an International Bank Account Number (IBAN)
* To test it, take the sample IBAN from
@@ -3835,11 +3918,11 @@
if (value === '') {
return true;
}
var compareWith = validator.getFieldElements(options.field);
- if (compareWith === null) {
+ if (compareWith === null || compareWith.length === 0) {
return true;
}
if (value === compareWith.val()) {
validator.updateStatus(options.field, validator.STATUS_VALID, 'identical');
@@ -3893,10 +3976,55 @@
}
}
};
}(window.jQuery));
;(function($) {
+ $.fn.bootstrapValidator.i18n.imo = $.extend($.fn.bootstrapValidator.i18n.imo || {}, {
+ 'default': 'Please enter a valid IMO number'
+ });
+
+ $.fn.bootstrapValidator.validators.imo = {
+ /**
+ * Validate IMO (International Maritime Organization)
+ * Examples:
+ * - Valid: IMO 8814275, IMO 9176187
+ * - Invalid: IMO 8814274
+ *
+ * @see http://en.wikipedia.org/wiki/IMO_Number
+ * @param {BootstrapValidator} validator The validator plugin instance
+ * @param {jQuery} $field Field element
+ * @param {Object} options Can consist of the following keys:
+ * - message: The invalid message
+ * @returns {Boolean}
+ */
+ validate: function(validator, $field, options) {
+ var value = $field.val();
+ if (value === '') {
+ return true;
+ }
+
+ if (!/^IMO \d{7}$/i.test(value)) {
+ return false;
+ }
+
+ // Grab just the digits
+ var sum = 0,
+ digits = value.replace(/^.*(\d{7})$/, '$1');
+
+ // Go over each char, multiplying by the inverse of it's position
+ // IMO 9176187
+ // (9 * 7) + (1 * 6) + (7 * 5) + (6 * 4) + (1 * 3) + (8 * 2) = 147
+ // Take the last digit of that, that's the check digit (7)
+ for (var i = 6; i >= 1; i--) {
+ sum += (digits.slice((6 - i), -i) * (i + 1));
+ }
+
+ return sum % 10 === parseInt(digits.charAt(6), 10);
+ }
+ };
+}(window.jQuery));
+;(function($) {
$.fn.bootstrapValidator.i18n.integer = $.extend($.fn.bootstrapValidator.i18n.integer || {}, {
'default': 'Please enter a valid number'
});
$.fn.bootstrapValidator.validators.integer = {
@@ -3912,10 +4040,14 @@
* @param {Object} options Can consist of the following key:
* - message: The invalid message
* @returns {Boolean}
*/
validate: function(validator, $field, options) {
+ if (this.enableByHtml5($field) && $field.get(0).validity && $field.get(0).validity.badInput === true) {
+ return false;
+ }
+
var value = $field.val();
if (value === '') {
return true;
}
return /^(?:-?(?:0|[1-9][0-9]*))$/.test(value);
@@ -3952,27 +4084,41 @@
if (value === '') {
return true;
}
options = $.extend({}, { ipv4: true, ipv6: true }, options);
- if (options.ipv4) {
- return {
- 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),
- message: options.message || $.fn.bootstrapValidator.i18n.ip.ipv4
- };
- } else if (options.ipv6) {
- return {
- 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),
- message: options.message || $.fn.bootstrapValidator.i18n.ip.ipv6
- };
+ 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]?)$/,
+ 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*$/,
+ valid = false,
+ message;
+
+ switch (true) {
+ case (options.ipv4 && !options.ipv6):
+ valid = ipv4Regex.test(value);
+ message = options.message || $.fn.bootstrapValidator.i18n.ip.ipv4;
+ break;
+
+ case (!options.ipv4 && options.ipv6):
+ valid = ipv6Regex.test(value);
+ message = options.message || $.fn.bootstrapValidator.i18n.ip.ipv6;
+ break;
+
+ case (options.ipv4 && options.ipv6):
+ /* falls through */
+ default:
+ valid = ipv4Regex.test(value) && ipv6Regex.test(value);
+ message = options.message || $.fn.bootstrapValidator.i18n.ip['default'];
+ break;
}
- return false;
+ return {
+ valid: valid,
+ message: message
+ };
}
};
-}(window.jQuery));
-;(function($) {
+}(window.jQuery));;(function($) {
$.fn.bootstrapValidator.i18n.isbn = $.extend($.fn.bootstrapValidator.i18n.isbn || {}, {
'default': 'Please enter a valid ISBN number'
});
$.fn.bootstrapValidator.validators.isbn = {
@@ -4232,12 +4378,13 @@
value: 'value',
inclusive: 'inclusive'
},
enableByHtml5: function($field) {
- var max = $field.attr('max');
- if (max) {
+ var type = $field.attr('type'),
+ max = $field.attr('max');
+ if (max && type !== 'date') {
return {
value: max
};
}
@@ -4263,13 +4410,15 @@
validate: function(validator, $field, options) {
var value = $field.val();
if (value === '') {
return true;
}
+ if (!$.isNumeric(value)) {
+ return false;
+ }
var compareTo = $.isNumeric(options.value) ? options.value : validator.getDynamicOption($field, options.value);
-
value = parseFloat(value);
return (options.inclusive === true || options.inclusive === undefined)
? {
valid: value <= compareTo,
message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.lessThan['default'], compareTo)
@@ -4305,10 +4454,93 @@
return /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value);
}
};
}(window.jQuery));
;(function($) {
+ $.fn.bootstrapValidator.i18n.meid = $.extend($.fn.bootstrapValidator.i18n.meid || {}, {
+ 'default': 'Please enter a valid MEID number'
+ });
+
+ $.fn.bootstrapValidator.validators.meid = {
+ /**
+ * Validate MEID (Mobile Equipment Identifier)
+ * Examples:
+ * - Valid: 293608736500703710, 29360-87365-0070-3710, AF0123450ABCDE, AF-012345-0ABCDE
+ * - Invalid: 2936087365007037101
+ *
+ * @see http://en.wikipedia.org/wiki/Mobile_equipment_identifier
+ * @param {BootstrapValidator} validator The validator plugin instance
+ * @param {jQuery} $field Field element
+ * @param {Object} options Can consist of the following keys:
+ * - message: The invalid message
+ * @returns {Boolean}
+ */
+ validate: function(validator, $field, options) {
+ var value = $field.val();
+ if (value === '') {
+ return true;
+ }
+
+ switch (true) {
+ // 14 digit hex representation (no check digit)
+ case /^[0-9A-F]{15}$/i.test(value):
+ // 14 digit hex representation + dashes or spaces (no check digit)
+ case /^[0-9A-F]{2}[- ][0-9A-F]{6}[- ][0-9A-F]{6}[- ][0-9A-F]$/i.test(value):
+ // 18 digit decimal representation (no check digit)
+ case /^\d{19}$/.test(value):
+ // 18 digit decimal representation + dashes or spaces (no check digit)
+ case /^\d{5}[- ]\d{5}[- ]\d{4}[- ]\d{4}[- ]\d$/.test(value):
+ // Grab the check digit
+ var cd = value.charAt(value.length - 1);
+
+ // Strip any non-hex chars
+ value = value.replace(/[- ]/g, '');
+
+ // If it's all digits, luhn base 10 is used
+ if (value.match(/^\d*$/i)) {
+ return $.fn.bootstrapValidator.helpers.luhn(value);
+ }
+
+ // Strip the check digit
+ value = value.slice(0, -1);
+
+ // Get every other char, and double it
+ var cdCalc = '';
+ for (var i = 1; i <= 13; i += 2) {
+ cdCalc += (parseInt(value.charAt(i), 16) * 2).toString(16);
+ }
+
+ // Get the sum of each char in the string
+ var sum = 0;
+ for (i = 0; i < cdCalc.length; i++) {
+ sum += parseInt(cdCalc.charAt(i), 16);
+ }
+
+ // If the last digit of the calc is 0, the check digit is 0
+ return (sum % 10 === 0)
+ ? (cd === '0')
+ // Subtract it from the next highest 10s number (64 goes to 70) and subtract the sum
+ // Double it and turn it into a hex char
+ : (cd === ((Math.floor((sum + 10) / 10) * 10 - sum) * 2).toString(16));
+
+ // 14 digit hex representation (no check digit)
+ case /^[0-9A-F]{14}$/i.test(value):
+ // 14 digit hex representation + dashes or spaces (no check digit)
+ case /^[0-9A-F]{2}[- ][0-9A-F]{6}[- ][0-9A-F]{6}$/i.test(value):
+ // 18 digit decimal representation (no check digit)
+ case /^\d{18}$/.test(value):
+ // 18 digit decimal representation + dashes or spaces (no check digit)
+ case /^\d{5}[- ]\d{5}[- ]\d{4}[- ]\d{4}$/.test(value):
+ return true;
+
+ default:
+ return false;
+ }
+ }
+ };
+}(window.jQuery));
+;(function($) {
$.fn.bootstrapValidator.i18n.notEmpty = $.extend($.fn.bootstrapValidator.i18n.notEmpty || {}, {
'default': 'Please enter a value'
});
$.fn.bootstrapValidator.validators.notEmpty = {
@@ -4362,10 +4594,14 @@
* - message: The invalid message
* - separator: The decimal separator. Can be "." (default), ","
* @returns {Boolean}
*/
validate: function(validator, $field, options) {
+ if (this.enableByHtml5($field) && $field.get(0).validity && $field.get(0).validity.badInput === true) {
+ return false;
+ }
+
var value = $field.val();
if (value === '') {
return true;
}
var separator = options.separator || '.';
@@ -4381,11 +4617,16 @@
$.fn.bootstrapValidator.i18n.phone = $.extend($.fn.bootstrapValidator.i18n.phone || {}, {
'default': 'Please enter a valid phone number',
countryNotSupported: 'The country code %s is not supported',
country: 'Please enter a valid phone number in %s',
countries: {
+ BR: 'Brazil',
+ ES: 'Spain',
+ FR: 'France',
GB: 'United Kingdom',
+ MA: 'Morocco',
+ PK: 'Pakistan',
US: 'USA'
}
});
$.fn.bootstrapValidator.validators.phone = {
@@ -4393,11 +4634,11 @@
message: 'message',
country: 'country'
},
// The supported countries
- COUNTRY_CODES: ['GB', 'US'],
+ COUNTRY_CODES: ['BR', 'ES', 'FR', 'GB', 'MA', 'PK', 'US'],
/**
* Return true if the input value contains a valid phone number for the country
* selected in the options
*
@@ -4409,11 +4650,10 @@
* - A country code
* - Name of field which its value defines the country code
* - Name of callback function that returns the country code
* - A callback function that returns the country code
*
- * Currently it only supports United State (US) or United Kingdom (GB) countries
* @returns {Boolean|Object}
*/
validate: function(validator, $field, options) {
var value = $field.val();
if (value === '') {
@@ -4433,17 +4673,48 @@
};
}
var isValid = true;
switch (country.toUpperCase()) {
+ case 'BR':
+ // Test: http://regexr.com/399m1
+ value = $.trim(value);
+ 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);
+ break;
+
+ case 'ES':
+ // http://regex101.com/r/rB9mA9/1
+ value = $.trim(value);
+ isValid = (/^(?:(?:(?:\+|00)34\D?))?(?:9|6)(?:\d\D?){8}$/).test(value);
+ break;
+
+ case 'FR':
+ // http://regexr.com/39a2p
+ value = $.trim(value);
+ isValid = (/^(?:(?:(?:\+|00)33[ ]?(?:\(0\)[ ]?)?)|0){1}[1-9]{1}([ .-]?)(?:\d{2}\1?){3}\d{2}$/).test(value);
+ break;
+
case 'GB':
// http://aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers#Match_GB_telephone_number_in_any_format
// Test: http://regexr.com/38uhv
value = $.trim(value);
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);
break;
+ case 'MA':
+ // http://en.wikipedia.org/wiki/Telephone_numbers_in_Morocco
+ // Test: http://regexr.com/399n8
+ value = $.trim(value);
+ 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);
+ break;
+
+ case 'PK':
+ // http://regex101.com/r/yH8aV9/2
+ value = $.trim(value);
+ isValid = (/^0?3[0-9]{2}[0-9]{7}$/).test(value);
+ break;
+
case 'US':
/* falls through */
default:
// Make sure US phone numbers have 10 digits
// May start with 1, +1, or 1-; should discard
@@ -4509,12 +4780,13 @@
});
$.fn.bootstrapValidator.validators.remote = {
html5Attributes: {
message: 'message',
- url: 'url',
- name: 'name'
+ name: 'name',
+ type: 'type',
+ url: 'url'
},
/**
* Request a remote server to check the input value
*
@@ -4527,22 +4799,24 @@
* {
* <fieldName>: <fieldValue>
* }
* - name {String} [optional]: Override the field name for the request.
* - message: The invalid message
+ * - headers: Additional headers
* @returns {Boolean|Deferred}
*/
validate: function(validator, $field, options) {
var value = $field.val();
if (value === '') {
return true;
}
- var name = $field.attr('data-bv-field'),
- data = options.data || {},
- url = options.url,
- type = options.type || 'POST';
+ var name = $field.attr('data-bv-field'),
+ data = options.data || {},
+ url = options.url,
+ type = options.type || 'POST',
+ headers = options.headers || {};
// Support dynamic data
if ('function' === typeof data) {
data = data.call(this, validator);
}
@@ -4555,10 +4829,11 @@
data[options.name || name] = value;
var dfd = new $.Deferred();
var xhr = $.ajax({
type: type,
+ headers: headers,
url: url,
dataType: 'json',
data: data
});
xhr.then(function(response) {
@@ -4944,20 +5219,21 @@
// http://mathiasbynens.be/demo/url-regex
//
// Notes on possible differences from a standard/generic validation:
//
// - utf-8 char class take in consideration the full Unicode range
- // - TLDs have been made mandatory so single names like "localhost" fails
+ // - TLDs are mandatory unless `allowLocal` is true
// - protocols have been restricted to ftp, http and https only as requested
//
// Changes:
//
// - IP address dotted notation validation, range: 1.0.0.0 - 223.255.255.255
// first and last IP address of each class is considered invalid
// (since they are broadcast/network addresses)
//
// - Added exclusion of private, reserved and/or local networks ranges
+ // unless `allowLocal` is true
//
var allowLocal = options.allowLocal === true || options.allowLocal === 'true',
urlExp = new RegExp(
"^" +
// protocol identifier
@@ -4985,10 +5261,12 @@
"(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)" +
// domain name
"(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*" +
// TLD identifier
"(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
+ // Allow intranet sites (no TLD) if `allowLocal` is true
+ (allowLocal ? '?' : '') +
")" +
// port number
"(?::\\d{2,5})?" +
// resource path
"(?:/[^\\s]*)?" +
@@ -5052,10 +5330,11 @@
country: 'Please enter a valid %s VAT number',
countries: {
AT: 'Austrian',
BE: 'Belgian',
BG: 'Bulgarian',
+ BR: 'Brazilian',
CH: 'Swiss',
CY: 'Cypriot',
CZ: 'Czech',
DE: 'German',
DK: 'Danish',
@@ -5067,10 +5346,11 @@
GR: 'Greek',
EL: 'Greek',
HU: 'Hungarian',
HR: 'Croatian',
IE: 'Irish',
+ IS: 'Iceland',
IT: 'Italian',
LT: 'Lithuanian',
LU: 'Luxembourg',
LV: 'Latvian',
MT: 'Maltese',
@@ -5081,11 +5361,12 @@
RO: 'Romanian',
RU: 'Russian',
RS: 'Serbian',
SE: 'Swedish',
SI: 'Slovenian',
- SK: 'Slovak'
+ SK: 'Slovak',
+ ZA: 'South African'
}
});
$.fn.bootstrapValidator.validators.vat = {
html5Attributes: {
@@ -5093,12 +5374,12 @@
country: 'country'
},
// Supported country codes
COUNTRY_CODES: [
- 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'EL', 'HU', 'IE', 'IT',
- 'LV', 'LT', 'LU', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'RS', 'SK', 'SI', 'ES', 'SE', 'CH', 'GB'
+ 'AT', 'BE', 'BG', 'BR', 'CH', 'CY', 'CZ', 'DE', 'DK', 'EE', 'EL', 'ES', 'FI', 'FR', 'GB', 'GR', 'HR', 'HU',
+ 'IE', 'IS', 'IT', 'LT', 'LU', 'LV', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'RS', 'SE', 'SK', 'SI', 'ZA'
],
/**
* Validate an European VAT number
*
@@ -5299,11 +5580,69 @@
return (egn(value) || pnf(value) || vat(value));
}
return false;
},
+
+ /**
+ * Validate Brazilian VAT number (CNPJ)
+ *
+ * @param {String} value VAT number
+ * @returns {Boolean}
+ */
+ _br: function(value) {
+ if (value === '') {
+ return true;
+ }
+ var cnpj = value.replace(/[^\d]+/g, '');
+ if (cnpj === '' || cnpj.length !== 14) {
+ return false;
+ }
+ // Remove invalids CNPJs
+ if (cnpj === '00000000000000' || cnpj === '11111111111111' || cnpj === '22222222222222' ||
+ cnpj === '33333333333333' || cnpj === '44444444444444' || cnpj === '55555555555555' ||
+ cnpj === '66666666666666' || cnpj === '77777777777777' || cnpj === '88888888888888' ||
+ cnpj === '99999999999999')
+ {
+ return false;
+ }
+
+ // Validate verification digits
+ var length = cnpj.length - 2,
+ numbers = cnpj.substring(0, length),
+ digits = cnpj.substring(length),
+ sum = 0,
+ pos = length - 7;
+
+ for (var i = length; i >= 1; i--) {
+ sum += parseInt(numbers.charAt(length - i), 10) * pos--;
+ if (pos < 2) {
+ pos = 9;
+ }
+ }
+
+ var result = sum % 11 < 2 ? 0 : 11 - sum % 11;
+ if (result !== parseInt(digits.charAt(0), 10)) {
+ return false;
+ }
+
+ length = length + 1;
+ numbers = cnpj.substring(0, length);
+ sum = 0;
+ pos = length - 7;
+ for (i = length; i >= 1; i--) {
+ sum += parseInt(numbers.charAt(length - i), 10) * pos--;
+ if (pos < 2) {
+ pos = 9;
+ }
+ }
+
+ result = sum % 11 < 2 ? 0 : 11 - sum % 11;
+ return (result === parseInt(digits.charAt(1), 10));
+ },
+
/**
* Validate Swiss VAT number
*
* @param {String} value VAT number
* @returns {Boolean}
@@ -5639,11 +5978,11 @@
return false;
}
value = value.substr(2);
- if (!$.fn.bootstrapValidator.helpers.luhn(value.substr(2))) {
+ if (!$.fn.bootstrapValidator.helpers.luhn(value.substr(2))) {
return false;
}
if (/^[0-9]{2}$/.test(value.substr(0, 2))) {
// First two characters are digits
@@ -5833,10 +6172,23 @@
return true;
},
/**
+ * Validate Icelandic VAT (VSK) number
+ * Examples:
+ * - Valid: 12345, 123456
+ * - Invalid: 1234567
+ *
+ * @params {String} value VAT number
+ * @returns {Boolean}
+ */
+ _is: function(value) {
+ return /^IS\d{5,6}$/.test(value);
+ },
+
+ /**
* Validate Italian VAT number, which consists of 11 digits.
* - First 7 digits are a company identifier
* - Next 3 are the province of residence
* - The last one is a check digit
*
@@ -6260,10 +6612,23 @@
if (!/^SK[1-9][0-9][(2-4)|(6-9)][0-9]{7}$/.test(value)) {
return false;
}
return (parseInt(value.substr(2), 10) % 11 === 0);
+ },
+
+ /**
+ * Validate South African VAT number
+ * Examples:
+ * - Valid: 4012345678
+ * - Invalid: 40123456789, 3012345678
+ *
+ * @params {String} value VAT number
+ * @returns {Boolean}
+ */
+ _za: function(value) {
+ return /^ZA4\d{9}$/.test(value);
}
};
}(window.jQuery));
;(function($) {
$.fn.bootstrapValidator.i18n.vin = $.extend($.fn.bootstrapValidator.i18n.vin || {}, {
@@ -6318,28 +6683,30 @@
$.fn.bootstrapValidator.i18n.zipCode = $.extend($.fn.bootstrapValidator.i18n.zipCode || {}, {
'default': 'Please enter a valid zip code',
countryNotSupported: 'The country code %s is not supported',
country: 'Please enter a valid %s',
countries: {
- 'CA': 'Canadian postal code',
- 'DK': 'Danish postal code',
- 'GB': 'United Kingdom postal code',
- 'IT': 'Italian postal code',
- 'NL': 'Dutch postal code',
- 'SE': 'Swiss postal code',
- 'SG': 'Singapore postal code',
- 'US': 'US zip code'
+ BR: 'Brazilian postal code',
+ CA: 'Canadian postal code',
+ DK: 'Danish postal code',
+ GB: 'United Kingdom postal code',
+ IT: 'Italian postal code',
+ MA: 'Moroccan postal code',
+ NL: 'Dutch postal code',
+ SE: 'Swiss postal code',
+ SG: 'Singapore postal code',
+ US: 'US zip code'
}
});
$.fn.bootstrapValidator.validators.zipCode = {
html5Attributes: {
message: 'message',
country: 'country'
},
- COUNTRY_CODES: ['CA', 'DK', 'GB', 'IT', 'NL', 'SE', 'SG', 'US'],
+ COUNTRY_CODES: ['BR', 'CA', 'DK', 'GB', 'IT', 'MA', 'NL', 'SE', 'SG', 'US'],
/**
* Return true if and only if the input value is a valid country zip code
*
* @param {BootstrapValidator} validator The validator plugin instance
@@ -6348,20 +6715,10 @@
* - message: The invalid message
* - country: The country
*
* The country can be defined by:
* - An ISO 3166 country code
- * Currently it supports the following countries:
- * - US (United States)
- * - CA (Canada)
- * - DK (Denmark)
- * - GB (United Kingdom)
- * - IT (Italy)
- * - NL (Netherlands)
- * - SE (Sweden)
- * - SG (Singapore)
- *
* - Name of field which its value defines the country code
* - Name of callback function that returns the country code
* - A callback function that returns the country code
*
* callback: function(value, validator, $field) {
@@ -6389,10 +6746,14 @@
}
var isValid = false;
country = country.toUpperCase();
switch (country) {
+ case 'BR':
+ isValid = /^(\d{2})([\.]?)(\d{3})([\-]?)(\d{3})$/.test(value);
+ break;
+
case 'CA':
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);
break;
case 'DK':
@@ -6406,10 +6767,15 @@
// http://en.wikipedia.org/wiki/List_of_postal_codes_in_Italy
case 'IT':
isValid = /^(I-|IT-)?\d{5}$/i.test(value);
break;
+ // http://en.wikipedia.org/wiki/List_of_postal_codes_in_Morocco
+ case 'MA':
+ isValid = /^[1-9][0-9]{4}$/i.test(value);
+ break;
+
// http://en.wikipedia.org/wiki/Postal_codes_in_the_Netherlands
case 'NL':
isValid = /^[1-9][0-9]{3} ?(?!sa|sd|ss)[a-z]{2}$/i.test(value);
break;
@@ -6417,11 +6783,11 @@
isValid = /^(S-)?\d{3}\s?\d{2}$/i.test(value);
break;
case 'SG':
isValid = /^([0][1-9]|[1-6][0-9]|[7]([0-3]|[5-9])|[8][0-2])(\d{4})$/i.test(value);
- break;
-
+ break;
+
case 'US':
/* falls through */
default:
isValid = /^\d{4,5}([\-]?\d{4})?$/.test(value);
break;