From 36dde68f440565033d9b50be25da7b4071a116a6 Mon Sep 17 00:00:00 2001 From: Peter Dave Hello Date: Sun, 7 Sep 2014 14:30:25 +0800 Subject: [PATCH] add jquery.bootstrapvalidator v0.1.0~0.4.5 --- .../0.1.0/css/bootstrapValidator.css | 11 + .../0.1.0/css/bootstrapValidator.min.css | 12 + .../0.1.0/css/bootstrapValidator.scss | 15 + .../0.1.0/js/bootstrapValidator.js | 627 +++ .../0.1.0/js/bootstrapValidator.min.js | 11 + .../0.1.1/css/bootstrapValidator.css | 11 + .../0.1.1/css/bootstrapValidator.min.css | 12 + .../0.1.1/css/bootstrapValidator.scss | 15 + .../0.1.1/js/bootstrapValidator.js | 631 +++ .../0.1.1/js/bootstrapValidator.min.js | 11 + .../0.2.0/css/bootstrapValidator.css | 11 + .../0.2.0/css/bootstrapValidator.min.css | 12 + .../0.2.0/css/bootstrapValidator.scss | 15 + .../0.2.0/js/bootstrapValidator.js | 778 +++ .../0.2.0/js/bootstrapValidator.min.js | 11 + .../0.2.1/css/bootstrapValidator.css | 11 + .../0.2.1/css/bootstrapValidator.min.css | 12 + .../0.2.1/css/bootstrapValidator.scss | 15 + .../0.2.1/js/bootstrapValidator.js | 778 +++ .../0.2.1/js/bootstrapValidator.min.js | 11 + .../0.2.2/css/bootstrapValidator.css | 11 + .../0.2.2/css/bootstrapValidator.min.css | 12 + .../0.2.2/css/bootstrapValidator.scss | 15 + .../0.2.2/js/bootstrapValidator.js | 853 +++ .../0.2.2/js/bootstrapValidator.min.js | 11 + .../0.3.0/css/bootstrapValidator.css | 11 + .../0.3.0/css/bootstrapValidator.min.css | 13 + .../0.3.0/css/bootstrapValidator.scss | 15 + .../0.3.0/js/bootstrapValidator.js | 1050 ++++ .../0.3.0/js/bootstrapValidator.min.js | 12 + .../0.3.1/css/bootstrapValidator.css | 11 + .../0.3.1/css/bootstrapValidator.min.css | 13 + .../0.3.1/css/bootstrapValidator.scss | 15 + .../0.3.1/js/bootstrapValidator.js | 1198 ++++ .../0.3.1/js/bootstrapValidator.min.js | 12 + .../0.3.2/css/bootstrapValidator.css | 13 + .../0.3.2/css/bootstrapValidator.min.css | 13 + .../0.3.2/js/bootstrapValidator.js | 1598 ++++++ .../0.3.2/js/bootstrapValidator.min.js | 12 + .../0.3.3/css/bootstrapValidator.css | 13 + .../0.3.3/css/bootstrapValidator.min.css | 13 + .../0.3.3/js/bootstrapValidator.js | 1600 ++++++ .../0.3.3/js/bootstrapValidator.min.js | 12 + .../0.4.0/css/bootstrapValidator.css | 13 + .../0.4.0/css/bootstrapValidator.min.css | 13 + .../0.4.0/js/bootstrapValidator.js | 2185 ++++++++ .../0.4.0/js/bootstrapValidator.min.js | 12 + .../0.4.1/css/bootstrapValidator.css | 13 + .../0.4.1/css/bootstrapValidator.min.css | 13 + .../0.4.1/js/bootstrapValidator.js | 2212 ++++++++ .../0.4.1/js/bootstrapValidator.min.js | 12 + .../0.4.2/css/bootstrapValidator.css | 13 + .../0.4.2/css/bootstrapValidator.min.css | 13 + .../0.4.2/js/bootstrapValidator.js | 2382 ++++++++ .../0.4.2/js/bootstrapValidator.min.js | 12 + .../0.4.3/css/bootstrapValidator.css | 13 + .../0.4.3/css/bootstrapValidator.min.css | 13 + .../0.4.3/js/bootstrapValidator.js | 3672 ++++++++++++ .../0.4.3/js/bootstrapValidator.min.js | 13 + .../0.4.4/css/bootstrapValidator.css | 19 + .../0.4.4/css/bootstrapValidator.min.css | 13 + .../0.4.4/js/bootstrapValidator.js | 3952 +++++++++++++ .../0.4.4/js/bootstrapValidator.min.js | 13 + .../0.4.5/css/bootstrapValidator.css | 19 + .../0.4.5/css/bootstrapValidator.min.css | 13 + .../0.4.5/js/bootstrapValidator.js | 4967 +++++++++++++++++ .../0.4.5/js/bootstrapValidator.min.js | 13 + 67 files changed, 29149 insertions(+) create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.1.0/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.1.0/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.1.0/css/bootstrapValidator.scss create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.1.0/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.1.0/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.1.1/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.1.1/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.1.1/css/bootstrapValidator.scss create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.1.1/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.1.1/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.0/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.0/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.0/css/bootstrapValidator.scss create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.0/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.0/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.1/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.1/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.1/css/bootstrapValidator.scss create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.1/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.1/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.2/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.2/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.2/css/bootstrapValidator.scss create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.2/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.2.2/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.0/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.0/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.0/css/bootstrapValidator.scss create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.0/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.0/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.1/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.1/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.1/css/bootstrapValidator.scss create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.1/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.1/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.2/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.2/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.2/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.2/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.3/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.3/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.3/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.3.3/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.0/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.0/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.0/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.0/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.1/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.1/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.1/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.1/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.2/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.2/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.2/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.2/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.3/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.3/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.3/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.3/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.4/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.4/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.4/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.4/js/bootstrapValidator.min.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.5/css/bootstrapValidator.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.5/css/bootstrapValidator.min.css create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.5/js/bootstrapValidator.js create mode 100644 ajax/libs/jquery.bootstrapvalidator/0.4.5/js/bootstrapValidator.min.js diff --git a/ajax/libs/jquery.bootstrapvalidator/0.1.0/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.1.0/css/bootstrapValidator.css new file mode 100644 index 000000000..81862c312 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.1.0/css/bootstrapValidator.css @@ -0,0 +1,11 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ +.bootstrap-validator-form .help-block { + margin-bottom: 0; } diff --git a/ajax/libs/jquery.bootstrapvalidator/0.1.0/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.1.0/css/bootstrapValidator.min.css new file mode 100644 index 000000000..885db98ab --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.1.0/css/bootstrapValidator.min.css @@ -0,0 +1,12 @@ +/** + * BootstrapValidator v0.1.0 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.1.0/css/bootstrapValidator.scss b/ajax/libs/jquery.bootstrapvalidator/0.1.0/css/bootstrapValidator.scss new file mode 100644 index 000000000..d2f6229dc --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.1.0/css/bootstrapValidator.scss @@ -0,0 +1,15 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form { + .help-block { + margin-bottom: 0; + } +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.1.0/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.1.0/js/bootstrapValidator.js new file mode 100644 index 000000000..c4fb0562a --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.1.0/js/bootstrapValidator.js @@ -0,0 +1,627 @@ +/** + * BootstrapValidator v0.1.0 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + this.invalidFields = {}; + this.xhrRequests = {}; + this.numPendingRequests = null; + this.formSubmited = false; + + this._init(); + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // The submit buttons selector + // These buttons will be disabled when the form input are invalid + submitButtons: 'button[type="submit"]', + + // Map the field name with validator rules + fields: null + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + if (this.options.fields == null) { + return; + } + + var that = this; + this.$form + .addClass(this.options.elementClass) + .on('submit', function(e) { + that.formSubmited = true; + if (that.options.fields) { + for (var field in that.options.fields) { + if (that.numPendingRequests > 0 || that.numPendingRequests == null) { + // Check if the field is valid + var $field = that.getFieldElement(field); + if ($field.data('bootstrapValidator.isValid') !== true) { + that.validateField(field); + } + } + } + if (!that.isValid()) { + that.$form.find(that.options.submitButtons).attr('disabled', 'disabled'); + e.preventDefault(); + } + } + }); + + for (var field in this.options.fields) { + this._initField(field); + } + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + var $field = this.getFieldElement(field); + if (null == $field) { + return; + } + + // Create a help block element for showing the error + var that = this, + $parent = $field.parents('.form-group'), + helpBlock = $parent.find('.help-block'); + + if (helpBlock.length == 0) { + var $small = $('').addClass('help-block').appendTo($parent); + $field.data('bootstrapValidator.error', $small); + + // Calculate the number of columns of the label/field element + // Then set offset to the help block element + var label, cssClasses, offset; + if (label = $parent.find('label').get(0)) { + cssClasses = $(label).attr('class').split(' '); + for (var i = 0; i < cssClasses.length; i++) { + if (cssClasses[i].substr(0, 7) == 'col-lg-') { + offset = cssClasses[i].substr(7); + break; + } + } + } else { + cssClasses = $parent.children().eq(0).attr('class').split(' '); + for (var i = 0; i < cssClasses.length; i++) { + if (cssClasses[i].substr(0, 14) == 'col-lg-offset-') { + offset = cssClasses[i].substr(14); + break; + } + } + } + $small.addClass('col-lg-offset-' + offset).addClass('col-lg-' + parseInt(12 - offset)); + } else { + $field.data('bootstrapValidator.error', helpBlock.eq(0)); + } + + var type = $field.attr('type'), + event = ('checkbox' == type || 'radio' == type) ? 'change' : 'keyup'; + $field.on(event, function() { + that.formSubmited = false; + that.validateField(field); + }); + }, + + /** + * Get field element + * + * @param {String} field The field name + * @returns {jQuery} + */ + getFieldElement: function(field) { + var fields = this.$form.find('[name="' + field + '"]'); + return (fields.length == 0) ? null : $(fields[0]); + }, + + /** + * Validate given field + * + * @param {String} field The field name + */ + validateField: function(field) { + var $field = this.getFieldElement(field); + if (null == $field) { + // Return if cannot find the field with given name + return; + } + var that = this, + validators = that.options.fields[field].validators; + for (var validatorName in validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + continue; + } + var isValid = $.fn.bootstrapValidator.validators[validatorName].validate(that, $field, validators[validatorName]); + if (isValid === false) { + that.showError($field, validatorName); + break; + } else if (isValid === true) { + that.removeError($field); + } + } + }, + + /** + * Show field error + * + * @param {jQuery} $field The field element + * @param {String} validatorName + */ + showError: function($field, validatorName) { + var field = $field.attr('name'), + validator = this.options.fields[field].validators[validatorName], + message = validator.message || this.options.message, + $parent = $field.parents('.form-group'); + + this.invalidFields[field] = true; + + // Add has-error class to parent element + $parent.removeClass('has-success').addClass('has-error'); + + $field.data('bootstrapValidator.error').html(message).show(); + + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + }, + + /** + * Remove error from given field + * + * @param {jQuery} $field The field element + */ + removeError: function($field) { + delete this.invalidFields[$field.attr('name')]; + $field.parents('.form-group').removeClass('has-error').addClass('has-success'); + $field.data('bootstrapValidator.error').hide(); + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + }, + + /** + * Start remote checking + * + * @param {jQuery} $field The field element + * @param {String} validatorName + * @param {XMLHttpRequest} xhr + */ + startRequest: function($field, validatorName, xhr) { + var field = $field.attr('name'); + + $field.data('bootstrapValidator.isValid', false); + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + + if(this.numPendingRequests == null){ + this.numPendingRequests = 0; + } + this.numPendingRequests++; + // Abort the previous request + if (!this.xhrRequests[field]) { + this.xhrRequests[field] = {}; + } + + if (this.xhrRequests[field][validatorName]) { + this.numPendingRequests--; + this.xhrRequests[field][validatorName].abort(); + } + this.xhrRequests[field][validatorName] = xhr; + }, + + /** + * Complete remote checking + * + * @param {jQuery} $field The field element + * @param {String} validatorName + * @param {boolean} isValid + */ + completeRequest: function($field, validatorName, isValid) { + if (isValid === false) { + this.showError($field, validatorName); + } else if (isValid === true) { + this.removeError($field); + $field.data('bootstrapValidator.isValid', true); + } + + var field = $field.attr('name'); + + delete this.xhrRequests[field][validatorName]; + + this.numPendingRequests--; + if (this.numPendingRequests <= 0) { + this.numPendingRequests = 0; + if (this.formSubmited) { + this.$form.submit(); + } + } + }, + + /** + * Check the form validity + * + * @returns {boolean} + */ + isValid: function() { + if (this.numPendingRequests > 0) { + return false; + } + for (var field in this.invalidFields) { + if (this.invalidFields[field]) { + return false; + } + } + return true; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(options) { + return this.each(function() { + var $this = $(this), data = $this.data('bootstrapValidator'); + if (!data) { + $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options))); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = parseFloat($field.val()); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + return /^\d+$/.test($field.val()); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(), + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = parseFloat($field.val()); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + /** + * Return true if the input value is a valid hex color + * + * @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(); + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(), + $compareWith = validator.getFieldElement(options.field); + if ($compareWith && value == $compareWith.val()) { + validator.removeError($compareWith); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = parseFloat($field.val()); + return (options.inclusive === true) ? (value < options.value) : (value <= options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + return ('checkbox' == type || 'radio' == type) ? $field.is(':checked') : ($.trim($field.val()) != ''); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + return value.match(options.regexp); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.remote = { + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - message: The invalid message + * @returns {string} + */ + validate: function(validator, $field, options) { + var value = $field.val(), name = $field.attr('name'), data = options.data; + if (data == null) { + data = {}; + data[name] = value; + } + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }).success(function(response) { + var isValid = response.valid === true || response.valid === 'true'; + validator.completeRequest($field, 'remote', isValid); + }); + validator.startRequest($field, 'remote', xhr); + + return 'pending'; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $.trim($field.val()), length = value.length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test($field.val()); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.usZipCode = { + /** + * Return true if and only if the input value is a valid US zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validateInstance, $field, options) { + var value = $field.val(); + return /^\d{5}([\-]\d{4})?$/.test(value); + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.1.0/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.1.0/js/bootstrapValidator.min.js new file mode 100644 index 000000000..d6830156b --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.1.0/js/bootstrapValidator.min.js @@ -0,0 +1,11 @@ +/** + * BootstrapValidator v0.1.0 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),this.invalidFields={},this.xhrRequests={},this.numPendingRequests=null,this.formSubmited=!1,this._init()};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",submitButtons:'button[type="submit"]',fields:null},b.prototype={constructor:b,_init:function(){if(null!=this.options.fields){var a=this;this.$form.addClass(this.options.elementClass).on("submit",function(b){if(a.formSubmited=!0,a.options.fields){for(var c in a.options.fields)if(a.numPendingRequests>0||null==a.numPendingRequests){var d=a.getFieldElement(c);d.data("bootstrapValidator.isValid")!==!0&&a.validateField(c)}a.isValid()||(a.$form.find(a.options.submitButtons).attr("disabled","disabled"),b.preventDefault())}});for(var b in this.options.fields)this._initField(b)}},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){var c=this.getFieldElement(b);if(null!=c){var d=this,e=c.parents(".form-group"),f=e.find(".help-block");if(0==f.length){var g=a("").addClass("help-block").appendTo(e);c.data("bootstrapValidator.error",g);var h,i,j;if(h=e.find("label").get(0)){i=a(h).attr("class").split(" ");for(var k=0;k0)return!1;for(var a in this.invalidFields)if(this.invalidFields[a])return!1;return!0}},a.fn.bootstrapValidator=function(c){return this.each(function(){var d=a(this),e=d.data("bootstrapValidator");e||d.data("bootstrapValidator",e=new b(this,c))})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={validate:function(a,b,c){var d=parseFloat(b.val());return c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){return/^\d+$/.test(b.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={validate:function(a,b){var c=b.val(),d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={validate:function(a,b,c){var d=parseFloat(b.val());return c.inclusive===!0?d>c.value:d>=c.value}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={validate:function(a,b){var c=b.val();return/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={validate:function(a,b,c){var d=b.val(),e=a.getFieldElement(c.field);return e&&d==e.val()?(a.removeError(e),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={validate:function(a,b,c){var d=parseFloat(b.val());return c.inclusive===!0?dd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={validate:function(a,b){var c=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return c.test(b.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.usZipCode={validate:function(a,b){var c=b.val();return/^\d{5}([\-]\d{4})?$/.test(c)}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.1.1/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.1.1/css/bootstrapValidator.css new file mode 100644 index 000000000..81862c312 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.1.1/css/bootstrapValidator.css @@ -0,0 +1,11 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ +.bootstrap-validator-form .help-block { + margin-bottom: 0; } diff --git a/ajax/libs/jquery.bootstrapvalidator/0.1.1/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.1.1/css/bootstrapValidator.min.css new file mode 100644 index 000000000..165caf3d3 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.1.1/css/bootstrapValidator.min.css @@ -0,0 +1,12 @@ +/** + * BootstrapValidator v0.1.1 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.1.1/css/bootstrapValidator.scss b/ajax/libs/jquery.bootstrapvalidator/0.1.1/css/bootstrapValidator.scss new file mode 100644 index 000000000..d2f6229dc --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.1.1/css/bootstrapValidator.scss @@ -0,0 +1,15 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form { + .help-block { + margin-bottom: 0; + } +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.1.1/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.1.1/js/bootstrapValidator.js new file mode 100644 index 000000000..e056ca165 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.1.1/js/bootstrapValidator.js @@ -0,0 +1,631 @@ +/** + * BootstrapValidator v0.1.1 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + this.invalidFields = {}; + this.xhrRequests = {}; + this.numPendingRequests = null; + this.formSubmited = false; + + this._init(); + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // The submit buttons selector + // These buttons will be disabled when the form input are invalid + submitButtons: 'button[type="submit"]', + + // Map the field name with validator rules + fields: null + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + if (this.options.fields == null) { + return; + } + + var that = this; + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + .on('submit', function(e) { + that.formSubmited = true; + if (that.options.fields) { + for (var field in that.options.fields) { + if (that.numPendingRequests > 0 || that.numPendingRequests == null) { + // Check if the field is valid + var $field = that.getFieldElement(field); + if ($field.data('bootstrapValidator.isValid') !== true) { + that.validateField(field); + } + } + } + if (!that.isValid()) { + that.$form.find(that.options.submitButtons).attr('disabled', 'disabled'); + e.preventDefault(); + } + } + }); + + for (var field in this.options.fields) { + this._initField(field); + } + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + var $field = this.getFieldElement(field); + if (null == $field) { + return; + } + + // Create a help block element for showing the error + var that = this, + $parent = $field.parents('.form-group'), + helpBlock = $parent.find('.help-block'); + + if (helpBlock.length == 0) { + var $small = $('').addClass('help-block').appendTo($parent); + $field.data('bootstrapValidator.error', $small); + + // Calculate the number of columns of the label/field element + // Then set offset to the help block element + var label, cssClasses, offset; + if (label = $parent.find('label').get(0)) { + cssClasses = $(label).attr('class').split(' '); + for (var i = 0; i < cssClasses.length; i++) { + if (cssClasses[i].substr(0, 7) == 'col-lg-') { + offset = cssClasses[i].substr(7); + break; + } + } + } else { + cssClasses = $parent.children().eq(0).attr('class').split(' '); + for (var i = 0; i < cssClasses.length; i++) { + if (cssClasses[i].substr(0, 14) == 'col-lg-offset-') { + offset = cssClasses[i].substr(14); + break; + } + } + } + if (offset) { + $small.addClass('col-lg-offset-' + offset).addClass('col-lg-' + parseInt(12 - offset)); + } + } else { + $field.data('bootstrapValidator.error', helpBlock.eq(0)); + } + + var type = $field.attr('type'), + event = ('checkbox' == type || 'radio' == type || 'SELECT' == $field.get(0).tagName) ? 'change' : 'keyup'; + $field.on(event, function() { + that.formSubmited = false; + that.validateField(field); + }); + }, + + /** + * Get field element + * + * @param {String} field The field name + * @returns {jQuery} + */ + getFieldElement: function(field) { + var fields = this.$form.find('[name="' + field + '"]'); + return (fields.length == 0) ? null : $(fields[0]); + }, + + /** + * Validate given field + * + * @param {String} field The field name + */ + validateField: function(field) { + var $field = this.getFieldElement(field); + if (null == $field) { + // Return if cannot find the field with given name + return; + } + var that = this, + validators = that.options.fields[field].validators; + for (var validatorName in validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + continue; + } + var isValid = $.fn.bootstrapValidator.validators[validatorName].validate(that, $field, validators[validatorName]); + if (isValid === false) { + that.showError($field, validatorName); + break; + } else if (isValid === true) { + that.removeError($field); + } + } + }, + + /** + * Show field error + * + * @param {jQuery} $field The field element + * @param {String} validatorName + */ + showError: function($field, validatorName) { + var field = $field.attr('name'), + validator = this.options.fields[field].validators[validatorName], + message = validator.message || this.options.message, + $parent = $field.parents('.form-group'); + + this.invalidFields[field] = true; + + // Add has-error class to parent element + $parent.removeClass('has-success').addClass('has-error'); + + $field.data('bootstrapValidator.error').html(message).show(); + + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + }, + + /** + * Remove error from given field + * + * @param {jQuery} $field The field element + */ + removeError: function($field) { + delete this.invalidFields[$field.attr('name')]; + $field.parents('.form-group').removeClass('has-error').addClass('has-success'); + $field.data('bootstrapValidator.error').hide(); + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + }, + + /** + * Start remote checking + * + * @param {jQuery} $field The field element + * @param {String} validatorName + * @param {XMLHttpRequest} xhr + */ + startRequest: function($field, validatorName, xhr) { + var field = $field.attr('name'); + + $field.data('bootstrapValidator.isValid', false); + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + + if(this.numPendingRequests == null){ + this.numPendingRequests = 0; + } + this.numPendingRequests++; + // Abort the previous request + if (!this.xhrRequests[field]) { + this.xhrRequests[field] = {}; + } + + if (this.xhrRequests[field][validatorName]) { + this.numPendingRequests--; + this.xhrRequests[field][validatorName].abort(); + } + this.xhrRequests[field][validatorName] = xhr; + }, + + /** + * Complete remote checking + * + * @param {jQuery} $field The field element + * @param {String} validatorName + * @param {boolean} isValid + */ + completeRequest: function($field, validatorName, isValid) { + if (isValid === false) { + this.showError($field, validatorName); + } else if (isValid === true) { + this.removeError($field); + $field.data('bootstrapValidator.isValid', true); + } + + var field = $field.attr('name'); + + delete this.xhrRequests[field][validatorName]; + + this.numPendingRequests--; + if (this.numPendingRequests <= 0) { + this.numPendingRequests = 0; + if (this.formSubmited) { + this.$form.submit(); + } + } + }, + + /** + * Check the form validity + * + * @returns {boolean} + */ + isValid: function() { + if (this.numPendingRequests > 0) { + return false; + } + for (var field in this.invalidFields) { + if (this.invalidFields[field]) { + return false; + } + } + return true; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(options) { + return this.each(function() { + var $this = $(this), data = $this.data('bootstrapValidator'); + if (!data) { + $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options))); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = parseFloat($field.val()); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + return /^\d+$/.test($field.val()); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(), + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = parseFloat($field.val()); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + /** + * Return true if the input value is a valid hex color + * + * @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(); + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(), + $compareWith = validator.getFieldElement(options.field); + if ($compareWith && value == $compareWith.val()) { + validator.removeError($compareWith); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = parseFloat($field.val()); + return (options.inclusive === true) ? (value < options.value) : (value <= options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + return ('checkbox' == type || 'radio' == type) ? $field.is(':checked') : ($.trim($field.val()) != ''); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + return value.match(options.regexp); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.remote = { + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - message: The invalid message + * @returns {string} + */ + validate: function(validator, $field, options) { + var value = $field.val(), name = $field.attr('name'), data = options.data; + if (data == null) { + data = {}; + data[name] = value; + } + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }).success(function(response) { + var isValid = response.valid === true || response.valid === 'true'; + validator.completeRequest($field, 'remote', isValid); + }); + validator.startRequest($field, 'remote', xhr); + + return 'pending'; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $.trim($field.val()), length = value.length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test($field.val()); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.usZipCode = { + /** + * Return true if and only if the input value is a valid US zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validateInstance, $field, options) { + var value = $field.val(); + return /^\d{5}([\-]\d{4})?$/.test(value); + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.1.1/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.1.1/js/bootstrapValidator.min.js new file mode 100644 index 000000000..eff2be76c --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.1.1/js/bootstrapValidator.min.js @@ -0,0 +1,11 @@ +/** + * BootstrapValidator v0.1.1 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),this.invalidFields={},this.xhrRequests={},this.numPendingRequests=null,this.formSubmited=!1,this._init()};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",submitButtons:'button[type="submit"]',fields:null},b.prototype={constructor:b,_init:function(){if(null!=this.options.fields){var a=this;this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit",function(b){if(a.formSubmited=!0,a.options.fields){for(var c in a.options.fields)if(a.numPendingRequests>0||null==a.numPendingRequests){var d=a.getFieldElement(c);d.data("bootstrapValidator.isValid")!==!0&&a.validateField(c)}a.isValid()||(a.$form.find(a.options.submitButtons).attr("disabled","disabled"),b.preventDefault())}});for(var b in this.options.fields)this._initField(b)}},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){var c=this.getFieldElement(b);if(null!=c){var d=this,e=c.parents(".form-group"),f=e.find(".help-block");if(0==f.length){var g=a("").addClass("help-block").appendTo(e);c.data("bootstrapValidator.error",g);var h,i,j;if(h=e.find("label").get(0)){i=a(h).attr("class").split(" ");for(var k=0;k0)return!1;for(var a in this.invalidFields)if(this.invalidFields[a])return!1;return!0}},a.fn.bootstrapValidator=function(c){return this.each(function(){var d=a(this),e=d.data("bootstrapValidator");e||d.data("bootstrapValidator",e=new b(this,c))})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={validate:function(a,b,c){var d=parseFloat(b.val());return c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){return/^\d+$/.test(b.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={validate:function(a,b){var c=b.val(),d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={validate:function(a,b,c){var d=parseFloat(b.val());return c.inclusive===!0?d>c.value:d>=c.value}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={validate:function(a,b){var c=b.val();return/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={validate:function(a,b,c){var d=b.val(),e=a.getFieldElement(c.field);return e&&d==e.val()?(a.removeError(e),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={validate:function(a,b,c){var d=parseFloat(b.val());return c.inclusive===!0?dd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={validate:function(a,b){var c=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return c.test(b.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.usZipCode={validate:function(a,b){var c=b.val();return/^\d{5}([\-]\d{4})?$/.test(c)}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.0/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.2.0/css/bootstrapValidator.css new file mode 100644 index 000000000..81862c312 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.0/css/bootstrapValidator.css @@ -0,0 +1,11 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ +.bootstrap-validator-form .help-block { + margin-bottom: 0; } diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.0/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.2.0/css/bootstrapValidator.min.css new file mode 100644 index 000000000..ed8a307fe --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.0/css/bootstrapValidator.min.css @@ -0,0 +1,12 @@ +/** + * BootstrapValidator v0.2.0 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.0/css/bootstrapValidator.scss b/ajax/libs/jquery.bootstrapvalidator/0.2.0/css/bootstrapValidator.scss new file mode 100644 index 000000000..d2f6229dc --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.0/css/bootstrapValidator.scss @@ -0,0 +1,15 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form { + .help-block { + margin-bottom: 0; + } +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.0/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.2.0/js/bootstrapValidator.js new file mode 100644 index 000000000..8c62ac3ca --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.0/js/bootstrapValidator.js @@ -0,0 +1,778 @@ +/** + * BootstrapValidator v0.2.0 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + if ('disabled' == this.options.live) { + // Don't disable the submit buttons if the live validating is disabled + this.options.submitButtons = null; + } + + this.invalidFields = {}; + this.xhrRequests = {}; + this.numPendingRequests = null; + this.formSubmited = false; + + this._init(); + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // The submit buttons selector + // These buttons will be disabled when the form input are invalid + submitButtons: 'button[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submitting + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating. Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + if (this.options.fields == null) { + return; + } + + var that = this; + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + .on('submit', function(e) { + that.formSubmited = true; + if (that.options.fields) { + for (var field in that.options.fields) { + if (that.numPendingRequests > 0 || that.numPendingRequests == null) { + // Check if the field is valid + var $field = that.getFieldElement(field); + if ($field.data('bootstrapValidator.isValid') !== true) { + that.validateField(field); + } + } + } + if (!that.isValid()) { + that.$form.find(that.options.submitButtons).attr('disabled', 'disabled'); + if ('submitted' == that.options.live) { + that.options.live = 'enabled'; + that._setLiveValidating(); + } + + e.preventDefault(); + } else { + if (that.options.submitHandler && 'function' == typeof that.options.submitHandler) { + that.options.submitHandler.call(that, that, that.$form); + return false; + } + } + } + }); + + for (var field in this.options.fields) { + this._initField(field); + } + + this._setLiveValidating(); + }, + + /** + * Enable live validating + */ + _setLiveValidating: function() { + if ('enabled' == this.options.live) { + var that = this; + // Since this should be called once, I have to disable the live validating mode + this.options.live = 'disabled'; + + for (var field in this.options.fields) { + (function(field) { + var $field = that.getFieldElement(field); + if ($field) { + var type = $field.attr('type'), + event = ('checkbox' == type || 'radio' == type || 'SELECT' == $field.get(0).tagName) ? 'change' : 'keyup'; + $field.on(event, function() { + that.formSubmited = false; + that.validateField(field); + }); + } + })(field); + } + } + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + var $field = this.getFieldElement(field); + if (null == $field) { + return; + } + + // Create a help block element for showing the error + var that = this, + $parent = $field.parents('.form-group'), + helpBlock = $parent.find('.help-block'); + + if (helpBlock.length == 0) { + var $small = $('').addClass('help-block').appendTo($parent); + $field.data('bootstrapValidator.error', $small); + + // Calculate the number of columns of the label/field element + // Then set offset to the help block element + var label, cssClasses, offset, size; + if (label = $parent.find('label').get(0)) { + cssClasses = $(label).attr('class').split(' '); + for (var i = 0; i < cssClasses.length; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i])) { + offset = cssClasses[i].substr(7); + size = cssClasses[i].substr(4, 2); + break; + } + } + } else { + cssClasses = $parent.children().eq(0).attr('class').split(' '); + for (var i = 0; i < cssClasses.length; i++) { + if (/^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + offset = cssClasses[i].substr(14); + size = cssClasses[i].substr(4, 2); + break; + } + } + } + if (size && offset) { + $small.addClass(['col-', size, '-offset-', offset].join('')) + .addClass(['col-', size, '-', 12 - offset].join('')); + } + } else { + $field.data('bootstrapValidator.error', helpBlock.eq(0)); + } + }, + + /** + * Get field element + * + * @param {String} field The field name + * @returns {jQuery} + */ + getFieldElement: function(field) { + var fields = this.$form.find('[name="' + field + '"]'); + return (fields.length == 0) ? null : $(fields[0]); + }, + + /** + * Validate given field + * + * @param {String} field The field name + */ + validateField: function(field) { + var $field = this.getFieldElement(field); + if (null == $field) { + // Return if cannot find the field with given name + return; + } + var that = this, + validators = that.options.fields[field].validators; + for (var validatorName in validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + continue; + } + var isValid = $.fn.bootstrapValidator.validators[validatorName].validate(that, $field, validators[validatorName]); + if (isValid === false) { + that.showError($field, validatorName); + break; + } else if (isValid === true) { + that.removeError($field); + } + } + }, + + /** + * Show field error + * + * @param {jQuery} $field The field element + * @param {String} validatorName + */ + showError: function($field, validatorName) { + var field = $field.attr('name'), + validator = this.options.fields[field].validators[validatorName], + message = validator.message || this.options.message, + $parent = $field.parents('.form-group'); + + this.invalidFields[field] = true; + + // Add has-error class to parent element + $parent.removeClass('has-success').addClass('has-error'); + + $field.data('bootstrapValidator.error').html(message).show(); + + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + }, + + /** + * Remove error from given field + * + * @param {jQuery} $field The field element + */ + removeError: function($field) { + delete this.invalidFields[$field.attr('name')]; + $field.parents('.form-group').removeClass('has-error').addClass('has-success'); + $field.data('bootstrapValidator.error').hide(); + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + }, + + /** + * Start remote checking + * + * @param {jQuery} $field The field element + * @param {String} validatorName + * @param {XMLHttpRequest} xhr + */ + startRequest: function($field, validatorName, xhr) { + var field = $field.attr('name'); + + $field.data('bootstrapValidator.isValid', false); + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + + if(this.numPendingRequests == null){ + this.numPendingRequests = 0; + } + this.numPendingRequests++; + // Abort the previous request + if (!this.xhrRequests[field]) { + this.xhrRequests[field] = {}; + } + + if (this.xhrRequests[field][validatorName]) { + this.numPendingRequests--; + this.xhrRequests[field][validatorName].abort(); + } + this.xhrRequests[field][validatorName] = xhr; + }, + + /** + * Complete remote checking + * + * @param {jQuery} $field The field element + * @param {String} validatorName + * @param {boolean} isValid + */ + completeRequest: function($field, validatorName, isValid) { + if (isValid === false) { + this.showError($field, validatorName); + } else if (isValid === true) { + this.removeError($field); + $field.data('bootstrapValidator.isValid', true); + } + + var field = $field.attr('name'); + + delete this.xhrRequests[field][validatorName]; + + this.numPendingRequests--; + if (this.numPendingRequests <= 0) { + this.numPendingRequests = 0; + if (this.formSubmited) { + if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + this.options.submitHandler.call(this, this, this.$form); + } else { + this.$form.submit(); + } + } + } + }, + + /** + * Check the form validity + * + * @returns {boolean} + */ + isValid: function() { + if (this.numPendingRequests > 0) { + return false; + } + for (var field in this.invalidFields) { + if (this.invalidFields[field]) { + return false; + } + } + return true; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(options) { + return this.each(function() { + var $this = $(this), data = $this.data('bootstrapValidator'); + if (!data) { + $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options))); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = parseFloat($field.val()); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (options.callback && 'function' == typeof options.callback) { + return options.callback.call(this, value, this); + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + + // The Luhn Algorithm + // http://en.wikipedia.org/wiki/Luhn + value = value.replace(/\D/g, ''); + var check = 0, digit = 0, even = false, length = value.length; + + for (var n = length - 1; n >= 0; n--) { + digit = parseInt(value.charAt(n), 10); + + if (even) { + if ((digit *= 2) > 9) { + digit -= 9; + } + } + + check += digit; + even = !even; + } + + return (check % 10) == 0; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.different = { + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(), + $compareWith = validator.getFieldElement(options.field); + if ($compareWith && value != $compareWith.val()) { + validator.removeError($compareWith); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + return /^\d+$/.test($field.val()); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(), + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = parseFloat($field.val()); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + /** + * Return true if the input value is a valid hex color + * + * @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(); + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(), + $compareWith = validator.getFieldElement(options.field); + if ($compareWith && value == $compareWith.val()) { + validator.removeError($compareWith); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = parseFloat($field.val()); + return (options.inclusive === true) ? (value < options.value) : (value <= options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + return ('checkbox' == type || 'radio' == type) ? $field.is(':checked') : ($.trim($field.val()) != ''); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + return options.regexp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.remote = { + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - message: The invalid message + * @returns {string} + */ + validate: function(validator, $field, options) { + var value = $field.val(), name = $field.attr('name'), data = options.data; + if (data == null) { + data = {}; + data[name] = value; + } + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }).success(function(response) { + var isValid = response.valid === true || response.valid === 'true'; + validator.completeRequest($field, 'remote', isValid); + }); + validator.startRequest($field, 'remote', xhr); + + return 'pending'; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $.trim($field.val()), length = value.length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test($field.val()); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.usZipCode = { + /** + * Return true if and only if the input value is a valid US zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validateInstance, $field, options) { + var value = $field.val(); + return /^\d{5}([\-]\d{4})?$/.test(value); + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.0/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.2.0/js/bootstrapValidator.min.js new file mode 100644 index 000000000..9d9794a0b --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.0/js/bootstrapValidator.min.js @@ -0,0 +1,11 @@ +/** + * BootstrapValidator v0.2.0 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),"disabled"==this.options.live&&(this.options.submitButtons=null),this.invalidFields={},this.xhrRequests={},this.numPendingRequests=null,this.formSubmited=!1,this._init()};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",submitButtons:'button[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){if(null!=this.options.fields){var a=this;this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit",function(b){if(a.formSubmited=!0,a.options.fields){for(var c in a.options.fields)if(a.numPendingRequests>0||null==a.numPendingRequests){var d=a.getFieldElement(c);d.data("bootstrapValidator.isValid")!==!0&&a.validateField(c)}if(a.isValid()){if(a.options.submitHandler&&"function"==typeof a.options.submitHandler)return a.options.submitHandler.call(a,a,a.$form),!1}else a.$form.find(a.options.submitButtons).attr("disabled","disabled"),"submitted"==a.options.live&&(a.options.live="enabled",a._setLiveValidating()),b.preventDefault()}});for(var b in this.options.fields)this._initField(b);this._setLiveValidating()}},_setLiveValidating:function(){if("enabled"==this.options.live){var a=this;this.options.live="disabled";for(var b in this.options.fields)!function(b){var c=a.getFieldElement(b);if(c){var d=c.attr("type"),e="checkbox"==d||"radio"==d||"SELECT"==c.get(0).tagName?"change":"keyup";c.on(e,function(){a.formSubmited=!1,a.validateField(b)})}}(b)}},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){var c=this.getFieldElement(b);if(null!=c){var d=c.parents(".form-group"),e=d.find(".help-block");if(0==e.length){var f=a("").addClass("help-block").appendTo(d);c.data("bootstrapValidator.error",f);var g,h,i,j;if(g=d.find("label").get(0)){h=a(g).attr("class").split(" ");for(var k=0;k0)return!1;for(var a in this.invalidFields)if(this.invalidFields[a])return!1;return!0}},a.fn.bootstrapValidator=function(c){return this.each(function(){var d=a(this),e=d.data("bootstrapValidator");e||d.data("bootstrapValidator",e=new b(this,c))})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={validate:function(a,b,c){var d=parseFloat(b.val());return c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(a,b,c){var d=b.val();return c.callback&&"function"==typeof c.callback?c.callback.call(this,d,this):!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(a,b){var c=b.val();if(/[^0-9-\s]+/.test(c))return!1;c=c.replace(/\D/g,"");for(var d=0,e=0,f=!1,g=c.length,h=g-1;h>=0;h--)e=parseInt(c.charAt(h),10),f&&(e*=2)>9&&(e-=9),d+=e,f=!f;return 0==d%10}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={validate:function(a,b,c){var d=b.val(),e=a.getFieldElement(c.field);return e&&d!=e.val()?(a.removeError(e),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){return/^\d+$/.test(b.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={validate:function(a,b){var c=b.val(),d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={validate:function(a,b,c){var d=parseFloat(b.val());return c.inclusive===!0?d>c.value:d>=c.value}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={validate:function(a,b){var c=b.val();return/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={validate:function(a,b,c){var d=b.val(),e=a.getFieldElement(c.field);return e&&d==e.val()?(a.removeError(e),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={validate:function(a,b,c){var d=parseFloat(b.val());return c.inclusive===!0?dd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={validate:function(a,b){var c=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return c.test(b.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.usZipCode={validate:function(a,b){var c=b.val();return/^\d{5}([\-]\d{4})?$/.test(c)}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.1/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.2.1/css/bootstrapValidator.css new file mode 100644 index 000000000..81862c312 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.1/css/bootstrapValidator.css @@ -0,0 +1,11 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ +.bootstrap-validator-form .help-block { + margin-bottom: 0; } diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.1/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.2.1/css/bootstrapValidator.min.css new file mode 100644 index 000000000..3653c4bac --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.1/css/bootstrapValidator.min.css @@ -0,0 +1,12 @@ +/** + * BootstrapValidator v0.2.1 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.1/css/bootstrapValidator.scss b/ajax/libs/jquery.bootstrapvalidator/0.2.1/css/bootstrapValidator.scss new file mode 100644 index 000000000..d2f6229dc --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.1/css/bootstrapValidator.scss @@ -0,0 +1,15 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form { + .help-block { + margin-bottom: 0; + } +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.1/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.2.1/js/bootstrapValidator.js new file mode 100644 index 000000000..dcfb52491 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.1/js/bootstrapValidator.js @@ -0,0 +1,778 @@ +/** + * BootstrapValidator v0.2.1 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + if ('disabled' == this.options.live) { + // Don't disable the submit buttons if the live validating is disabled + this.options.submitButtons = null; + } + + this.invalidFields = {}; + this.xhrRequests = {}; + this.numPendingRequests = null; + this.formSubmited = false; + + this._init(); + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // The submit buttons selector + // These buttons will be disabled when the form input are invalid + submitButtons: 'button[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submitting + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating. Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + if (this.options.fields == null) { + return; + } + + var that = this; + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + .on('submit', function(e) { + that.formSubmited = true; + if (that.options.fields) { + for (var field in that.options.fields) { + if (that.numPendingRequests > 0 || that.numPendingRequests == null) { + // Check if the field is valid + var $field = that.getFieldElement(field); + if ($field.data('bootstrapValidator.isValid') !== true) { + that.validateField(field); + } + } + } + if (!that.isValid()) { + that.$form.find(that.options.submitButtons).attr('disabled', 'disabled'); + if ('submitted' == that.options.live) { + that.options.live = 'enabled'; + that._setLiveValidating(); + } + + e.preventDefault(); + } else { + if (that.options.submitHandler && 'function' == typeof that.options.submitHandler) { + that.options.submitHandler.call(that, that, that.$form); + return false; + } + } + } + }); + + for (var field in this.options.fields) { + this._initField(field); + } + + this._setLiveValidating(); + }, + + /** + * Enable live validating + */ + _setLiveValidating: function() { + if ('enabled' == this.options.live) { + var that = this; + // Since this should be called once, I have to disable the live validating mode + this.options.live = 'disabled'; + + for (var field in this.options.fields) { + (function(field) { + var $field = that.getFieldElement(field); + if ($field) { + var type = $field.attr('type'), + event = ('checkbox' == type || 'radio' == type || 'SELECT' == $field.get(0).tagName) ? 'change' : 'keyup'; + $field.on(event, function() { + that.formSubmited = false; + that.validateField(field); + }); + } + })(field); + } + } + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + var $field = this.getFieldElement(field); + if (null == $field) { + return; + } + + // Create a help block element for showing the error + var that = this, + $parent = $field.parents('.form-group'), + helpBlock = $parent.find('.help-block'); + + if (helpBlock.length == 0) { + var $small = $('').addClass('help-block').css('display', 'none').appendTo($parent); + $field.data('bootstrapValidator.error', $small); + + // Calculate the number of columns of the label/field element + // Then set offset to the help block element + var label, cssClasses, offset, size; + if (label = $parent.find('label').get(0)) { + cssClasses = $(label).attr('class').split(' '); + for (var i = 0; i < cssClasses.length; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i])) { + offset = cssClasses[i].substr(7); + size = cssClasses[i].substr(4, 2); + break; + } + } + } else { + cssClasses = $parent.children().eq(0).attr('class').split(' '); + for (var i = 0; i < cssClasses.length; i++) { + if (/^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + offset = cssClasses[i].substr(14); + size = cssClasses[i].substr(4, 2); + break; + } + } + } + if (size && offset) { + $small.addClass(['col-', size, '-offset-', offset].join('')) + .addClass(['col-', size, '-', 12 - offset].join('')); + } + } else { + $field.data('bootstrapValidator.error', helpBlock.eq(0)); + } + }, + + /** + * Get field element + * + * @param {String} field The field name + * @returns {jQuery} + */ + getFieldElement: function(field) { + var fields = this.$form.find('[name="' + field + '"]'); + return (fields.length == 0) ? null : $(fields[0]); + }, + + /** + * Validate given field + * + * @param {String} field The field name + */ + validateField: function(field) { + var $field = this.getFieldElement(field); + if (null == $field) { + // Return if cannot find the field with given name + return; + } + var that = this, + validators = that.options.fields[field].validators; + for (var validatorName in validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + continue; + } + var isValid = $.fn.bootstrapValidator.validators[validatorName].validate(that, $field, validators[validatorName]); + if (isValid === false) { + that.showError($field, validatorName); + break; + } else if (isValid === true) { + that.removeError($field); + } + } + }, + + /** + * Show field error + * + * @param {jQuery} $field The field element + * @param {String} validatorName + */ + showError: function($field, validatorName) { + var field = $field.attr('name'), + validator = this.options.fields[field].validators[validatorName], + message = validator.message || this.options.message, + $parent = $field.parents('.form-group'); + + this.invalidFields[field] = true; + + // Add has-error class to parent element + $parent.removeClass('has-success').addClass('has-error'); + + $field.data('bootstrapValidator.error').html(message).show(); + + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + }, + + /** + * Remove error from given field + * + * @param {jQuery} $field The field element + */ + removeError: function($field) { + delete this.invalidFields[$field.attr('name')]; + $field.parents('.form-group').removeClass('has-error').addClass('has-success'); + $field.data('bootstrapValidator.error').hide(); + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + }, + + /** + * Start remote checking + * + * @param {jQuery} $field The field element + * @param {String} validatorName + * @param {XMLHttpRequest} xhr + */ + startRequest: function($field, validatorName, xhr) { + var field = $field.attr('name'); + + $field.data('bootstrapValidator.isValid', false); + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + + if(this.numPendingRequests == null){ + this.numPendingRequests = 0; + } + this.numPendingRequests++; + // Abort the previous request + if (!this.xhrRequests[field]) { + this.xhrRequests[field] = {}; + } + + if (this.xhrRequests[field][validatorName]) { + this.numPendingRequests--; + this.xhrRequests[field][validatorName].abort(); + } + this.xhrRequests[field][validatorName] = xhr; + }, + + /** + * Complete remote checking + * + * @param {jQuery} $field The field element + * @param {String} validatorName + * @param {boolean} isValid + */ + completeRequest: function($field, validatorName, isValid) { + if (isValid === false) { + this.showError($field, validatorName); + } else if (isValid === true) { + this.removeError($field); + $field.data('bootstrapValidator.isValid', true); + } + + var field = $field.attr('name'); + + delete this.xhrRequests[field][validatorName]; + + this.numPendingRequests--; + if (this.numPendingRequests <= 0) { + this.numPendingRequests = 0; + if (this.formSubmited) { + if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + this.options.submitHandler.call(this, this, this.$form); + } else { + this.$form.submit(); + } + } + } + }, + + /** + * Check the form validity + * + * @returns {boolean} + */ + isValid: function() { + if (this.numPendingRequests > 0) { + return false; + } + for (var field in this.invalidFields) { + if (this.invalidFields[field]) { + return false; + } + } + return true; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(options) { + return this.each(function() { + var $this = $(this), data = $this.data('bootstrapValidator'); + if (!data) { + $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options))); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = parseFloat($field.val()); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (options.callback && 'function' == typeof options.callback) { + return options.callback.call(this, value, this); + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + + // The Luhn Algorithm + // http://en.wikipedia.org/wiki/Luhn + value = value.replace(/\D/g, ''); + var check = 0, digit = 0, even = false, length = value.length; + + for (var n = length - 1; n >= 0; n--) { + digit = parseInt(value.charAt(n), 10); + + if (even) { + if ((digit *= 2) > 9) { + digit -= 9; + } + } + + check += digit; + even = !even; + } + + return (check % 10) == 0; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.different = { + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(), + $compareWith = validator.getFieldElement(options.field); + if ($compareWith && value != $compareWith.val()) { + validator.removeError($compareWith); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + return /^\d+$/.test($field.val()); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(), + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = parseFloat($field.val()); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + /** + * Return true if the input value is a valid hex color + * + * @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(); + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(), + $compareWith = validator.getFieldElement(options.field); + if ($compareWith && value == $compareWith.val()) { + validator.removeError($compareWith); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = parseFloat($field.val()); + return (options.inclusive === true) ? (value < options.value) : (value <= options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + return ('checkbox' == type || 'radio' == type) ? $field.is(':checked') : ($.trim($field.val()) != ''); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + return options.regexp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.remote = { + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - message: The invalid message + * @returns {string} + */ + validate: function(validator, $field, options) { + var value = $field.val(), name = $field.attr('name'), data = options.data; + if (data == null) { + data = {}; + data[name] = value; + } + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }).success(function(response) { + var isValid = response.valid === true || response.valid === 'true'; + validator.completeRequest($field, 'remote', isValid); + }); + validator.startRequest($field, 'remote', xhr); + + return 'pending'; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {boolean} + */ + validate: function(validator, $field, options) { + var value = $.trim($field.val()), length = value.length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validator, $field, options) { + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test($field.val()); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.usZipCode = { + /** + * Return true if and only if the input value is a valid US zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {boolean} + */ + validate: function(validateInstance, $field, options) { + var value = $field.val(); + return /^\d{5}([\-]\d{4})?$/.test(value); + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.1/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.2.1/js/bootstrapValidator.min.js new file mode 100644 index 000000000..5c39d3f70 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.1/js/bootstrapValidator.min.js @@ -0,0 +1,11 @@ +/** + * BootstrapValidator v0.2.1 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),"disabled"==this.options.live&&(this.options.submitButtons=null),this.invalidFields={},this.xhrRequests={},this.numPendingRequests=null,this.formSubmited=!1,this._init()};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",submitButtons:'button[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){if(null!=this.options.fields){var a=this;this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit",function(b){if(a.formSubmited=!0,a.options.fields){for(var c in a.options.fields)if(a.numPendingRequests>0||null==a.numPendingRequests){var d=a.getFieldElement(c);d.data("bootstrapValidator.isValid")!==!0&&a.validateField(c)}if(a.isValid()){if(a.options.submitHandler&&"function"==typeof a.options.submitHandler)return a.options.submitHandler.call(a,a,a.$form),!1}else a.$form.find(a.options.submitButtons).attr("disabled","disabled"),"submitted"==a.options.live&&(a.options.live="enabled",a._setLiveValidating()),b.preventDefault()}});for(var b in this.options.fields)this._initField(b);this._setLiveValidating()}},_setLiveValidating:function(){if("enabled"==this.options.live){var a=this;this.options.live="disabled";for(var b in this.options.fields)!function(b){var c=a.getFieldElement(b);if(c){var d=c.attr("type"),e="checkbox"==d||"radio"==d||"SELECT"==c.get(0).tagName?"change":"keyup";c.on(e,function(){a.formSubmited=!1,a.validateField(b)})}}(b)}},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){var c=this.getFieldElement(b);if(null!=c){var d=c.parents(".form-group"),e=d.find(".help-block");if(0==e.length){var f=a("").addClass("help-block").css("display","none").appendTo(d);c.data("bootstrapValidator.error",f);var g,h,i,j;if(g=d.find("label").get(0)){h=a(g).attr("class").split(" ");for(var k=0;k0)return!1;for(var a in this.invalidFields)if(this.invalidFields[a])return!1;return!0}},a.fn.bootstrapValidator=function(c){return this.each(function(){var d=a(this),e=d.data("bootstrapValidator");e||d.data("bootstrapValidator",e=new b(this,c))})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={validate:function(a,b,c){var d=parseFloat(b.val());return c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(a,b,c){var d=b.val();return c.callback&&"function"==typeof c.callback?c.callback.call(this,d,this):!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(a,b){var c=b.val();if(/[^0-9-\s]+/.test(c))return!1;c=c.replace(/\D/g,"");for(var d=0,e=0,f=!1,g=c.length,h=g-1;h>=0;h--)e=parseInt(c.charAt(h),10),f&&(e*=2)>9&&(e-=9),d+=e,f=!f;return 0==d%10}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={validate:function(a,b,c){var d=b.val(),e=a.getFieldElement(c.field);return e&&d!=e.val()?(a.removeError(e),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){return/^\d+$/.test(b.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={validate:function(a,b){var c=b.val(),d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={validate:function(a,b,c){var d=parseFloat(b.val());return c.inclusive===!0?d>c.value:d>=c.value}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={validate:function(a,b){var c=b.val();return/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={validate:function(a,b,c){var d=b.val(),e=a.getFieldElement(c.field);return e&&d==e.val()?(a.removeError(e),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={validate:function(a,b,c){var d=parseFloat(b.val());return c.inclusive===!0?dd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={validate:function(a,b){var c=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return c.test(b.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.usZipCode={validate:function(a,b){var c=b.val();return/^\d{5}([\-]\d{4})?$/.test(c)}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.2/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.2.2/css/bootstrapValidator.css new file mode 100644 index 000000000..9cac64e4f --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.2/css/bootstrapValidator.css @@ -0,0 +1,11 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ +.bootstrap-validator-form .help-block { + margin-bottom: 0; } diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.2/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.2.2/css/bootstrapValidator.min.css new file mode 100644 index 000000000..e0023e692 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.2/css/bootstrapValidator.min.css @@ -0,0 +1,12 @@ +/** + * BootstrapValidator v0.2.2 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.2/css/bootstrapValidator.scss b/ajax/libs/jquery.bootstrapvalidator/0.2.2/css/bootstrapValidator.scss new file mode 100644 index 000000000..329630fb0 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.2/css/bootstrapValidator.scss @@ -0,0 +1,15 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form { + .help-block { + margin-bottom: 0; + } +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.2/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.2.2/js/bootstrapValidator.js new file mode 100644 index 000000000..69d13f370 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.2/js/bootstrapValidator.js @@ -0,0 +1,853 @@ +/** + * BootstrapValidator v0.2.2 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + if ('disabled' == this.options.live) { + // Don't disable the submit buttons if the live validating is disabled + this.options.submitButtons = null; + } + + this.invalidFields = {}; + this.xhrRequests = {}; + this.numPendingRequests = null; + this.formSubmited = false; + this.submitHandlerCalled = false; + + this._init(); + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // The submit buttons selector + // These buttons will be disabled when the form input are invalid + submitButtons: 'button[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submitting + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating. Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + if (this.options.fields == null) { + return; + } + + var that = this; + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + .on('submit', function(e) { + that.formSubmited = true; + if (that.options.fields) { + for (var field in that.options.fields) { + if (that.numPendingRequests > 0 || that.numPendingRequests == null) { + // Check if the field is valid + var $field = that.getFieldElement(field); + if ($field && $field.data('bootstrapValidator.isValid') !== true) { + that.validateField(field); + } + } + } + if (!that.isValid()) { + that.$form.find(that.options.submitButtons).attr('disabled', 'disabled'); + if ('submitted' == that.options.live) { + that.options.live = 'enabled'; + that._setLiveValidating(); + } + + // Focus to the first invalid field + for (var i in that.invalidFields) { + that.getFieldElement(i).focus(); + break; + } + + e.preventDefault(); + } else { + if (!that.submitHandlerCalled && that.options.submitHandler && 'function' == typeof that.options.submitHandler) { + // Avoid calling submitHandler recursively + // in the case user call form.submit() right inside the submitHandler() + that.submitHandlerCalled = true; + that.options.submitHandler.call(that, that, that.$form); + return false; + } + } + } + }); + + for (var field in this.options.fields) { + this._initField(field); + } + + this._setLiveValidating(); + }, + + /** + * Enable live validating + */ + _setLiveValidating: function() { + if ('enabled' == this.options.live) { + var that = this; + // Since this should be called once, I have to disable the live validating mode + this.options.live = 'disabled'; + + for (var field in this.options.fields) { + (function(field) { + var $field = that.getFieldElement(field); + if ($field) { + var type = $field.attr('type'), + event = ('checkbox' == type || 'radio' == type || 'SELECT' == $field.get(0).tagName) ? 'change' : 'keyup'; + $field.on(event, function() { + that.formSubmited = false; + that.validateField(field); + }); + } + })(field); + } + } + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + var $field = this.getFieldElement(field); + if (null == $field) { + return; + } + + // Create a help block element for showing the error + var $parent = $field.parents('.form-group'), + helpBlock = $parent.find('.help-block'); + + if (helpBlock.length == 0) { + var $small = $('').addClass('help-block').css('display', 'none').appendTo($parent); + $field.data('bootstrapValidator.error', $small); + + // Calculate the number of columns of the label/field element + // Then set offset to the help block element + var label, cssClasses, offset, size; + if (label = $parent.find('label').get(0)) { + // The default Bootstrap form don't require class for label (http://getbootstrap.com/css/#forms) + if (cssClasses = $(label).attr('class')) { + cssClasses = cssClasses.split(' '); + for (var i = 0; i < cssClasses.length; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i])) { + offset = cssClasses[i].substr(7); + size = cssClasses[i].substr(4, 2); + break; + } + } + } + } else if (cssClasses = $parent.children().eq(0).attr('class')) { + cssClasses = cssClasses.split(' '); + for (var i = 0; i < cssClasses.length; i++) { + if (/^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + offset = cssClasses[i].substr(14); + size = cssClasses[i].substr(4, 2); + break; + } + } + } + if (size && offset) { + $small.addClass(['col-', size, '-offset-', offset].join('')) + .addClass(['col-', size, '-', 12 - offset].join('')); + } + } else { + $field.data('bootstrapValidator.error', helpBlock.eq(0)); + } + }, + + /** + * Get field element + * + * @param {String} field The field name + * @returns {jQuery} + */ + getFieldElement: function(field) { + var fields = this.$form.find('[name="' + field + '"]'); + return (fields.length == 0) ? null : $(fields[0]); + }, + + /** + * Validate given field + * + * @param {String} field The field name + */ + validateField: function(field) { + var $field = this.getFieldElement(field); + if (null == $field) { + // Return if cannot find the field with given name + return; + } + var that = this, + validators = that.options.fields[field].validators; + for (var validatorName in validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + continue; + } + var isValid = $.fn.bootstrapValidator.validators[validatorName].validate(that, $field, validators[validatorName]); + if (isValid === false) { + that.showError($field, validatorName); + break; + } else if (isValid === true) { + that.removeError($field); + } + } + }, + + /** + * Show field error + * + * @param {jQuery} $field The field element + * @param {String} validatorName + */ + showError: function($field, validatorName) { + var field = $field.attr('name'), + validator = this.options.fields[field].validators[validatorName], + message = validator.message || this.options.message, + $parent = $field.parents('.form-group'); + + this.invalidFields[field] = true; + + // Add has-error class to parent element + $parent.removeClass('has-success').addClass('has-error'); + + $field.data('bootstrapValidator.error').html(message).show(); + + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + }, + + /** + * Remove error from given field + * + * @param {jQuery} $field The field element + */ + removeError: function($field) { + delete this.invalidFields[$field.attr('name')]; + $field.parents('.form-group').removeClass('has-error').addClass('has-success'); + $field.data('bootstrapValidator.error').hide(); + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + }, + + /** + * Start remote checking + * + * @param {jQuery} $field The field element + * @param {String} validatorName + * @param {XMLHttpRequest} xhr + */ + startRequest: function($field, validatorName, xhr) { + var field = $field.attr('name'); + + $field.data('bootstrapValidator.isValid', false); + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + + if(this.numPendingRequests == null){ + this.numPendingRequests = 0; + } + this.numPendingRequests++; + // Abort the previous request + if (!this.xhrRequests[field]) { + this.xhrRequests[field] = {}; + } + + if (this.xhrRequests[field][validatorName]) { + this.numPendingRequests--; + this.xhrRequests[field][validatorName].abort(); + } + this.xhrRequests[field][validatorName] = xhr; + }, + + /** + * Complete remote checking + * + * @param {jQuery} $field The field element + * @param {String} validatorName + * @param {Boolean} isValid + */ + completeRequest: function($field, validatorName, isValid) { + if (isValid === false) { + this.showError($field, validatorName); + } else if (isValid === true) { + this.removeError($field); + $field.data('bootstrapValidator.isValid', true); + } + + var field = $field.attr('name'); + + delete this.xhrRequests[field][validatorName]; + + this.numPendingRequests--; + if (this.numPendingRequests <= 0) { + this.numPendingRequests = 0; + if (this.formSubmited) { + if (!this.submitHandlerCalled && this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + this.submitHandlerCalled = true; + this.options.submitHandler.call(this, this, this.$form); + } else { + this.$form.submit(); + } + } + } + }, + + /** + * Check the form validity + * + * @returns {Boolean} + */ + isValid: function() { + if (this.numPendingRequests > 0) { + return false; + } + for (var field in this.invalidFields) { + if (this.invalidFields[field]) { + return false; + } + } + return true; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(options) { + return this.each(function() { + var $this = $(this), data = $this.data('bootstrapValidator'); + if (!data) { + $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options))); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = parseFloat(value); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (options.callback && 'function' == typeof options.callback) { + return options.callback.call(this, value, this); + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + + // The Luhn Algorithm + // http://en.wikipedia.org/wiki/Luhn + value = value.replace(/\D/g, ''); + var check = 0, digit = 0, even = false, length = value.length; + + for (var n = length - 1; n >= 0; n--) { + digit = parseInt(value.charAt(n), 10); + + if (even) { + if ((digit *= 2) > 9) { + digit -= 9; + } + } + + check += digit; + even = !even; + } + + return (check % 10) == 0; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.different = { + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var $compareWith = validator.getFieldElement(options.field); + if ($compareWith && value != $compareWith.val()) { + validator.removeError($compareWith); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^\d+$/.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + /** + * Return true if the input value is a valid hex color + * + * @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; + } + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var $compareWith = validator.getFieldElement(options.field); + if ($compareWith && value == $compareWith.val()) { + validator.removeError($compareWith); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value < options.value) : (value <= options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + return ('checkbox' == type || 'radio' == type) ? $field.is(':checked') : ($.trim($field.val()) != ''); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return options.regexp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.remote = { + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - message: The invalid message + * @returns {Boolean|String} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var name = $field.attr('name'), data = options.data; + if (data == null) { + data = {}; + } + data[name] = value; + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }).success(function(response) { + var isValid = response.valid === true || response.valid === 'true'; + validator.completeRequest($field, 'remote', isValid); + }); + validator.startRequest($field, 'remote', xhr); + + return 'pending'; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var length = $.trim(value).length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.usZipCode = { + /** + * Return true if and only if the input value is a valid US zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validateInstance, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + return /^\d{5}([\-]\d{4})?$/.test(value); + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.2.2/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.2.2/js/bootstrapValidator.min.js new file mode 100644 index 000000000..2b8c38289 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.2.2/js/bootstrapValidator.min.js @@ -0,0 +1,11 @@ +/** + * BootstrapValidator v0.2.2 (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author Nguyen Huu Phuoc + * @copyright (c) 2013 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),"disabled"==this.options.live&&(this.options.submitButtons=null),this.invalidFields={},this.xhrRequests={},this.numPendingRequests=null,this.formSubmited=!1,this.submitHandlerCalled=!1,this._init()};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",submitButtons:'button[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){if(null!=this.options.fields){var a=this;this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit",function(b){if(a.formSubmited=!0,a.options.fields){for(var c in a.options.fields)if(a.numPendingRequests>0||null==a.numPendingRequests){var d=a.getFieldElement(c);d&&d.data("bootstrapValidator.isValid")!==!0&&a.validateField(c)}if(a.isValid()){if(!a.submitHandlerCalled&&a.options.submitHandler&&"function"==typeof a.options.submitHandler)return a.submitHandlerCalled=!0,a.options.submitHandler.call(a,a,a.$form),!1}else{a.$form.find(a.options.submitButtons).attr("disabled","disabled"),"submitted"==a.options.live&&(a.options.live="enabled",a._setLiveValidating());for(var e in a.invalidFields){a.getFieldElement(e).focus();break}b.preventDefault()}}});for(var b in this.options.fields)this._initField(b);this._setLiveValidating()}},_setLiveValidating:function(){if("enabled"==this.options.live){var a=this;this.options.live="disabled";for(var b in this.options.fields)!function(b){var c=a.getFieldElement(b);if(c){var d=c.attr("type"),e="checkbox"==d||"radio"==d||"SELECT"==c.get(0).tagName?"change":"keyup";c.on(e,function(){a.formSubmited=!1,a.validateField(b)})}}(b)}},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){var c=this.getFieldElement(b);if(null!=c){var d=c.parents(".form-group"),e=d.find(".help-block");if(0==e.length){var f=a("").addClass("help-block").css("display","none").appendTo(d);c.data("bootstrapValidator.error",f);var g,h,i,j;if(g=d.find("label").get(0)){if(h=a(g).attr("class")){h=h.split(" ");for(var k=0;k0)return!1;for(var a in this.invalidFields)if(this.invalidFields[a])return!1;return!0}},a.fn.bootstrapValidator=function(c){return this.each(function(){var d=a(this),e=d.data("bootstrapValidator");e||d.data("bootstrapValidator",e=new b(this,c))})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(a,b,c){var d=b.val();return""==d?!0:c.callback&&"function"==typeof c.callback?c.callback.call(this,d,this):!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(a,b){var c=b.val();if(""==c)return!0;if(/[^0-9-\s]+/.test(c))return!1;c=c.replace(/\D/g,"");for(var d=0,e=0,f=!1,g=c.length,h=g-1;h>=0;h--)e=parseInt(c.charAt(h),10),f&&(e*=2)>9&&(e-=9),d+=e,f=!f;return 0==d%10}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElement(c.field);return e&&d!=e.val()?(a.removeError(e),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){var c=b.val();return""==c?!0:/^\d+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={validate:function(a,b){var c=b.val();if(""==c)return!0;var d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.value:d>=c.value)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={validate:function(a,b){var c=b.val();return""==c?!0:/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElement(c.field);return e&&d==e.val()?(a.removeError(e),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?dd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={validate:function(a,b){var c=b.val();if(""==c)return!0;var d=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.usZipCode={validate:function(a,b){var c=b.val();return""==c?!0:/^\d{5}([\-]\d{4})?$/.test(c)}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.0/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.3.0/css/bootstrapValidator.css new file mode 100644 index 000000000..9cac64e4f --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.0/css/bootstrapValidator.css @@ -0,0 +1,11 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ +.bootstrap-validator-form .help-block { + margin-bottom: 0; } diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.0/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.3.0/css/bootstrapValidator.min.css new file mode 100644 index 000000000..3e58483de --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.0/css/bootstrapValidator.min.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.3.0 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.0/css/bootstrapValidator.scss b/ajax/libs/jquery.bootstrapvalidator/0.3.0/css/bootstrapValidator.scss new file mode 100644 index 000000000..329630fb0 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.0/css/bootstrapValidator.scss @@ -0,0 +1,15 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form { + .help-block { + margin-bottom: 0; + } +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.0/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.3.0/js/bootstrapValidator.js new file mode 100644 index 000000000..e5ba485ec --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.0/js/bootstrapValidator.js @@ -0,0 +1,1050 @@ +/** + * BootstrapValidator (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.3.0 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + this.dfds = {}; // Array of deferred + this.results = {}; // Validating results + + this.invalidField = null; // First invalid field + this.$submitButton = null; // The submit button which is clicked to submit form + + this._init(); + + this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED'; + this.STATUS_VALIDATING = 'VALIDATING'; + this.STATUS_INVALID = 'INVALID'; + this.STATUS_VALID = 'VALID'; + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // The number of grid columns + // Change it if you use custom grid with different number of columns + columns: 12, + + // Shows ok/error/loading icons based on the field validity. + // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation). + // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically. + // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later. + // + // Examples: + // - Use Glyphicons icons: + // feedbackIcons: { + // valid: 'glyphicon glyphicon-ok', + // invalid: 'glyphicon glyphicon-remove', + // validating: 'glyphicon glyphicon-refresh' + // } + // - Use FontAwesome icons: + // feedbackIcons: { + // valid: 'fa fa-check', + // invalid: 'fa fa-times', + // validating: 'fa fa-refresh' + // } + feedbackIcons: null, + + // The submit buttons selector + // These buttons will be disabled to prevent the valid form from multiple submissions + submitButtons: 'button[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submission + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating option + // Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + if (this.options.fields == null) { + return; + } + + var that = this; + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + // Disable the default submission first + .on('submit.bootstrapValidator', function(e) { + e.preventDefault(); + that.validate(); + }) + .find(this.options.submitButtons) + .on('click', function() { + that.$submitButton = $(this); + }); + + for (var field in this.options.fields) { + this._initField(field); + } + + this._setLiveValidating(); + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + this.dfds[field] = {}; + this.results[field] = {}; + + var fields = this.getFieldElements(field); + + // We don't need to validate ... + if (fields == null // ... non-existing fields + || (fields.length == 1 && fields.is(':disabled'))) // ... disabled field + { + delete this.options.fields[field]; + delete this.dfds[field]; + return; + } + + // Create a help block element for showing the error + var $field = $(fields[0]), + $parent = $field.parents('.form-group'), + // Calculate the number of columns of the label/field element + // Then set offset to the help block element + label, cssClasses, offset, size; + + if (label = $parent.find('label').get(0)) { + // The default Bootstrap form don't require class for label (http://getbootstrap.com/css/#forms) + if (cssClasses = $(label).attr('class')) { + cssClasses = cssClasses.split(' '); + for (var i = 0; i < cssClasses.length; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i])) { + offset = cssClasses[i].substr(7); + size = cssClasses[i].substr(4, 2); + break; + } + } + } + } else if (cssClasses = $parent.children().eq(0).attr('class')) { + cssClasses = cssClasses.split(' '); + for (var i = 0; i < cssClasses.length; i++) { + if (/^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + offset = cssClasses[i].substr(14); + size = cssClasses[i].substr(4, 2); + break; + } + } + } + + if (size && offset) { + for (var validatorName in this.options.fields[field].validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + delete this.options.fields[field].validators[validatorName]; + continue; + } + + this.results[field][validatorName] = this.STATUS_NOT_VALIDATED; + $('') + .css('display', 'none') + .attr('data-bs-validator', validatorName) + .addClass('help-block') + .addClass(['col-', size, '-offset-', offset].join('')) + .addClass(['col-', size, '-', this.options.columns - offset].join('')) + .appendTo($parent); + } + } + + // Prepare the feedback icons + // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation) + if (this.options.feedbackIcons) { + $parent.addClass('has-feedback'); + $('').css('display', 'none').addClass('form-control-feedback').insertAfter($(fields[fields.length - 1])); + } + + // Whenever the user change the field value, make it as not validated yet + var that = this, + type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup'; + + fields.on(event, function() { + // Whenever the user change the field value, make it as not validated yet + for (var v in that.options.fields[field].validators) { + that.results[field][v] = that.STATUS_NOT_VALIDATED; + } + }); + }, + + /** + * Enable live validating + */ + _setLiveValidating: function() { + if ('enabled' == this.options.live) { + var that = this; + for (var field in this.options.fields) { + (function(f) { + var fields = that.getFieldElements(f); + if (fields) { + var type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup'; + + fields.on(event, function() { + that.validateField(f); + }); + } + })(field); + } + } + }, + + /** + * Disable/Enable submit buttons + * + * @param {Boolean} disabled + */ + _disableSubmitButtons: function(disabled) { + if (!disabled) { + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + } else if (this.options.live != 'disabled') { + // Don't disable if the live validating mode is disabled + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + } + }, + + /** + * Called when all validations are completed + */ + _submit: function() { + if (!this.isValid()) { + if ('submitted' == this.options.live) { + this.options.live = 'enabled'; + this._setLiveValidating(); + } + + // Focus to the first invalid field + if (this.invalidField) { + this.getFieldElements(this.invalidField).focus(); + } + return; + } + + this._disableSubmitButtons(true); + + // Call the custom submission if enabled + if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + this.options.submitHandler.call(this, this, this.$form, this.$submitButton); + } else { + // Submit form + this.$form.off('submit.bootstrapValidator').submit(); + } + }, + + // --- Public methods --- + + /** + * Retrieve the field elements by given name + * + * @param {String} field The field name + * @returns {null|jQuery[]} + */ + getFieldElements: function(field) { + var fields = this.$form.find('[name="' + field + '"]'); + return (fields.length == 0) ? null : fields; + }, + + /** + * Validate the form + */ + validate: function() { + if (!this.options.fields) { + return this; + } + this._disableSubmitButtons(true); + + for (var field in this.options.fields) { + this.validateField(field); + } + + this._submit(); + return this; + }, + + /** + * Validate given field + * + * @param {String} field The field name + */ + validateField: function(field) { + var that = this, + fields = this.$form.find('[name="' + field + '"]'), + $field = $(fields[0]), + validators = this.options.fields[field].validators, + validatorName, + validateResult; + + for (validatorName in validators) { + if (this.dfds[field][validatorName]) { + this.dfds[field][validatorName].reject(); + } + + // Don't validate field if it is already done + if (this.results[field][validatorName] == this.STATUS_VALID || this.results[field][validatorName] == this.STATUS_INVALID) { + continue; + } + + this.results[field][validatorName] = this.STATUS_VALIDATING; + validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]); + + if ('object' == typeof validateResult) { + this.updateStatus($field, validatorName, this.STATUS_VALIDATING); + this.dfds[field][validatorName] = validateResult; + + validateResult.done(function(isValid, v) { + // v is validator name + delete that.dfds[field][v]; + isValid ? that.updateStatus($field, v, that.STATUS_VALID) + : that.updateStatus($field, v, that.STATUS_INVALID); + }); + } else if ('boolean' == typeof validateResult) { + validateResult ? this.updateStatus($field, validatorName, this.STATUS_VALID) + : this.updateStatus($field, validatorName, this.STATUS_INVALID); + } + } + }, + + /** + * Check the form validity + * + * @returns {Boolean} + */ + isValid: function() { + var field, validatorName; + for (field in this.results) { + for (validatorName in this.results[field]) { + if (this.results[field][validatorName] == this.STATUS_NOT_VALIDATED || this.results[field][validatorName] == this.STATUS_VALIDATING) { + return false; + } + + if (this.results[field][validatorName] == this.STATUS_INVALID) { + this.invalidField = field; + return false; + } + } + } + + return true; + }, + + /** + * Update field status + * + * @param {jQuery} $field The field element + * @param {String} validatorName + * @param {String} status The status + * Can be STATUS_VALIDATING, STATUS_INVALID, STATUS_VALID + */ + updateStatus: function($field, validatorName, status) { + var that = this, + field = $field.attr('name'), + validator = this.options.fields[field].validators[validatorName], + message = validator.message || this.options.message, + $parent = $field.parents('.form-group'), + $errors = $parent.find('.help-block[data-bs-validator]'); + + switch (status) { + case this.STATUS_VALIDATING: + this.results[field][validatorName] = this.STATUS_VALIDATING; + this._disableSubmitButtons(true); + + $parent.removeClass('has-success').removeClass('has-error'); + // TODO: Show validating message + $errors.filter('.help-block[data-bs-validator="' + validatorName + '"]').html(message).hide(); + + if (this.options.feedbackIcons) { + // Show "loading" icon + $parent.find('.form-control-feedback').removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(); + } + break; + + case this.STATUS_INVALID: + this.results[field][validatorName] = this.STATUS_INVALID; + this._disableSubmitButtons(true); + + // Add has-error class to parent element + $parent.removeClass('has-success').addClass('has-error'); + + $errors.filter('[data-bs-validator="' + validatorName + '"]').html(message).show(); + + if (this.options.feedbackIcons) { + // Show "error" icon + $parent.find('.form-control-feedback').removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(); + } + break; + + case this.STATUS_VALID: + this.results[field][validatorName] = this.STATUS_VALID; + + // Hide error element + $errors.filter('[data-bs-validator="' + validatorName + '"]').hide(); + + // If the field is valid + if ($errors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bs-validator'); + return ('block' == display) || (that.results[field][v] != that.STATUS_VALID); + }).length == 0 + ) { + this._disableSubmitButtons(false); + + $parent.removeClass('has-error').addClass('has-success'); + // Show the "ok" icon + if (this.options.feedbackIcons) { + $parent.find('.form-control-feedback').removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.valid).show(); + } + } + break; + + default: + break; + } + }, + + // Useful APIs which aren't use internally + + /** + * Reset the form + * + * @param {Boolean} resetFormData Reset current form data + */ + resetForm: function(resetFormData) { + for (var field in this.options.fields) { + this.dfds[field] = {}; + this.results[field] = {}; + + // Mark all fields as not validated yet + for (var v in this.options.fields[field].validators) { + this.results[field][v] = this.STATUS_NOT_VALIDATED; + } + } + + this.invalidField = null; + this.$submitButton = null; + + // Hide all error elements + this.$form + .find('.has-error').removeClass('has-error').end() + .find('.has-success').removeClass('has-success').end() + .find('.help-block[data-bs-validator]').hide(); + + // Enable submit buttons + this._disableSubmitButtons(false); + + // Hide all feeback icons + if (this.options.feedbackIcons) { + this.$form.find('.form-control-feedback').removeClass('glyphicon-ok').removeClass('glyphicon-remove').removeClass('glyphicon-refresh').hide(); + } + + if (resetFormData) { + this.$form.get(0).reset(); + } + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(options) { + return this.each(function() { + var $this = $(this), data = $this.data('bootstrapValidator'); + if (!data) { + $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options))); + } + if ('string' == typeof options) { + data[options](); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = parseFloat(value); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {Boolean|Deferred} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (options.callback && 'function' == typeof options.callback) { + var dfd = new $.Deferred(); + dfd.resolve(options.callback.call(this, value, validator), 'callback'); + return dfd; + return options.callback.call(this, value, validator); + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.choice = { + /** + * Check if the number of checked boxes are less or more than a given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var numChoices = validator + .getFieldElements($field.attr('name')) + .filter(':checked') + .length; + if ((options.min && numChoices < options.min) || (options.max && numChoices > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + + // The Luhn Algorithm + // http://en.wikipedia.org/wiki/Luhn + value = value.replace(/\D/g, ''); + var check = 0, digit = 0, even = false, length = value.length; + + for (var n = length - 1; n >= 0; n--) { + digit = parseInt(value.charAt(n), 10); + + if (even) { + if ((digit *= 2) > 9) { + digit -= 9; + } + } + + check += digit; + even = !even; + } + + return (check % 10) == 0; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.different = { + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value != compareWith.val()) { + validator.updateStatus(compareWith, 'different', validator.STATUS_VALID); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^\d+$/.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + /** + * Return true if the input value is a valid hex color + * + * @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; + } + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value == compareWith.val()) { + validator.updateStatus(compareWith, 'identical', validator.STATUS_VALID); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value < options.value) : (value <= options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + if ('radio' == type || 'checkbox' == type) { + return validator + .getFieldElements($field.attr('name')) + .filter(':checked') + .length > 0; + } + + return $.trim($field.val()) != ''; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return options.regexp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.remote = { + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - message: The invalid message + * @returns {Boolean|Deferred} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var name = $field.attr('name'), data = options.data; + if (data == null) { + data = {}; + } + // Support dynamic data + if ('function' == typeof data) { + data = data.call(this, validator); + } + data[name] = value; + + var dfd = new $.Deferred(); + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }); + xhr.then(function(response) { + dfd.resolve(response.valid === true || response.valid === 'true', 'remote'); + }); + + dfd.fail(function() { + xhr.abort(); + }); + + return dfd; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var length = $.trim(value).length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.zipCode = { + /** + * Return true if and only if the input value is a valid country zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - country: The ISO 3166 country code + * + * Currently it supports the following countries: + * - US (United State) + * - DK (Denmark) + * - SE (Sweden) + * + * @returns {Boolean} + */ + validate: function(validateInstance, $field, options) { + var value = $field.val(); + if (value == '' || !options.country) { + return true; + } + switch (options.country.toUpperCase()) { + case 'DK': + return /^(DK(-|\s)?)?\d{4}$/i.test(value); + case 'SE': + return /^(S-)?\d{3}\s?\d{2}$/i.test(value); + case 'US': + default: + return /^\d{5}([\-]\d{4})?$/.test(value); + } + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.0/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.3.0/js/bootstrapValidator.min.js new file mode 100644 index 000000000..9e7ffba4d --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.0/js/bootstrapValidator.min.js @@ -0,0 +1,12 @@ +/** + * BootstrapValidator (http://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.3.0 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),this.dfds={},this.results={},this.invalidField=null,this.$submitButton=null,this._init(),this.STATUS_NOT_VALIDATED="NOT_VALIDATED",this.STATUS_VALIDATING="VALIDATING",this.STATUS_INVALID="INVALID",this.STATUS_VALID="VALID"};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",columns:12,feedbackIcons:null,submitButtons:'button[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){if(null!=this.options.fields){var b=this;this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit.bootstrapValidator",function(a){a.preventDefault(),b.validate()}).find(this.options.submitButtons).on("click",function(){b.$submitButton=a(this)});for(var c in this.options.fields)this._initField(c);this._setLiveValidating()}},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){this.dfds[b]={},this.results[b]={};var c=this.getFieldElements(b);if(null==c||1==c.length&&c.is(":disabled"))return delete this.options.fields[b],void delete this.dfds[b];var d,e,f,g,h=a(c[0]),i=h.parents(".form-group");if(d=i.find("label").get(0)){if(e=a(d).attr("class")){e=e.split(" ");for(var j=0;j").css("display","none").attr("data-bs-validator",k).addClass("help-block").addClass(["col-",g,"-offset-",f].join("")).addClass(["col-",g,"-",this.options.columns-f].join("")).appendTo(i)):delete this.options.fields[b].validators[k];this.options.feedbackIcons&&(i.addClass("has-feedback"),a("").css("display","none").addClass("form-control-feedback").insertAfter(a(c[c.length-1])));var l=this,m=c.attr("type"),n="radio"==m||"checkbox"==m||"SELECT"==c[0].tagName?"change":"keyup";c.on(n,function(){for(var a in l.options.fields[b].validators)l.results[b][a]=l.STATUS_NOT_VALIDATED})}},_setLiveValidating:function(){if("enabled"==this.options.live){var a=this;for(var b in this.options.fields)!function(b){var c=a.getFieldElements(b);if(c){var d=c.attr("type"),e="radio"==d||"checkbox"==d||"SELECT"==c[0].tagName?"change":"keyup";c.on(e,function(){a.validateField(b)})}}(b)}},_disableSubmitButtons:function(a){a?"disabled"!=this.options.live&&this.$form.find(this.options.submitButtons).attr("disabled","disabled"):this.$form.find(this.options.submitButtons).removeAttr("disabled")},_submit:function(){return this.isValid()?(this._disableSubmitButtons(!0),void(this.options.submitHandler&&"function"==typeof this.options.submitHandler?this.options.submitHandler.call(this,this,this.$form,this.$submitButton):this.$form.off("submit.bootstrapValidator").submit())):("submitted"==this.options.live&&(this.options.live="enabled",this._setLiveValidating()),void(this.invalidField&&this.getFieldElements(this.invalidField).focus()))},getFieldElements:function(a){var b=this.$form.find('[name="'+a+'"]');return 0==b.length?null:b},validate:function(){if(!this.options.fields)return this;this._disableSubmitButtons(!0);for(var a in this.options.fields)this.validateField(a);return this._submit(),this},validateField:function(b){var c,d,e=this,f=this.$form.find('[name="'+b+'"]'),g=a(f[0]),h=this.options.fields[b].validators;for(c in h)this.dfds[b][c]&&this.dfds[b][c].reject(),this.results[b][c]!=this.STATUS_VALID&&this.results[b][c]!=this.STATUS_INVALID&&(this.results[b][c]=this.STATUS_VALIDATING,d=a.fn.bootstrapValidator.validators[c].validate(this,g,h[c]),"object"==typeof d?(this.updateStatus(g,c,this.STATUS_VALIDATING),this.dfds[b][c]=d,d.done(function(a,c){delete e.dfds[b][c],a?e.updateStatus(g,c,e.STATUS_VALID):e.updateStatus(g,c,e.STATUS_INVALID)})):"boolean"==typeof d&&(d?this.updateStatus(g,c,this.STATUS_VALID):this.updateStatus(g,c,this.STATUS_INVALID)))},isValid:function(){var a,b;for(a in this.results)for(b in this.results[a]){if(this.results[a][b]==this.STATUS_NOT_VALIDATED||this.results[a][b]==this.STATUS_VALIDATING)return!1;if(this.results[a][b]==this.STATUS_INVALID)return this.invalidField=a,!1}return!0},updateStatus:function(b,c,d){var e=this,f=b.attr("name"),g=this.options.fields[f].validators[c],h=g.message||this.options.message,i=b.parents(".form-group"),j=i.find(".help-block[data-bs-validator]");switch(d){case this.STATUS_VALIDATING:this.results[f][c]=this.STATUS_VALIDATING,this._disableSubmitButtons(!0),i.removeClass("has-success").removeClass("has-error"),j.filter('.help-block[data-bs-validator="'+c+'"]').html(h).hide(),this.options.feedbackIcons&&i.find(".form-control-feedback").removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show();break;case this.STATUS_INVALID:this.results[f][c]=this.STATUS_INVALID,this._disableSubmitButtons(!0),i.removeClass("has-success").addClass("has-error"),j.filter('[data-bs-validator="'+c+'"]').html(h).show(),this.options.feedbackIcons&&i.find(".form-control-feedback").removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show();break;case this.STATUS_VALID:this.results[f][c]=this.STATUS_VALID,j.filter('[data-bs-validator="'+c+'"]').hide(),0==j.filter(function(){var b=a(this).css("display"),c=a(this).attr("data-bs-validator");return"block"==b||e.results[f][c]!=e.STATUS_VALID}).length&&(this._disableSubmitButtons(!1),i.removeClass("has-error").addClass("has-success"),this.options.feedbackIcons&&i.find(".form-control-feedback").removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.valid).show())}},resetForm:function(a){for(var b in this.options.fields){this.dfds[b]={},this.results[b]={};for(var c in this.options.fields[b].validators)this.results[b][c]=this.STATUS_NOT_VALIDATED}this.invalidField=null,this.$submitButton=null,this.$form.find(".has-error").removeClass("has-error").end().find(".has-success").removeClass("has-success").end().find(".help-block[data-bs-validator]").hide(),this._disableSubmitButtons(!1),this.options.feedbackIcons&&this.$form.find(".form-control-feedback").removeClass("glyphicon-ok").removeClass("glyphicon-remove").removeClass("glyphicon-refresh").hide(),a&&this.$form.get(0).reset()}},a.fn.bootstrapValidator=function(c){return this.each(function(){var d=a(this),e=d.data("bootstrapValidator");e||d.data("bootstrapValidator",e=new b(this,c)),"string"==typeof c&&e[c]()})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(b,c,d){var e=c.val();if(d.callback&&"function"==typeof d.callback){var f=new a.Deferred;return f.resolve(d.callback.call(this,e,b),"callback"),f}return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.choice={validate:function(a,b,c){var d=a.getFieldElements(b.attr("name")).filter(":checked").length;return c.min&&dc.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(a,b){var c=b.val();if(""==c)return!0;if(/[^0-9-\s]+/.test(c))return!1;c=c.replace(/\D/g,"");for(var d=0,e=0,f=!1,g=c.length,h=g-1;h>=0;h--)e=parseInt(c.charAt(h),10),f&&(e*=2)>9&&(e-=9),d+=e,f=!f;return d%10==0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d!=e.val()?(a.updateStatus(e,"different",a.STATUS_VALID),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){var c=b.val();return""==c?!0:/^\d+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={validate:function(a,b){var c=b.val();if(""==c)return!0;var d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.value:d>=c.value)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={validate:function(a,b){var c=b.val();return""==c?!0:/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d==e.val()?(a.updateStatus(e,"identical",a.STATUS_VALID),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d0:""!=a.trim(c.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.regexp={validate:function(a,b,c){var d=b.val();return""==d?!0:c.regexp.test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.remote={validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=c.attr("name"),g=d.data;null==g&&(g={}),"function"==typeof g&&(g=g.call(this,b)),g[f]=e;var h=new a.Deferred,i=a.ajax({type:"POST",url:d.url,dataType:"json",data:g});return i.then(function(a){h.resolve(a.valid===!0||"true"===a.valid,"remote")}),h.fail(function(){i.abort()}),h}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringLength={validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=a.trim(e).length;return d.min&&fd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={validate:function(a,b){var c=b.val();if(""==c)return!0;var d=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.zipCode={validate:function(a,b,c){var d=b.val();if(""==d||!c.country)return!0;switch(c.country.toUpperCase()){case"DK":return/^(DK(-|\s)?)?\d{4}$/i.test(d);case"SE":return/^(S-)?\d{3}\s?\d{2}$/i.test(d);case"US":default:return/^\d{5}([\-]\d{4})?$/.test(d)}}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.1/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.3.1/css/bootstrapValidator.css new file mode 100644 index 000000000..9cac64e4f --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.1/css/bootstrapValidator.css @@ -0,0 +1,11 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ +.bootstrap-validator-form .help-block { + margin-bottom: 0; } diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.1/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.3.1/css/bootstrapValidator.min.css new file mode 100644 index 000000000..4c96bc658 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.1/css/bootstrapValidator.min.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.3.1 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.1/css/bootstrapValidator.scss b/ajax/libs/jquery.bootstrapvalidator/0.3.1/css/bootstrapValidator.scss new file mode 100644 index 000000000..329630fb0 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.1/css/bootstrapValidator.scss @@ -0,0 +1,15 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form { + .help-block { + margin-bottom: 0; + } +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.1/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.3.1/js/bootstrapValidator.js new file mode 100644 index 000000000..56043168d --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.1/js/bootstrapValidator.js @@ -0,0 +1,1198 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.3.1 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + this.dfds = {}; // Array of deferred + this.results = {}; // Validating results + + this.invalidField = null; // First invalid field + this.$submitButton = null; // The submit button which is clicked to submit form + + this._init(); + + this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED'; + this.STATUS_VALIDATING = 'VALIDATING'; + this.STATUS_INVALID = 'INVALID'; + this.STATUS_VALID = 'VALID'; + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // Shows ok/error/loading icons based on the field validity. + // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation). + // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically. + // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later. + // + // Examples: + // - Use Glyphicons icons: + // feedbackIcons: { + // valid: 'glyphicon glyphicon-ok', + // invalid: 'glyphicon glyphicon-remove', + // validating: 'glyphicon glyphicon-refresh' + // } + // - Use FontAwesome icons: + // feedbackIcons: { + // valid: 'fa fa-check', + // invalid: 'fa fa-times', + // validating: 'fa fa-refresh' + // } + feedbackIcons: { + valid: null, + invalid: null, + validating: null + }, + + // The submit buttons selector + // These buttons will be disabled to prevent the valid form from multiple submissions + submitButtons: 'button[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submission + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating option + // Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + if (this.options.fields == null) { + return; + } + + var that = this; + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + // Disable the default submission first + .on('submit.bootstrapValidator', function(e) { + e.preventDefault(); + that.validate(); + }) + .find(this.options.submitButtons) + .on('click', function() { + that.$submitButton = $(this); + }); + + for (var field in this.options.fields) { + this._initField(field); + } + + this._setLiveValidating(); + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + this.dfds[field] = {}; + this.results[field] = {}; + + var fields = this.getFieldElements(field); + + // We don't need to validate non-existing fields + if (fields == null) { + delete this.options.fields[field]; + delete this.dfds[field]; + return; + } + + // Create help block elements for showing the error messages + var $field = $(fields[0]), + $parent = $field.parents('.form-group'), + $message = this._getMessageContainer($field); + + $field.data('bootstrapValidator.messageContainer', $message); + for (var validatorName in this.options.fields[field].validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + delete this.options.fields[field].validators[validatorName]; + continue; + } + + this.results[field][validatorName] = this.STATUS_NOT_VALIDATED; + $('') + .css('display', 'none') + .attr('data-bs-validator', validatorName) + .html(this.options.fields[field].validators[validatorName].message || this.options.message) + .addClass('help-block') + .appendTo($message); + } + + // Prepare the feedback icons + // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation) + if (this.options.feedbackIcons) { + $parent.addClass('has-feedback'); + var $icon = $('').css('display', 'none').addClass('form-control-feedback').insertAfter($(fields[fields.length - 1])); + // 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); + } + } + + if (this.options.fields[field]['enabled'] == null) { + this.options.fields[field]['enabled'] = true; + } + + // Whenever the user change the field value, mark it as not validated yet + var that = this, + type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup'; + fields.on(event, function() { + that.updateStatus($field, that.STATUS_NOT_VALIDATED, null); + }); + }, + + /** + * Get the element to place the error messages + * + * @param {jQuery} $field The field element + * @returns {jQuery} + */ + _getMessageContainer: function($field) { + var $parent = $field.parent(); + if ($parent.hasClass('form-group')) { + return $parent; + } + + var cssClasses = $parent.attr('class'); + if (!cssClasses) { + return this._getMessageContainer($parent); + } + + cssClasses = cssClasses.split(' '); + var n = cssClasses.length; + for (var i = 0; i < n; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i]) || /^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + return $parent; + } + } + + return this._getMessageContainer($parent); + }, + + /** + * Enable live validating + */ + _setLiveValidating: function() { + if ('enabled' == this.options.live) { + var that = this; + for (var field in this.options.fields) { + (function(f) { + var fields = that.getFieldElements(f); + if (fields) { + var type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup'; + + fields.on(event, function() { + that.validateField(f); + }); + } + })(field); + } + } + }, + + /** + * Disable/Enable submit buttons + * + * @param {Boolean} disabled + */ + _disableSubmitButtons: function(disabled) { + if (!disabled) { + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + } else if (this.options.live != 'disabled') { + // Don't disable if the live validating mode is disabled + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + } + }, + + /** + * Called when all validations are completed + */ + _submit: function() { + if (!this.isValid()) { + if ('submitted' == this.options.live) { + this.options.live = 'enabled'; + this._setLiveValidating(); + } + + // Focus to the first invalid field + if (this.invalidField) { + this.getFieldElements(this.invalidField).focus(); + } + return; + } + + this._disableSubmitButtons(true); + + // Call the custom submission if enabled + if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + this.options.submitHandler.call(this, this, this.$form, this.$submitButton); + } else { + // Submit form + this.$form.off('submit.bootstrapValidator').submit(); + } + }, + + // --- Public methods --- + + /** + * Retrieve the field elements by given name + * + * @param {String} field The field name + * @returns {null|jQuery[]} + */ + getFieldElements: function(field) { + var fields = this.$form.find('[name="' + field + '"]'); + return (fields.length == 0) ? null : fields; + }, + + /** + * Validate the form + * + * @return {BootstrapValidator} + */ + validate: function() { + if (!this.options.fields) { + return this; + } + this._disableSubmitButtons(true); + + for (var field in this.options.fields) { + this.validateField(field); + } + + this._submit(); + return this; + }, + + /** + * Validate given field + * + * @param {String} field The field name + */ + validateField: function(field) { + if (!this.options.fields[field]['enabled']) { + return; + } + + var that = this, + fields = this.getFieldElements(field), + $field = $(fields[0]), + validators = this.options.fields[field].validators, + validatorName, + validateResult; + + // We don't need to validate disabled field + if (fields.length == 1 && fields.is(':disabled')) { + delete this.options.fields[field]; + delete this.dfds[field]; + return; + } + + for (validatorName in validators) { + if (this.dfds[field][validatorName]) { + this.dfds[field][validatorName].reject(); + } + + // Don't validate field if it is already done + if (this.results[field][validatorName] == this.STATUS_VALID || this.results[field][validatorName] == this.STATUS_INVALID) { + continue; + } + + this.results[field][validatorName] = this.STATUS_VALIDATING; + validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]); + + if ('object' == typeof validateResult) { + this.updateStatus($field, this.STATUS_VALIDATING, validatorName); + this.dfds[field][validatorName] = validateResult; + + validateResult.done(function(isValid, v) { + // v is validator name + delete that.dfds[field][v]; + that.updateStatus($field, isValid ? that.STATUS_VALID : that.STATUS_INVALID, v); + + if (isValid && 'disabled' == that.options.live) { + that._submit(); + } + }); + } else if ('boolean' == typeof validateResult) { + this.updateStatus($field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName); + } + } + }, + + /** + * Check the form validity + * + * @returns {Boolean} + */ + isValid: function() { + var field, validatorName; + for (field in this.results) { + if (!this.options.fields[field]['enabled']) { + continue; + } + + for (validatorName in this.results[field]) { + if (this.results[field][validatorName] == this.STATUS_NOT_VALIDATED || this.results[field][validatorName] == this.STATUS_VALIDATING) { + return false; + } + + if (this.results[field][validatorName] == this.STATUS_INVALID) { + this.invalidField = field; + return false; + } + } + } + + return true; + }, + + /** + * Update field status + * + * @param {String|jQuery} field The field name or field element + * @param {String} status The status + * Can be 'not_validated', 'validating', 'invalid' or 'valid' + * @param {String|null} validatorName The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateStatus: function(field, status, validatorName) { + var $field = ('string' == typeof field) ? this.getFieldElements(field) : field, + that = this, + field = $field.attr('name'), + $parent = $field.parents('.form-group'), + $message = $field.data('bootstrapValidator.messageContainer'), + $errors = $message.find('.help-block[data-bs-validator]'); + + // Update status + if (validatorName) { + this.results[field][validatorName] = status; + } else { + for (var v in this.options.fields[field].validators) { + this.results[field][v] = status; + } + } + + // Show/hide error elements and feedback icons + switch (status) { + case this.STATUS_VALIDATING: + this._disableSubmitButtons(true); + $parent.removeClass('has-success').removeClass('has-error'); + // TODO: Show validating message + validatorName ? $errors.filter('.help-block[data-bs-validator="' + validatorName + '"]').hide() : $errors.hide(); + $message.find('.form-control-feedback').removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(); + break; + + case this.STATUS_INVALID: + this._disableSubmitButtons(true); + $parent.removeClass('has-success').addClass('has-error'); + validatorName ? $errors.filter('[data-bs-validator="' + validatorName + '"]').show() : $errors.show(); + $message.find('.form-control-feedback').removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(); + break; + + case this.STATUS_VALID: + validatorName ? $errors.filter('[data-bs-validator="' + validatorName + '"]').hide() : $errors.hide(); + + // If the field is valid + if ($errors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bs-validator'); + return ('block' == display) || (that.results[field][v] != that.STATUS_VALID); + }).length == 0 + ) { + this._disableSubmitButtons(false); + $parent.removeClass('has-error').addClass('has-success'); + $message.find('.form-control-feedback').removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.valid).show(); + } + break; + + case this.STATUS_NOT_VALIDATED: + default: + this._disableSubmitButtons(false); + $parent.removeClass('has-success').removeClass('has-error'); + validatorName ? $errors.filter('.help-block[data-bs-validator="' + validatorName + '"]').hide() : $errors.hide(); + $message.find('.form-control-feedback').removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide(); + break; + } + + return this; + }, + + // Useful APIs which aren't used internally + + /** + * Reset the form + * + * @param {Boolean} resetFormData Reset current form data + * @return {BootstrapValidator} + */ + resetForm: function(resetFormData) { + var field, $field, type; + for (field in this.options.fields) { + this.dfds[field] = {}; + this.results[field] = {}; + + $field = this.getFieldElements(field); + // Mark field as not validated yet + this.updateStatus($field, this.STATUS_NOT_VALIDATED, null); + + if (resetFormData) { + type = $field.attr('type'); + ('radio' == type || 'checkbox' == type) ? $field.removeAttr('checked').removeAttr('selected') : $field.val(''); + } + } + + this.invalidField = null; + this.$submitButton = null; + + // Enable submit buttons + this._disableSubmitButtons(false); + + return this; + }, + + /** + * Enable/Disable all validators to given field + * + * @param {String} field The field name + * @param {Boolean} enabled Enable/Disable field validators + * @return {BootstrapValidator} + */ + enableFieldValidators: function(field, enabled) { + this.options.fields[field]['enabled'] = enabled; + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + return this; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(options) { + return this.each(function() { + var $this = $(this), data = $this.data('bootstrapValidator'); + if (!data) { + $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options))); + } + if ('string' == typeof options) { + data[options](); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = parseFloat(value); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {Boolean|Deferred} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (options.callback && 'function' == typeof options.callback) { + var dfd = new $.Deferred(); + dfd.resolve(options.callback.call(this, value, validator), 'callback'); + return dfd; + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.choice = { + /** + * Check if the number of checked boxes are less or more than a given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var numChoices = validator + .getFieldElements($field.attr('name')) + .filter(':checked') + .length; + if ((options.min && numChoices < options.min) || (options.max && numChoices > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + + // The Luhn Algorithm + // http://en.wikipedia.org/wiki/Luhn + value = value.replace(/\D/g, ''); + var check = 0, digit = 0, even = false, length = value.length; + + for (var n = length - 1; n >= 0; n--) { + digit = parseInt(value.charAt(n), 10); + + if (even) { + if ((digit *= 2) > 9) { + digit -= 9; + } + } + + check += digit; + even = !even; + } + + return (check % 10) == 0; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.date = { + /** + * Return true if the input value is valid date + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - format: The date format. Default is MM/DD/YYYY + * Support the following formats: + * YYYY/DD/MM + * YYYY/DD/MM h:m A + * YYYY/MM/DD + * YYYY/MM/DD h:m A + * + * YYYY-DD-MM + * YYYY-DD-MM h:m A + * YYYY-MM-DD + * YYYY-MM-DD h:m A + * + * MM/DD/YYYY + * MM/DD/YYYY h:m A + * DD/MM/YYYY + * DD/MM/YYYY h:m A + * + * MM-DD-YYYY + * MM-DD-YYYY h:m A + * DD-MM-YYYY + * DD-MM-YYYY h:m A + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + // Determine the separator + options.format = options.format || 'MM/DD/YYYY'; + var separator = (options.format.indexOf('/') != -1) + ? '/' + : ((options.format.indexOf('-') != -1) ? '-' : null); + if (separator == null) { + return false; + } + + var month, day, year, minutes = null, hours = null, matches; + switch (true) { + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/DD/MM'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-DD-MM'): + year = matches[1]; day = matches[2]; month = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'DD/MM/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'DD-MM-YYYY'): + day = matches[1]; month = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/MM/DD'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-MM-DD'): + year = matches[1]; month = matches[2]; day = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'MM/DD/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'MM-DD-YYYY'): + month = matches[1]; day = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/DD/MM h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-DD-MM h:m A'): + year = matches[1]; day = matches[2]; month = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD/MM/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD-MM-YYYY h:m A'): + day = matches[1]; month = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/MM/DD h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-MM-DD h:m A'): + year = matches[1]; month = matches[2]; day = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM/DD/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM-DD-YYYY h:m A'): + month = matches[1]; day = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + default: + return false; + } + + // Validate hours and minutes + if (hours && minutes) { + hours = parseInt(hours, 10); + minutes = parseInt(minutes, 10); + if (hours < 1 || hours > 12 || minutes < 0 || minutes > 59) { + return false; + } + } + + // Validate day, month, and year + day = parseInt(day, 10); + month = parseInt(month, 10); + year = parseInt(year, 10); + + if (year < 1000 || year > 9999 || month == 0 || month > 12) { + return false; + } + + var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + // Update the number of days in Feb of leap year + if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) { + numDays[1] = 29; + } + + // Check the day + return (day > 0 && day <= numDays[month - 1]); + } + }; +}(window.jQuery)); + +;(function($) { + $.fn.bootstrapValidator.validators.different = { + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value != compareWith.val()) { + validator.updateStatus(compareWith, validator.STATUS_VALID, 'different'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^\d+$/.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + /** + * Return true if the input value is a valid hex color + * + * @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; + } + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value == compareWith.val()) { + validator.updateStatus(compareWith, validator.STATUS_VALID, 'identical'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value < options.value) : (value <= options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + if ('radio' == type || 'checkbox' == type) { + return validator + .getFieldElements($field.attr('name')) + .filter(':checked') + .length > 0; + } + + return $.trim($field.val()) != ''; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return options.regexp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.remote = { + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - message: The invalid message + * @returns {Boolean|Deferred} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var name = $field.attr('name'), data = options.data; + if (data == null) { + data = {}; + } + // Support dynamic data + if ('function' == typeof data) { + data = data.call(this, validator); + } + data[name] = value; + + var dfd = new $.Deferred(); + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }); + xhr.then(function(response) { + dfd.resolve(response.valid === true || response.valid === 'true', 'remote'); + }); + + dfd.fail(function() { + xhr.abort(); + }); + + return dfd; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var length = $.trim(value).length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.zipCode = { + /** + * Return true if and only if the input value is a valid country zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - country: The ISO 3166 country code + * + * Currently it supports the following countries: + * - US (United State) + * - DK (Denmark) + * - SE (Sweden) + * + * @returns {Boolean} + */ + validate: function(validateInstance, $field, options) { + var value = $field.val(); + if (value == '' || !options.country) { + return true; + } + switch (options.country.toUpperCase()) { + case 'DK': + return /^(DK(-|\s)?)?\d{4}$/i.test(value); + case 'SE': + return /^(S-)?\d{3}\s?\d{2}$/i.test(value); + case 'US': + default: + return /^\d{5}([\-]\d{4})?$/.test(value); + } + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.1/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.3.1/js/bootstrapValidator.min.js new file mode 100644 index 000000000..cc390afc9 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.1/js/bootstrapValidator.min.js @@ -0,0 +1,12 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.3.1 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),this.dfds={},this.results={},this.invalidField=null,this.$submitButton=null,this._init(),this.STATUS_NOT_VALIDATED="NOT_VALIDATED",this.STATUS_VALIDATING="VALIDATING",this.STATUS_INVALID="INVALID",this.STATUS_VALID="VALID"};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",feedbackIcons:{valid:null,invalid:null,validating:null},submitButtons:'button[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){if(null!=this.options.fields){var b=this;this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit.bootstrapValidator",function(a){a.preventDefault(),b.validate()}).find(this.options.submitButtons).on("click",function(){b.$submitButton=a(this)});for(var c in this.options.fields)this._initField(c);this._setLiveValidating()}},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){this.dfds[b]={},this.results[b]={};var c=this.getFieldElements(b);if(null==c)return delete this.options.fields[b],void delete this.dfds[b];var d=a(c[0]),e=d.parents(".form-group"),f=this._getMessageContainer(d);d.data("bootstrapValidator.messageContainer",f);for(var g in this.options.fields[b].validators)a.fn.bootstrapValidator.validators[g]?(this.results[b][g]=this.STATUS_NOT_VALIDATED,a("").css("display","none").attr("data-bs-validator",g).html(this.options.fields[b].validators[g].message||this.options.message).addClass("help-block").appendTo(f)):delete this.options.fields[b].validators[g];if(this.options.feedbackIcons){e.addClass("has-feedback");var h=a("").css("display","none").addClass("form-control-feedback").insertAfter(a(c[c.length-1]));0==e.find("label").length&&h.css("top",0)}null==this.options.fields[b].enabled&&(this.options.fields[b].enabled=!0);var i=this,j=c.attr("type"),k="radio"==j||"checkbox"==j||"SELECT"==c[0].tagName?"change":"keyup";c.on(k,function(){i.updateStatus(d,i.STATUS_NOT_VALIDATED,null)})}},_getMessageContainer:function(a){var b=a.parent();if(b.hasClass("form-group"))return b;var c=b.attr("class");if(!c)return this._getMessageContainer(b);c=c.split(" ");for(var d=c.length,e=0;d>e;e++)if(/^col-(xs|sm|md|lg)-\d+$/.test(c[e])||/^col-(xs|sm|md|lg)-offset-\d+$/.test(c[e]))return b;return this._getMessageContainer(b)},_setLiveValidating:function(){if("enabled"==this.options.live){var a=this;for(var b in this.options.fields)!function(b){var c=a.getFieldElements(b);if(c){var d=c.attr("type"),e="radio"==d||"checkbox"==d||"SELECT"==c[0].tagName?"change":"keyup";c.on(e,function(){a.validateField(b)})}}(b)}},_disableSubmitButtons:function(a){a?"disabled"!=this.options.live&&this.$form.find(this.options.submitButtons).attr("disabled","disabled"):this.$form.find(this.options.submitButtons).removeAttr("disabled")},_submit:function(){return this.isValid()?(this._disableSubmitButtons(!0),void(this.options.submitHandler&&"function"==typeof this.options.submitHandler?this.options.submitHandler.call(this,this,this.$form,this.$submitButton):this.$form.off("submit.bootstrapValidator").submit())):("submitted"==this.options.live&&(this.options.live="enabled",this._setLiveValidating()),void(this.invalidField&&this.getFieldElements(this.invalidField).focus()))},getFieldElements:function(a){var b=this.$form.find('[name="'+a+'"]');return 0==b.length?null:b},validate:function(){if(!this.options.fields)return this;this._disableSubmitButtons(!0);for(var a in this.options.fields)this.validateField(a);return this._submit(),this},validateField:function(b){if(this.options.fields[b].enabled){var c,d,e=this,f=this.getFieldElements(b),g=a(f[0]),h=this.options.fields[b].validators;if(1==f.length&&f.is(":disabled"))return delete this.options.fields[b],void delete this.dfds[b];for(c in h)this.dfds[b][c]&&this.dfds[b][c].reject(),this.results[b][c]!=this.STATUS_VALID&&this.results[b][c]!=this.STATUS_INVALID&&(this.results[b][c]=this.STATUS_VALIDATING,d=a.fn.bootstrapValidator.validators[c].validate(this,g,h[c]),"object"==typeof d?(this.updateStatus(g,this.STATUS_VALIDATING,c),this.dfds[b][c]=d,d.done(function(a,c){delete e.dfds[b][c],e.updateStatus(g,a?e.STATUS_VALID:e.STATUS_INVALID,c),a&&"disabled"==e.options.live&&e._submit()})):"boolean"==typeof d&&this.updateStatus(g,d?this.STATUS_VALID:this.STATUS_INVALID,c))}},isValid:function(){var a,b;for(a in this.results)if(this.options.fields[a].enabled)for(b in this.results[a]){if(this.results[a][b]==this.STATUS_NOT_VALIDATED||this.results[a][b]==this.STATUS_VALIDATING)return!1;if(this.results[a][b]==this.STATUS_INVALID)return this.invalidField=a,!1}return!0},updateStatus:function(b,c,d){var e="string"==typeof b?this.getFieldElements(b):b,f=this,b=e.attr("name"),g=e.parents(".form-group"),h=e.data("bootstrapValidator.messageContainer"),i=h.find(".help-block[data-bs-validator]");if(d)this.results[b][d]=c;else for(var j in this.options.fields[b].validators)this.results[b][j]=c;switch(c){case this.STATUS_VALIDATING:this._disableSubmitButtons(!0),g.removeClass("has-success").removeClass("has-error"),d?i.filter('.help-block[data-bs-validator="'+d+'"]').hide():i.hide(),h.find(".form-control-feedback").removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show();break;case this.STATUS_INVALID:this._disableSubmitButtons(!0),g.removeClass("has-success").addClass("has-error"),d?i.filter('[data-bs-validator="'+d+'"]').show():i.show(),h.find(".form-control-feedback").removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show();break;case this.STATUS_VALID:d?i.filter('[data-bs-validator="'+d+'"]').hide():i.hide(),0==i.filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bs-validator");return"block"==c||f.results[b][d]!=f.STATUS_VALID}).length&&(this._disableSubmitButtons(!1),g.removeClass("has-error").addClass("has-success"),h.find(".form-control-feedback").removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.valid).show());break;case this.STATUS_NOT_VALIDATED:default:this._disableSubmitButtons(!1),g.removeClass("has-success").removeClass("has-error"),d?i.filter('.help-block[data-bs-validator="'+d+'"]').hide():i.hide(),h.find(".form-control-feedback").removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide()}return this},resetForm:function(a){var b,c,d;for(b in this.options.fields)this.dfds[b]={},this.results[b]={},c=this.getFieldElements(b),this.updateStatus(c,this.STATUS_NOT_VALIDATED,null),a&&(d=c.attr("type"),"radio"==d||"checkbox"==d?c.removeAttr("checked").removeAttr("selected"):c.val(""));return this.invalidField=null,this.$submitButton=null,this._disableSubmitButtons(!1),this},enableFieldValidators:function(a,b){return this.options.fields[a].enabled=b,this.updateStatus(a,this.STATUS_NOT_VALIDATED,null),this}},a.fn.bootstrapValidator=function(c){return this.each(function(){var d=a(this),e=d.data("bootstrapValidator");e||d.data("bootstrapValidator",e=new b(this,c)),"string"==typeof c&&e[c]()})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(b,c,d){var e=c.val();if(d.callback&&"function"==typeof d.callback){var f=new a.Deferred;return f.resolve(d.callback.call(this,e,b),"callback"),f}return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.choice={validate:function(a,b,c){var d=a.getFieldElements(b.attr("name")).filter(":checked").length;return c.min&&dc.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(a,b){var c=b.val();if(""==c)return!0;if(/[^0-9-\s]+/.test(c))return!1;c=c.replace(/\D/g,"");for(var d=0,e=0,f=!1,g=c.length,h=g-1;h>=0;h--)e=parseInt(c.charAt(h),10),f&&(e*=2)>9&&(e-=9),d+=e,f=!f;return d%10==0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.date={validate:function(a,b,c){var d=b.val();if(""==d)return!0;c.format=c.format||"MM/DD/YYYY";var e=-1!=c.format.indexOf("/")?"/":-1!=c.format.indexOf("-")?"-":null;if(null==e)return!1;var f,g,h,i,j=null,k=null;switch(!0){case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/DD/MM"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-DD-MM"==c.format:h=i[1],g=i[2],f=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"DD/MM/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"DD-MM-YYYY"==c.format:g=i[1],f=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/MM/DD"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-MM-DD"==c.format:h=i[1],f=i[2],g=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"MM/DD/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"MM-DD-YYYY"==c.format:f=i[1],g=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/DD/MM h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-DD-MM h:m A"==c.format:h=i[1],g=i[2],f=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD/MM/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD-MM-YYYY h:m A"==c.format:g=i[1],f=i[2],h=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/MM/DD h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-MM-DD h:m A"==c.format:h=i[1],f=i[2],g=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM/DD/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM-DD-YYYY h:m A"==c.format:f=i[1],g=i[2],h=i[3],k=i[4],j=i[5];break;default:return!1}if(k&&j&&(k=parseInt(k,10),j=parseInt(j,10),1>k||k>12||0>j||j>59))return!1;if(g=parseInt(g,10),f=parseInt(f,10),h=parseInt(h,10),1e3>h||h>9999||0==f||f>12)return!1;var l=[31,28,31,30,31,30,31,31,30,31,30,31];return(h%400==0||h%100!=0&&h%4==0)&&(l[1]=29),g>0&&g<=l[f-1]}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d!=e.val()?(a.updateStatus(e,a.STATUS_VALID,"different"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){var c=b.val();return""==c?!0:/^\d+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={validate:function(a,b){var c=b.val();if(""==c)return!0;var d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.value:d>=c.value)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={validate:function(a,b){var c=b.val();return""==c?!0:/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d==e.val()?(a.updateStatus(e,a.STATUS_VALID,"identical"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d0:""!=a.trim(c.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.regexp={validate:function(a,b,c){var d=b.val();return""==d?!0:c.regexp.test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.remote={validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=c.attr("name"),g=d.data;null==g&&(g={}),"function"==typeof g&&(g=g.call(this,b)),g[f]=e;var h=new a.Deferred,i=a.ajax({type:"POST",url:d.url,dataType:"json",data:g});return i.then(function(a){h.resolve(a.valid===!0||"true"===a.valid,"remote")}),h.fail(function(){i.abort()}),h}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringLength={validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=a.trim(e).length;return d.min&&fd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={validate:function(a,b){var c=b.val();if(""==c)return!0;var d=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.zipCode={validate:function(a,b,c){var d=b.val();if(""==d||!c.country)return!0;switch(c.country.toUpperCase()){case"DK":return/^(DK(-|\s)?)?\d{4}$/i.test(d);case"SE":return/^(S-)?\d{3}\s?\d{2}$/i.test(d);case"US":default:return/^\d{5}([\-]\d{4})?$/.test(d)}}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.2/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.3.2/css/bootstrapValidator.css new file mode 100644 index 000000000..20b84ba8d --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.2/css/bootstrapValidator.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form .help-block { + margin-bottom: 0; +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.2/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.3.2/css/bootstrapValidator.min.css new file mode 100644 index 000000000..4d8238532 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.2/css/bootstrapValidator.min.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.3.2 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.2/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.3.2/js/bootstrapValidator.js new file mode 100644 index 000000000..3059e8ecc --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.2/js/bootstrapValidator.js @@ -0,0 +1,1598 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.3.2 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + this.dfds = {}; // Array of deferred + this.results = {}; // Validating results + + this.invalidField = null; // First invalid field + this.$submitButton = null; // The submit button which is clicked to submit form + + this._init(); + + this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED'; + this.STATUS_VALIDATING = 'VALIDATING'; + this.STATUS_INVALID = 'INVALID'; + this.STATUS_VALID = 'VALID'; + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // Shows ok/error/loading icons based on the field validity. + // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation). + // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically. + // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later. + // + // Examples: + // - Use Glyphicons icons: + // feedbackIcons: { + // valid: 'glyphicon glyphicon-ok', + // invalid: 'glyphicon glyphicon-remove', + // validating: 'glyphicon glyphicon-refresh' + // } + // - Use FontAwesome icons: + // feedbackIcons: { + // valid: 'fa fa-check', + // invalid: 'fa fa-times', + // validating: 'fa fa-refresh' + // } + feedbackIcons: { + valid: null, + invalid: null, + validating: null + }, + + // The submit buttons selector + // These buttons will be disabled to prevent the valid form from multiple submissions + submitButtons: 'button[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submission + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating option + // Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + if (this.options.fields == null) { + return; + } + + var that = this; + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + // Disable the default submission first + .on('submit.bootstrapValidator', function(e) { + e.preventDefault(); + that.validate(); + }) + .find(this.options.submitButtons) + .on('click', function() { + that.$submitButton = $(this); + }); + + for (var field in this.options.fields) { + this._initField(field); + } + + this._setLiveValidating(); + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + this.dfds[field] = {}; + this.results[field] = {}; + + var fields = this.getFieldElements(field); + + // We don't need to validate non-existing fields + if (fields == null) { + delete this.options.fields[field]; + delete this.dfds[field]; + return; + } + + fields.attr('data-bv-field', field); + + // Create help block elements for showing the error messages + var $field = $(fields[0]), + $parent = $field.parents('.form-group'), + // Allow user to indicate where the error messages are shown + $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field); + + $field.data('bootstrapValidator.messageContainer', $message); + for (var validatorName in this.options.fields[field].validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + delete this.options.fields[field].validators[validatorName]; + continue; + } + + this.results[field][validatorName] = this.STATUS_NOT_VALIDATED; + $('') + .css('display', 'none') + .attr('data-bv-validator', validatorName) + .html(this.options.fields[field].validators[validatorName].message || this.options.message) + .addClass('help-block') + .appendTo($message); + } + + // Prepare the feedback icons + // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation) + if (this.options.feedbackIcons + && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid) + { + $parent.addClass('has-feedback'); + var $icon = $('').css('display', 'none').addClass('form-control-feedback').attr('data-bv-field', field).insertAfter($(fields[fields.length - 1])); + // 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); + } + } + + if (this.options.fields[field]['enabled'] == null) { + this.options.fields[field]['enabled'] = true; + } + + // Whenever the user change the field value, mark it as not validated yet + var that = this, + type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup'; + fields.on(event + '.bootstrapValidator', function() { + that.updateStatus($field, that.STATUS_NOT_VALIDATED, null); + }); + }, + + /** + * Get the element to place the error messages + * + * @param {jQuery} $field The field element + * @returns {jQuery} + */ + _getMessageContainer: function($field) { + var $parent = $field.parent(); + if ($parent.hasClass('form-group')) { + return $parent; + } + + var cssClasses = $parent.attr('class'); + if (!cssClasses) { + return this._getMessageContainer($parent); + } + + cssClasses = cssClasses.split(' '); + var n = cssClasses.length; + for (var i = 0; i < n; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i]) || /^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + return $parent; + } + } + + return this._getMessageContainer($parent); + }, + + /** + * Enable live validating + */ + _setLiveValidating: function() { + if ('enabled' == this.options.live) { + var that = this; + for (var field in this.options.fields) { + (function(f) { + var fields = that.getFieldElements(f); + if (fields) { + var type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup'; + + fields.on(event + '.bootstrapValidator', function() { + that.validateField(f); + }); + } + })(field); + } + } + }, + + /** + * Disable/Enable submit buttons + * + * @param {Boolean} disabled + */ + _disableSubmitButtons: function(disabled) { + if (!disabled) { + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + } else if (this.options.live != 'disabled') { + // Don't disable if the live validating mode is disabled + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + } + }, + + /** + * Called when all validations are completed + */ + _submit: function() { + if (!this.isValid()) { + if ('submitted' == this.options.live) { + this.options.live = 'enabled'; + this._setLiveValidating(); + } + + // Focus to the first invalid field + if (this.invalidField) { + this.getFieldElements(this.invalidField).focus(); + } + return; + } + + this._disableSubmitButtons(true); + + // Call the custom submission if enabled + if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + this.options.submitHandler.call(this, this, this.$form, this.$submitButton); + } else { + // Submit form + this.$form.off('submit.bootstrapValidator').submit(); + } + }, + + // --- Public methods --- + + /** + * Retrieve the field elements by given name + * + * @param {String} field The field name + * @returns {null|jQuery[]} + */ + getFieldElements: function(field) { + var fields = this.$form.find(this.options.fields[field].selector || '[name="' + field + '"]'); + return (fields.length == 0) ? null : fields; + }, + + /** + * Validate the form + * + * @return {BootstrapValidator} + */ + validate: function() { + if (!this.options.fields) { + return this; + } + this._disableSubmitButtons(true); + + for (var field in this.options.fields) { + this.validateField(field); + } + + this._submit(); + return this; + }, + + /** + * Validate given field + * + * @param {String} field The field name + */ + validateField: function(field) { + if (!this.options.fields[field]['enabled']) { + return; + } + + var that = this, + fields = this.getFieldElements(field), + $field = $(fields[0]), + validators = this.options.fields[field].validators, + validatorName, + validateResult; + + // We don't need to validate disabled field + if (fields.length == 1 && fields.is(':disabled')) { + delete this.options.fields[field]; + delete this.dfds[field]; + return; + } + + for (validatorName in validators) { + if (this.dfds[field][validatorName]) { + this.dfds[field][validatorName].reject(); + } + + // Don't validate field if it is already done + if (this.results[field][validatorName] == this.STATUS_VALID || this.results[field][validatorName] == this.STATUS_INVALID) { + continue; + } + + this.results[field][validatorName] = this.STATUS_VALIDATING; + validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]); + + if ('object' == typeof validateResult) { + this.updateStatus($field, this.STATUS_VALIDATING, validatorName); + this.dfds[field][validatorName] = validateResult; + + validateResult.done(function(isValid, v) { + // v is validator name + delete that.dfds[field][v]; + that.updateStatus($field, isValid ? that.STATUS_VALID : that.STATUS_INVALID, v); + + if (isValid && 'disabled' == that.options.live) { + that._submit(); + } + }); + } else if ('boolean' == typeof validateResult) { + this.updateStatus($field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName); + } + } + }, + + /** + * Check the form validity + * + * @returns {Boolean} + */ + isValid: function() { + var field, validatorName; + for (field in this.results) { + if (!this.options.fields[field]['enabled']) { + continue; + } + + for (validatorName in this.results[field]) { + if (this.results[field][validatorName] == this.STATUS_NOT_VALIDATED || this.results[field][validatorName] == this.STATUS_VALIDATING) { + return false; + } + + if (this.results[field][validatorName] == this.STATUS_INVALID) { + this.invalidField = field; + return false; + } + } + } + + return true; + }, + + /** + * Update field status + * + * @param {String|jQuery} field The field name or field element + * @param {String} status The status + * Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String|null} validatorName The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateStatus: function(field, status, validatorName) { + var $field = ('string' == typeof field) ? this.getFieldElements(field) : field, + that = this, + field = $field.attr('data-bv-field'), + $parent = $field.parents('.form-group'), + $message = $field.data('bootstrapValidator.messageContainer'), + $errors = $message.find('.help-block[data-bv-validator]'), + $icon = $parent.find('.form-control-feedback[data-bv-field="' + field + '"]'); + + // Update status + if (validatorName) { + this.results[field][validatorName] = status; + } else { + for (var v in this.options.fields[field].validators) { + this.results[field][v] = status; + } + } + + // Show/hide error elements and feedback icons + switch (status) { + case this.STATUS_VALIDATING: + this._disableSubmitButtons(true); + $parent.removeClass('has-success').removeClass('has-error'); + // TODO: Show validating message + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(); + } + break; + + case this.STATUS_INVALID: + this._disableSubmitButtons(true); + $parent.removeClass('has-success').addClass('has-error'); + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').show() : $errors.show(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(); + } + break; + + case this.STATUS_VALID: + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + + // If the field is valid + if ($errors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || (that.results[field][v] != that.STATUS_VALID); + }).length == 0 + ) { + this._disableSubmitButtons(false); + $parent.removeClass('has-error').addClass('has-success'); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.valid).show(); + } + } + break; + + case this.STATUS_NOT_VALIDATED: + default: + this._disableSubmitButtons(false); + $parent.removeClass('has-success').removeClass('has-error'); + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide(); + } + break; + } + + return this; + }, + + // Useful APIs which aren't used internally + + /** + * Reset the form + * + * @param {Boolean} resetFormData Reset current form data + * @return {BootstrapValidator} + */ + resetForm: function(resetFormData) { + var field, $field, type; + for (field in this.options.fields) { + this.dfds[field] = {}; + this.results[field] = {}; + + $field = this.getFieldElements(field); + // Mark field as not validated yet + this.updateStatus($field, this.STATUS_NOT_VALIDATED, null); + + if (resetFormData) { + type = $field.attr('type'); + ('radio' == type || 'checkbox' == type) ? $field.removeAttr('checked').removeAttr('selected') : $field.val(''); + } + } + + this.invalidField = null; + this.$submitButton = null; + + // Enable submit buttons + this._disableSubmitButtons(false); + + return this; + }, + + /** + * Enable/Disable all validators to given field + * + * @param {String} field The field name + * @param {Boolean} enabled Enable/Disable field validators + * @return {BootstrapValidator} + */ + enableFieldValidators: function(field, enabled) { + this.options.fields[field]['enabled'] = enabled; + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + return this; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(options) { + return this.each(function() { + var $this = $(this), data = $this.data('bootstrapValidator'); + if (!data) { + $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options))); + } + if ('string' == typeof options) { + data[options](); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.base64 = { + /** + * Return true if the input value is a base 64 encoded string. + * + * @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; + } + + return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = parseFloat(value); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {Boolean|Deferred} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (options.callback && 'function' == typeof options.callback) { + var dfd = new $.Deferred(); + dfd.resolve(options.callback.call(this, value, validator), 'callback'); + return dfd; + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.choice = { + /** + * Check if the number of checked boxes are less or more than a given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var numChoices = validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length; + if ((options.min && numChoices < options.min) || (options.max && numChoices > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + value = value.replace(/\D/g, ''); + + // Validate the check sum + // The Luhn Algorithm + // http://en.wikipedia.org/wiki/Luhn + var check = 0, digit = 0, even = false, length = value.length; + + for (var n = length - 1; n >= 0; n--) { + digit = parseInt(value.charAt(n), 10); + + if (even) { + if ((digit *= 2) > 9) { + digit -= 9; + } + } + + check += digit; + even = !even; + } + + if ((check % 10) != 0) { + return false; + } + + // Validate the card number based on prefix (IIN ranges) and length + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + + var type, i; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (value.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(value.length) != -1) // and length + { + return true; + } + } + } + + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.cvv = { + /** + * Return true if the input value is a valid CVV number. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - creditCardField: The credit card number field. It can be null + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^[0-9]{3,4}$/.test(value)) { + return false; + } + + if (!options.creditCardField) { + return true; + } + + // Get the credit card number + var creditCard = validator.getFieldElements(options.creditCardField).val(); + if (creditCard == '') { + return true; + } + + // Supported credit card types + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + var type, i, creditCardType = null; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (creditCard.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(creditCard.length) != -1) // and length + { + creditCardType = type; + break; + } + } + } + + return (creditCardType == null) + ? false + : (('AMERICAN_EXPRESS' == creditCardType) ? (value.length == 4) : (value.length == 3)); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.date = { + /** + * Return true if the input value is valid date + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - format: The date format. Default is MM/DD/YYYY + * Support the following formats: + * YYYY/DD/MM + * YYYY/DD/MM h:m A + * YYYY/MM/DD + * YYYY/MM/DD h:m A + * + * YYYY-DD-MM + * YYYY-DD-MM h:m A + * YYYY-MM-DD + * YYYY-MM-DD h:m A + * + * MM/DD/YYYY + * MM/DD/YYYY h:m A + * DD/MM/YYYY + * DD/MM/YYYY h:m A + * + * MM-DD-YYYY + * MM-DD-YYYY h:m A + * DD-MM-YYYY + * DD-MM-YYYY h:m A + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + // Determine the separator + options.format = options.format || 'MM/DD/YYYY'; + var separator = (options.format.indexOf('/') != -1) + ? '/' + : ((options.format.indexOf('-') != -1) ? '-' : null); + if (separator == null) { + return false; + } + + var month, day, year, minutes = null, hours = null, matches; + switch (true) { + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/DD/MM'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-DD-MM'): + year = matches[1]; day = matches[2]; month = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'DD/MM/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'DD-MM-YYYY'): + day = matches[1]; month = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/MM/DD'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-MM-DD'): + year = matches[1]; month = matches[2]; day = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'MM/DD/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'MM-DD-YYYY'): + month = matches[1]; day = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/DD/MM h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-DD-MM h:m A'): + year = matches[1]; day = matches[2]; month = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD/MM/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD-MM-YYYY h:m A'): + day = matches[1]; month = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/MM/DD h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-MM-DD h:m A'): + year = matches[1]; month = matches[2]; day = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM/DD/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM-DD-YYYY h:m A'): + month = matches[1]; day = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + default: + return false; + } + + // Validate hours and minutes + if (hours && minutes) { + hours = parseInt(hours, 10); + minutes = parseInt(minutes, 10); + if (hours < 1 || hours > 12 || minutes < 0 || minutes > 59) { + return false; + } + } + + // Validate day, month, and year + day = parseInt(day, 10); + month = parseInt(month, 10); + year = parseInt(year, 10); + + if (year < 1000 || year > 9999 || month == 0 || month > 12) { + return false; + } + + var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + // Update the number of days in Feb of leap year + if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) { + numDays[1] = 29; + } + + // Check the day + return (day > 0 && day <= numDays[month - 1]); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.different = { + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value != compareWith.val()) { + validator.updateStatus(compareWith, validator.STATUS_VALID, 'different'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^\d+$/.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + /** + * Return true if the input value is a valid hex color + * + * @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; + } + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value == compareWith.val()) { + validator.updateStatus(compareWith, validator.STATUS_VALID, 'identical'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.ip = { + /** + * Return true if the input value is a IP address. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - ipv4: Enable IPv4 validator, default to true + * - ipv6: Enable IPv6 validator, default to true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + options = $.extend({}, { ipv4: true, ipv6: true }, options); + + if (options.ipv4) { + return /^(?:(?: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); + } else if (options.ipv6) { + return /^\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(str); + } + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.isbn = { + /** + * Return true if the input value is a valid ISBN 10 or ISBN 13 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; + } + + // Replace all special characters except digits and X + value = value.replace(/[^\dX]/gi, ''); + var chars = value.split(''), + sum = 0, + checksum; + + // See http://en.wikipedia.org/wiki/International_Standard_Book_Number + switch (chars.length) { + // ISBN 10 + case 10: + sum = 0; + for (var i = 0; i < 9; i++) { + sum += ((10 - i) * parseInt(chars[i])); + } + checksum = 11 - (sum % 11); + if (checksum == 11) { + checksum = 0; + } else if (checksum == 10) { + checksum = 'X'; + } + return (checksum == chars[9]); + + // ISBN 13 + case 13: + sum = 0; + for (var i = 0; i < 12; i++) { + sum += ((i % 2 == 0) ? parseInt(chars[i]) : (parseInt(chars[i]) * 3)); + } + checksum = 10 - (sum % 10); + if (checksum == 10) { + checksum = '0'; + } + return (checksum == chars[12]); + + default: + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value < options.value) : (value <= options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.mac = { + /** + * Return true if the input value is a MAC address. + * + * @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; + } + + return /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + if ('radio' == type || 'checkbox' == type) { + return validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length > 0; + } + + return $.trim($field.val()) != ''; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.phone = { + /** + * Return true if the input value contains a valid US phone number only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - country: The ISO 3166 country code + * + * Currently it only supports United State (US) country + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options.country = options.country || 'US'; + switch (options.country.toUpperCase()) { + case 'US': + default: + value = value.replace(/\(|\)|\s+/g, ''); + return (/^(?:1\-?)?(\d{3})[\-\.]?(\d{3})[\-\.]?(\d{4})$/).test(value); + } + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return options.regexp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.remote = { + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - message: The invalid message + * @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; + if (data == null) { + data = {}; + } + // Support dynamic data + if ('function' == typeof data) { + data = data.call(this, validator); + } + data[name] = value; + + var dfd = new $.Deferred(); + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }); + xhr.then(function(response) { + dfd.resolve(response.valid === true || response.valid === 'true', 'remote'); + }); + + dfd.fail(function() { + xhr.abort(); + }); + + return dfd; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.step = { + /** + * Return true if the input value is valid step one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - baseValue: The base value + * - step: The step + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options = $.extend({}, { baseValue: 0, step: 1 }, options); + value = parseFloat(value); + if (isNaN(value) || !isFinite(value)) { + return false; + } + + var round = function(x, precision) { + var m = Math.pow(10, precision); + x = x * m; + var sign = (x > 0) | -(x < 0), + isHalf = (x % 1 === 0.5 * sign); + if (isHalf) { + return (Math.floor(x) + (sign > 0)) / m; + } else { + return Math.round(x) / m; + } + }, + floatMod = function(x, y) { + if (y == 0.0) { + return 1.0; + } + var dotX = (x + '').split('.'), + dotY = (y + '').split('.'), + precision = ((dotX.length == 1) ? 0 : dotX[1].length) + ((dotY.length == 1) ? 0 : dotY[1].length); + return round(x - y * Math.floor(x / y), precision); + }; + + var mod = floatMod(value - options.baseValue, options.step); + return (mod == 0.0 || mod == options.step); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var length = $.trim(value).length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.zipCode = { + /** + * Return true if and only if the input value is a valid country zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - country: The ISO 3166 country code + * + * Currently it supports the following countries: + * - US (United State) + * - DK (Denmark) + * - SE (Sweden) + * + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '' || !options.country) { + return true; + } + + options.country = options.country || 'US'; + switch (options.country.toUpperCase()) { + case 'DK': + return /^(DK(-|\s)?)?\d{4}$/i.test(value); + case 'SE': + return /^(S-)?\d{3}\s?\d{2}$/i.test(value); + case 'US': + default: + return /^\d{5}([\-]\d{4})?$/.test(value); + } + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.2/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.3.2/js/bootstrapValidator.min.js new file mode 100644 index 000000000..3880c8655 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.2/js/bootstrapValidator.min.js @@ -0,0 +1,12 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.3.2 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),this.dfds={},this.results={},this.invalidField=null,this.$submitButton=null,this._init(),this.STATUS_NOT_VALIDATED="NOT_VALIDATED",this.STATUS_VALIDATING="VALIDATING",this.STATUS_INVALID="INVALID",this.STATUS_VALID="VALID"};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",feedbackIcons:{valid:null,invalid:null,validating:null},submitButtons:'button[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){if(null!=this.options.fields){var b=this;this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit.bootstrapValidator",function(a){a.preventDefault(),b.validate()}).find(this.options.submitButtons).on("click",function(){b.$submitButton=a(this)});for(var c in this.options.fields)this._initField(c);this._setLiveValidating()}},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){this.dfds[b]={},this.results[b]={};var c=this.getFieldElements(b);if(null==c)return delete this.options.fields[b],void delete this.dfds[b];c.attr("data-bv-field",b);var d=a(c[0]),e=d.parents(".form-group"),f=this.options.fields[b].container?e.find(this.options.fields[b].container):this._getMessageContainer(d);d.data("bootstrapValidator.messageContainer",f);for(var g in this.options.fields[b].validators)a.fn.bootstrapValidator.validators[g]?(this.results[b][g]=this.STATUS_NOT_VALIDATED,a("").css("display","none").attr("data-bv-validator",g).html(this.options.fields[b].validators[g].message||this.options.message).addClass("help-block").appendTo(f)):delete this.options.fields[b].validators[g];if(this.options.feedbackIcons&&this.options.feedbackIcons.validating&&this.options.feedbackIcons.invalid&&this.options.feedbackIcons.valid){e.addClass("has-feedback");var h=a("").css("display","none").addClass("form-control-feedback").attr("data-bv-field",b).insertAfter(a(c[c.length-1]));0==e.find("label").length&&h.css("top",0)}null==this.options.fields[b].enabled&&(this.options.fields[b].enabled=!0);var i=this,j=c.attr("type"),k="radio"==j||"checkbox"==j||"SELECT"==c[0].tagName?"change":"keyup";c.on(k+".bootstrapValidator",function(){i.updateStatus(d,i.STATUS_NOT_VALIDATED,null)})}},_getMessageContainer:function(a){var b=a.parent();if(b.hasClass("form-group"))return b;var c=b.attr("class");if(!c)return this._getMessageContainer(b);c=c.split(" ");for(var d=c.length,e=0;d>e;e++)if(/^col-(xs|sm|md|lg)-\d+$/.test(c[e])||/^col-(xs|sm|md|lg)-offset-\d+$/.test(c[e]))return b;return this._getMessageContainer(b)},_setLiveValidating:function(){if("enabled"==this.options.live){var a=this;for(var b in this.options.fields)!function(b){var c=a.getFieldElements(b);if(c){var d=c.attr("type"),e="radio"==d||"checkbox"==d||"SELECT"==c[0].tagName?"change":"keyup";c.on(e+".bootstrapValidator",function(){a.validateField(b)})}}(b)}},_disableSubmitButtons:function(a){a?"disabled"!=this.options.live&&this.$form.find(this.options.submitButtons).attr("disabled","disabled"):this.$form.find(this.options.submitButtons).removeAttr("disabled")},_submit:function(){return this.isValid()?(this._disableSubmitButtons(!0),void(this.options.submitHandler&&"function"==typeof this.options.submitHandler?this.options.submitHandler.call(this,this,this.$form,this.$submitButton):this.$form.off("submit.bootstrapValidator").submit())):("submitted"==this.options.live&&(this.options.live="enabled",this._setLiveValidating()),void(this.invalidField&&this.getFieldElements(this.invalidField).focus()))},getFieldElements:function(a){var b=this.$form.find(this.options.fields[a].selector||'[name="'+a+'"]');return 0==b.length?null:b},validate:function(){if(!this.options.fields)return this;this._disableSubmitButtons(!0);for(var a in this.options.fields)this.validateField(a);return this._submit(),this},validateField:function(b){if(this.options.fields[b].enabled){var c,d,e=this,f=this.getFieldElements(b),g=a(f[0]),h=this.options.fields[b].validators;if(1==f.length&&f.is(":disabled"))return delete this.options.fields[b],void delete this.dfds[b];for(c in h)this.dfds[b][c]&&this.dfds[b][c].reject(),this.results[b][c]!=this.STATUS_VALID&&this.results[b][c]!=this.STATUS_INVALID&&(this.results[b][c]=this.STATUS_VALIDATING,d=a.fn.bootstrapValidator.validators[c].validate(this,g,h[c]),"object"==typeof d?(this.updateStatus(g,this.STATUS_VALIDATING,c),this.dfds[b][c]=d,d.done(function(a,c){delete e.dfds[b][c],e.updateStatus(g,a?e.STATUS_VALID:e.STATUS_INVALID,c),a&&"disabled"==e.options.live&&e._submit()})):"boolean"==typeof d&&this.updateStatus(g,d?this.STATUS_VALID:this.STATUS_INVALID,c))}},isValid:function(){var a,b;for(a in this.results)if(this.options.fields[a].enabled)for(b in this.results[a]){if(this.results[a][b]==this.STATUS_NOT_VALIDATED||this.results[a][b]==this.STATUS_VALIDATING)return!1;if(this.results[a][b]==this.STATUS_INVALID)return this.invalidField=a,!1}return!0},updateStatus:function(b,c,d){var e="string"==typeof b?this.getFieldElements(b):b,f=this,b=e.attr("data-bv-field"),g=e.parents(".form-group"),h=e.data("bootstrapValidator.messageContainer"),i=h.find(".help-block[data-bv-validator]"),j=g.find('.form-control-feedback[data-bv-field="'+b+'"]');if(d)this.results[b][d]=c;else for(var k in this.options.fields[b].validators)this.results[b][k]=c;switch(c){case this.STATUS_VALIDATING:this._disableSubmitButtons(!0),g.removeClass("has-success").removeClass("has-error"),d?i.filter('.help-block[data-bv-validator="'+d+'"]').hide():i.hide(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show();break;case this.STATUS_INVALID:this._disableSubmitButtons(!0),g.removeClass("has-success").addClass("has-error"),d?i.filter('[data-bv-validator="'+d+'"]').show():i.show(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show();break;case this.STATUS_VALID:d?i.filter('[data-bv-validator="'+d+'"]').hide():i.hide(),0==i.filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||f.results[b][d]!=f.STATUS_VALID}).length&&(this._disableSubmitButtons(!1),g.removeClass("has-error").addClass("has-success"),j&&j.removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.valid).show());break;case this.STATUS_NOT_VALIDATED:default:this._disableSubmitButtons(!1),g.removeClass("has-success").removeClass("has-error"),d?i.filter('.help-block[data-bv-validator="'+d+'"]').hide():i.hide(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide()}return this},resetForm:function(a){var b,c,d;for(b in this.options.fields)this.dfds[b]={},this.results[b]={},c=this.getFieldElements(b),this.updateStatus(c,this.STATUS_NOT_VALIDATED,null),a&&(d=c.attr("type"),"radio"==d||"checkbox"==d?c.removeAttr("checked").removeAttr("selected"):c.val(""));return this.invalidField=null,this.$submitButton=null,this._disableSubmitButtons(!1),this},enableFieldValidators:function(a,b){return this.options.fields[a].enabled=b,this.updateStatus(a,this.STATUS_NOT_VALIDATED,null),this}},a.fn.bootstrapValidator=function(c){return this.each(function(){var d=a(this),e=d.data("bootstrapValidator");e||d.data("bootstrapValidator",e=new b(this,c)),"string"==typeof c&&e[c]()})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.base64={validate:function(a,b){var c=b.val();return""==c?!0:/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(b,c,d){var e=c.val();if(d.callback&&"function"==typeof d.callback){var f=new a.Deferred;return f.resolve(d.callback.call(this,e,b),"callback"),f}return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.choice={validate:function(a,b,c){var d=a.getFieldElements(b.attr("data-bv-field")).filter(":checked").length;return c.min&&dc.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(a,b){var c=b.val();if(""==c)return!0;if(/[^0-9-\s]+/.test(c))return!1;c=c.replace(/\D/g,"");for(var d=0,e=0,f=!1,g=c.length,h=g-1;h>=0;h--)e=parseInt(c.charAt(h),10),f&&(e*=2)>9&&(e-=9),d+=e,f=!f;if(d%10!=0)return!1;var i,j,k={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["3528","3529","353","354","355","356","357","358"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}};for(i in k)for(j in k[i].prefix)if(c.substr(0,k[i].prefix[j].length)==k[i].prefix[j]&&-1!=k[i].length.indexOf(c.length))return!0;return!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.cvv={validate:function(a,b,c){var d=b.val();if(""==d)return!0;if(!/^[0-9]{3,4}$/.test(d))return!1;if(!c.creditCardField)return!0;var e=a.getFieldElements(c.creditCardField).val();if(""==e)return!0;var f,g,h={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["3528","3529","353","354","355","356","357","358"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}},i=null;for(f in h)for(g in h[f].prefix)if(e.substr(0,h[f].prefix[g].length)==h[f].prefix[g]&&-1!=h[f].length.indexOf(e.length)){i=f;break}return null==i?!1:"AMERICAN_EXPRESS"==i?4==d.length:3==d.length}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.date={validate:function(a,b,c){var d=b.val();if(""==d)return!0;c.format=c.format||"MM/DD/YYYY";var e=-1!=c.format.indexOf("/")?"/":-1!=c.format.indexOf("-")?"-":null;if(null==e)return!1;var f,g,h,i,j=null,k=null;switch(!0){case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/DD/MM"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-DD-MM"==c.format:h=i[1],g=i[2],f=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"DD/MM/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"DD-MM-YYYY"==c.format:g=i[1],f=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/MM/DD"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-MM-DD"==c.format:h=i[1],f=i[2],g=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"MM/DD/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"MM-DD-YYYY"==c.format:f=i[1],g=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/DD/MM h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-DD-MM h:m A"==c.format:h=i[1],g=i[2],f=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD/MM/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD-MM-YYYY h:m A"==c.format:g=i[1],f=i[2],h=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/MM/DD h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-MM-DD h:m A"==c.format:h=i[1],f=i[2],g=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM/DD/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM-DD-YYYY h:m A"==c.format:f=i[1],g=i[2],h=i[3],k=i[4],j=i[5];break;default:return!1}if(k&&j&&(k=parseInt(k,10),j=parseInt(j,10),1>k||k>12||0>j||j>59))return!1;if(g=parseInt(g,10),f=parseInt(f,10),h=parseInt(h,10),1e3>h||h>9999||0==f||f>12)return!1;var l=[31,28,31,30,31,30,31,31,30,31,30,31];return(h%400==0||h%100!=0&&h%4==0)&&(l[1]=29),g>0&&g<=l[f-1]}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d!=e.val()?(a.updateStatus(e,a.STATUS_VALID,"different"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){var c=b.val();return""==c?!0:/^\d+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={validate:function(a,b){var c=b.val();if(""==c)return!0;var d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.value:d>=c.value)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={validate:function(a,b){var c=b.val();return""==c?!0:/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d==e.val()?(a.updateStatus(e,a.STATUS_VALID,"identical"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.ip={validate:function(b,c,d){var e=c.val();return""==e?!0:(d=a.extend({},{ipv4:!0,ipv6:!0},d),d.ipv4?/^(?:(?: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(e):d.ipv6?/^\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(str):!1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.isbn={validate:function(a,b){var c=b.val();if(""==c)return!0;c=c.replace(/[^\dX]/gi,"");var d,e=c.split(""),f=0;switch(e.length){case 10:f=0;for(var g=0;9>g;g++)f+=(10-g)*parseInt(e[g]);return d=11-f%11,11==d?d=0:10==d&&(d="X"),d==e[9];case 13:f=0;for(var g=0;12>g;g++)f+=g%2==0?parseInt(e[g]):3*parseInt(e[g]);return d=10-f%10,10==d&&(d="0"),d==e[12];default:return!1}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d0:""!=a.trim(c.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.phone={validate:function(a,b,c){var d=b.val();if(""==d)return!0;switch(c.country=c.country||"US",c.country.toUpperCase()){case"US":default:return d=d.replace(/\(|\)|\s+/g,""),/^(?:1\-?)?(\d{3})[\-\.]?(\d{3})[\-\.]?(\d{4})$/.test(d)}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.regexp={validate:function(a,b,c){var d=b.val();return""==d?!0:c.regexp.test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.remote={validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=c.attr("data-bv-field"),g=d.data;null==g&&(g={}),"function"==typeof g&&(g=g.call(this,b)),g[f]=e;var h=new a.Deferred,i=a.ajax({type:"POST",url:d.url,dataType:"json",data:g});return i.then(function(a){h.resolve(a.valid===!0||"true"===a.valid,"remote")}),h.fail(function(){i.abort()}),h}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.step={validate:function(b,c,d){var e=c.val();if(""==e)return!0;if(d=a.extend({},{baseValue:0,step:1},d),e=parseFloat(e),isNaN(e)||!isFinite(e))return!1;var f=function(a,b){var c=Math.pow(10,b);a*=c;var d=a>0|-(0>a),e=a%1===.5*d;return e?(Math.floor(a)+(d>0))/c:Math.round(a)/c},g=function(a,b){if(0==b)return 1;var c=(a+"").split("."),d=(b+"").split("."),e=(1==c.length?0:c[1].length)+(1==d.length?0:d[1].length);return f(a-b*Math.floor(a/b),e)},h=g(e-d.baseValue,d.step);return 0==h||h==d.step}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringLength={validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=a.trim(e).length;return d.min&&fd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={validate:function(a,b){var c=b.val();if(""==c)return!0;var d=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.zipCode={validate:function(a,b,c){var d=b.val();if(""==d||!c.country)return!0;switch(c.country=c.country||"US",c.country.toUpperCase()){case"DK":return/^(DK(-|\s)?)?\d{4}$/i.test(d);case"SE":return/^(S-)?\d{3}\s?\d{2}$/i.test(d);case"US":default:return/^\d{5}([\-]\d{4})?$/.test(d)}}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.3/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.3.3/css/bootstrapValidator.css new file mode 100644 index 000000000..20b84ba8d --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.3/css/bootstrapValidator.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form .help-block { + margin-bottom: 0; +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.3/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.3.3/css/bootstrapValidator.min.css new file mode 100644 index 000000000..5b00c3e8f --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.3/css/bootstrapValidator.min.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.3.3 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.3/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.3.3/js/bootstrapValidator.js new file mode 100644 index 000000000..73ffd432a --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.3/js/bootstrapValidator.js @@ -0,0 +1,1600 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.3.3 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + this.dfds = {}; // Array of deferred + this.results = {}; // Validating results + + this.invalidField = null; // First invalid field + this.$submitButton = null; // The submit button which is clicked to submit form + + this._init(); + + this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED'; + this.STATUS_VALIDATING = 'VALIDATING'; + this.STATUS_INVALID = 'INVALID'; + this.STATUS_VALID = 'VALID'; + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // Shows ok/error/loading icons based on the field validity. + // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation). + // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically. + // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later. + // + // Examples: + // - Use Glyphicons icons: + // feedbackIcons: { + // valid: 'glyphicon glyphicon-ok', + // invalid: 'glyphicon glyphicon-remove', + // validating: 'glyphicon glyphicon-refresh' + // } + // - Use FontAwesome icons: + // feedbackIcons: { + // valid: 'fa fa-check', + // invalid: 'fa fa-times', + // validating: 'fa fa-refresh' + // } + feedbackIcons: { + valid: null, + invalid: null, + validating: null + }, + + // The submit buttons selector + // These buttons will be disabled to prevent the valid form from multiple submissions + submitButtons: 'button[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submission + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating option + // Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + if (this.options.fields == null) { + return; + } + + var that = this; + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + // Disable the default submission first + .on('submit.bootstrapValidator', function(e) { + e.preventDefault(); + that.validate(); + }) + .find(this.options.submitButtons) + .on('click', function() { + that.$submitButton = $(this); + }); + + for (var field in this.options.fields) { + this._initField(field); + } + + this._setLiveValidating(); + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + this.dfds[field] = {}; + this.results[field] = {}; + + var fields = this.getFieldElements(field); + + // We don't need to validate non-existing fields + if (fields == null) { + delete this.options.fields[field]; + delete this.dfds[field]; + return; + } + + fields.attr('data-bv-field', field); + + // Create help block elements for showing the error messages + var $field = $(fields[0]), + $parent = $field.parents('.form-group'), + // Allow user to indicate where the error messages are shown + $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field); + + $field.data('bootstrapValidator.messageContainer', $message); + for (var validatorName in this.options.fields[field].validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + delete this.options.fields[field].validators[validatorName]; + continue; + } + + this.results[field][validatorName] = this.STATUS_NOT_VALIDATED; + $('') + .css('display', 'none') + .attr('data-bv-validator', validatorName) + .html(this.options.fields[field].validators[validatorName].message || this.options.message) + .addClass('help-block') + .appendTo($message); + } + + // Prepare the feedback icons + // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation) + if (this.options.feedbackIcons + && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid) + { + $parent.addClass('has-feedback'); + var $icon = $('').css('display', 'none').addClass('form-control-feedback').attr('data-bv-field', field).insertAfter($(fields[fields.length - 1])); + // 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); + } + } + + if (this.options.fields[field]['enabled'] == null) { + this.options.fields[field]['enabled'] = true; + } + + // Whenever the user change the field value, mark it as not validated yet + var that = this, + type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup'; + fields.on(event + '.bootstrapValidator', function() { + that.updateStatus($field, that.STATUS_NOT_VALIDATED, null); + }); + }, + + /** + * Get the element to place the error messages + * + * @param {jQuery} $field The field element + * @returns {jQuery} + */ + _getMessageContainer: function($field) { + var $parent = $field.parent(); + if ($parent.hasClass('form-group')) { + return $parent; + } + + var cssClasses = $parent.attr('class'); + if (!cssClasses) { + return this._getMessageContainer($parent); + } + + cssClasses = cssClasses.split(' '); + var n = cssClasses.length; + for (var i = 0; i < n; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i]) || /^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + return $parent; + } + } + + return this._getMessageContainer($parent); + }, + + /** + * Enable live validating + */ + _setLiveValidating: function() { + if ('enabled' == this.options.live) { + var that = this; + for (var field in this.options.fields) { + (function(f) { + var fields = that.getFieldElements(f); + if (fields) { + var type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup'; + + fields.on(event + '.bootstrapValidator', function() { + that.validateField(f); + }); + } + })(field); + } + } + }, + + /** + * Disable/Enable submit buttons + * + * @param {Boolean} disabled + */ + _disableSubmitButtons: function(disabled) { + if (!disabled) { + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + } else if (this.options.live != 'disabled') { + // Don't disable if the live validating mode is disabled + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + } + }, + + /** + * Called when all validations are completed + */ + _submit: function() { + if (!this.isValid()) { + if ('submitted' == this.options.live) { + this.options.live = 'enabled'; + this._setLiveValidating(); + } + + // Focus to the first invalid field + if (this.invalidField) { + this.getFieldElements(this.invalidField).focus(); + } + return; + } + + this._disableSubmitButtons(true); + + // Call the custom submission if enabled + if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + // Turn off the submit handler, so user can call form.submit() inside their submitHandler method + this.$form.off('submit.bootstrapValidator'); + this.options.submitHandler.call(this, this, this.$form, this.$submitButton); + } else { + // Submit form + this.$form.off('submit.bootstrapValidator').submit(); + } + }, + + // --- Public methods --- + + /** + * Retrieve the field elements by given name + * + * @param {String} field The field name + * @returns {null|jQuery[]} + */ + getFieldElements: function(field) { + var fields = this.$form.find(this.options.fields[field].selector || '[name="' + field + '"]'); + return (fields.length == 0) ? null : fields; + }, + + /** + * Validate the form + * + * @return {BootstrapValidator} + */ + validate: function() { + if (!this.options.fields) { + return this; + } + this._disableSubmitButtons(true); + + for (var field in this.options.fields) { + this.validateField(field); + } + + this._submit(); + return this; + }, + + /** + * Validate given field + * + * @param {String} field The field name + */ + validateField: function(field) { + if (!this.options.fields[field]['enabled']) { + return; + } + + var that = this, + fields = this.getFieldElements(field), + $field = $(fields[0]), + validators = this.options.fields[field].validators, + validatorName, + validateResult; + + // We don't need to validate disabled field + if (fields.length == 1 && fields.is(':disabled')) { + delete this.options.fields[field]; + delete this.dfds[field]; + return; + } + + for (validatorName in validators) { + if (this.dfds[field][validatorName]) { + this.dfds[field][validatorName].reject(); + } + + // Don't validate field if it is already done + if (this.results[field][validatorName] == this.STATUS_VALID || this.results[field][validatorName] == this.STATUS_INVALID) { + continue; + } + + this.results[field][validatorName] = this.STATUS_VALIDATING; + validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]); + + if ('object' == typeof validateResult) { + this.updateStatus($field, this.STATUS_VALIDATING, validatorName); + this.dfds[field][validatorName] = validateResult; + + validateResult.done(function(isValid, v) { + // v is validator name + delete that.dfds[field][v]; + that.updateStatus($field, isValid ? that.STATUS_VALID : that.STATUS_INVALID, v); + + if (isValid && 'disabled' == that.options.live) { + that._submit(); + } + }); + } else if ('boolean' == typeof validateResult) { + this.updateStatus($field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName); + } + } + }, + + /** + * Check the form validity + * + * @returns {Boolean} + */ + isValid: function() { + var field, validatorName; + for (field in this.results) { + if (this.options.fields[field] == null || !this.options.fields[field]['enabled']) { + continue; + } + + for (validatorName in this.results[field]) { + if (this.results[field][validatorName] == this.STATUS_NOT_VALIDATED || this.results[field][validatorName] == this.STATUS_VALIDATING) { + return false; + } + + if (this.results[field][validatorName] == this.STATUS_INVALID) { + this.invalidField = field; + return false; + } + } + } + + return true; + }, + + /** + * Update field status + * + * @param {String|jQuery} field The field name or field element + * @param {String} status The status + * Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String|null} validatorName The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateStatus: function(field, status, validatorName) { + var $field = ('string' == typeof field) ? this.getFieldElements(field) : field, + that = this, + field = $field.attr('data-bv-field'), + $parent = $field.parents('.form-group'), + $message = $field.data('bootstrapValidator.messageContainer'), + $errors = $message.find('.help-block[data-bv-validator]'), + $icon = $parent.find('.form-control-feedback[data-bv-field="' + field + '"]'); + + // Update status + if (validatorName) { + this.results[field][validatorName] = status; + } else { + for (var v in this.options.fields[field].validators) { + this.results[field][v] = status; + } + } + + // Show/hide error elements and feedback icons + switch (status) { + case this.STATUS_VALIDATING: + this._disableSubmitButtons(true); + $parent.removeClass('has-success').removeClass('has-error'); + // TODO: Show validating message + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(); + } + break; + + case this.STATUS_INVALID: + this._disableSubmitButtons(true); + $parent.removeClass('has-success').addClass('has-error'); + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').show() : $errors.show(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(); + } + break; + + case this.STATUS_VALID: + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + + // If the field is valid + if ($errors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || (that.results[field][v] != that.STATUS_VALID); + }).length == 0 + ) { + this._disableSubmitButtons(false); + $parent.removeClass('has-error').addClass('has-success'); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.valid).show(); + } + } + break; + + case this.STATUS_NOT_VALIDATED: + default: + this._disableSubmitButtons(false); + $parent.removeClass('has-success').removeClass('has-error'); + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide(); + } + break; + } + + return this; + }, + + // Useful APIs which aren't used internally + + /** + * Reset the form + * + * @param {Boolean} resetFormData Reset current form data + * @return {BootstrapValidator} + */ + resetForm: function(resetFormData) { + var field, $field, type; + for (field in this.options.fields) { + this.dfds[field] = {}; + this.results[field] = {}; + + $field = this.getFieldElements(field); + // Mark field as not validated yet + this.updateStatus($field, this.STATUS_NOT_VALIDATED, null); + + if (resetFormData) { + type = $field.attr('type'); + ('radio' == type || 'checkbox' == type) ? $field.removeAttr('checked').removeAttr('selected') : $field.val(''); + } + } + + this.invalidField = null; + this.$submitButton = null; + + // Enable submit buttons + this._disableSubmitButtons(false); + + return this; + }, + + /** + * Enable/Disable all validators to given field + * + * @param {String} field The field name + * @param {Boolean} enabled Enable/Disable field validators + * @return {BootstrapValidator} + */ + enableFieldValidators: function(field, enabled) { + this.options.fields[field]['enabled'] = enabled; + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + return this; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(options) { + return this.each(function() { + var $this = $(this), data = $this.data('bootstrapValidator'); + if (!data) { + $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options))); + } + if ('string' == typeof options) { + data[options](); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.base64 = { + /** + * Return true if the input value is a base 64 encoded string. + * + * @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; + } + + return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = parseFloat(value); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {Boolean|Deferred} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (options.callback && 'function' == typeof options.callback) { + var dfd = new $.Deferred(); + dfd.resolve(options.callback.call(this, value, validator), 'callback'); + return dfd; + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.choice = { + /** + * Check if the number of checked boxes are less or more than a given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var numChoices = validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length; + if ((options.min && numChoices < options.min) || (options.max && numChoices > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + value = value.replace(/\D/g, ''); + + // Validate the check sum + // The Luhn Algorithm + // http://en.wikipedia.org/wiki/Luhn + var check = 0, digit = 0, even = false, length = value.length; + + for (var n = length - 1; n >= 0; n--) { + digit = parseInt(value.charAt(n), 10); + + if (even) { + if ((digit *= 2) > 9) { + digit -= 9; + } + } + + check += digit; + even = !even; + } + + if ((check % 10) != 0) { + return false; + } + + // Validate the card number based on prefix (IIN ranges) and length + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + + var type, i; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (value.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(value.length) != -1) // and length + { + return true; + } + } + } + + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.cvv = { + /** + * Return true if the input value is a valid CVV number. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - creditCardField: The credit card number field. It can be null + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^[0-9]{3,4}$/.test(value)) { + return false; + } + + if (!options.creditCardField) { + return true; + } + + // Get the credit card number + var creditCard = validator.getFieldElements(options.creditCardField).val(); + if (creditCard == '') { + return true; + } + + // Supported credit card types + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + var type, i, creditCardType = null; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (creditCard.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(creditCard.length) != -1) // and length + { + creditCardType = type; + break; + } + } + } + + return (creditCardType == null) + ? false + : (('AMERICAN_EXPRESS' == creditCardType) ? (value.length == 4) : (value.length == 3)); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.date = { + /** + * Return true if the input value is valid date + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - format: The date format. Default is MM/DD/YYYY + * Support the following formats: + * YYYY/DD/MM + * YYYY/DD/MM h:m A + * YYYY/MM/DD + * YYYY/MM/DD h:m A + * + * YYYY-DD-MM + * YYYY-DD-MM h:m A + * YYYY-MM-DD + * YYYY-MM-DD h:m A + * + * MM/DD/YYYY + * MM/DD/YYYY h:m A + * DD/MM/YYYY + * DD/MM/YYYY h:m A + * + * MM-DD-YYYY + * MM-DD-YYYY h:m A + * DD-MM-YYYY + * DD-MM-YYYY h:m A + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + // Determine the separator + options.format = options.format || 'MM/DD/YYYY'; + var separator = (options.format.indexOf('/') != -1) + ? '/' + : ((options.format.indexOf('-') != -1) ? '-' : null); + if (separator == null) { + return false; + } + + var month, day, year, minutes = null, hours = null, matches; + switch (true) { + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/DD/MM'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-DD-MM'): + year = matches[1]; day = matches[2]; month = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'DD/MM/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'DD-MM-YYYY'): + day = matches[1]; month = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/MM/DD'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-MM-DD'): + year = matches[1]; month = matches[2]; day = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'MM/DD/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'MM-DD-YYYY'): + month = matches[1]; day = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/DD/MM h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-DD-MM h:m A'): + year = matches[1]; day = matches[2]; month = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD/MM/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD-MM-YYYY h:m A'): + day = matches[1]; month = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/MM/DD h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-MM-DD h:m A'): + year = matches[1]; month = matches[2]; day = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM/DD/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM-DD-YYYY h:m A'): + month = matches[1]; day = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + default: + return false; + } + + // Validate hours and minutes + if (hours && minutes) { + hours = parseInt(hours, 10); + minutes = parseInt(minutes, 10); + if (hours < 1 || hours > 12 || minutes < 0 || minutes > 59) { + return false; + } + } + + // Validate day, month, and year + day = parseInt(day, 10); + month = parseInt(month, 10); + year = parseInt(year, 10); + + if (year < 1000 || year > 9999 || month == 0 || month > 12) { + return false; + } + + var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + // Update the number of days in Feb of leap year + if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) { + numDays[1] = 29; + } + + // Check the day + return (day > 0 && day <= numDays[month - 1]); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.different = { + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value != compareWith.val()) { + validator.updateStatus(compareWith, validator.STATUS_VALID, 'different'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^\d+$/.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + /** + * Return true if the input value is a valid hex color + * + * @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; + } + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value == compareWith.val()) { + validator.updateStatus(compareWith, validator.STATUS_VALID, 'identical'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.ip = { + /** + * Return true if the input value is a IP address. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - ipv4: Enable IPv4 validator, default to true + * - ipv6: Enable IPv6 validator, default to true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + options = $.extend({}, { ipv4: true, ipv6: true }, options); + + if (options.ipv4) { + return /^(?:(?: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); + } else if (options.ipv6) { + return /^\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(str); + } + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.isbn = { + /** + * Return true if the input value is a valid ISBN 10 or ISBN 13 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; + } + + // Replace all special characters except digits and X + value = value.replace(/[^\dX]/gi, ''); + var chars = value.split(''), + sum = 0, + checksum; + + // See http://en.wikipedia.org/wiki/International_Standard_Book_Number + switch (chars.length) { + // ISBN 10 + case 10: + sum = 0; + for (var i = 0; i < 9; i++) { + sum += ((10 - i) * parseInt(chars[i])); + } + checksum = 11 - (sum % 11); + if (checksum == 11) { + checksum = 0; + } else if (checksum == 10) { + checksum = 'X'; + } + return (checksum == chars[9]); + + // ISBN 13 + case 13: + sum = 0; + for (var i = 0; i < 12; i++) { + sum += ((i % 2 == 0) ? parseInt(chars[i]) : (parseInt(chars[i]) * 3)); + } + checksum = 10 - (sum % 10); + if (checksum == 10) { + checksum = '0'; + } + return (checksum == chars[12]); + + default: + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value < options.value) : (value <= options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.mac = { + /** + * Return true if the input value is a MAC address. + * + * @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; + } + + return /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + if ('radio' == type || 'checkbox' == type) { + return validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length > 0; + } + + return $.trim($field.val()) != ''; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.phone = { + /** + * Return true if the input value contains a valid US phone number only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - country: The ISO 3166 country code + * + * Currently it only supports United State (US) country + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options.country = options.country || 'US'; + switch (options.country.toUpperCase()) { + case 'US': + default: + value = value.replace(/\(|\)|\s+/g, ''); + return (/^(?:1\-?)?(\d{3})[\-\.]?(\d{3})[\-\.]?(\d{4})$/).test(value); + } + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return options.regexp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.remote = { + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - message: The invalid message + * @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; + if (data == null) { + data = {}; + } + // Support dynamic data + if ('function' == typeof data) { + data = data.call(this, validator); + } + data[name] = value; + + var dfd = new $.Deferred(); + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }); + xhr.then(function(response) { + dfd.resolve(response.valid === true || response.valid === 'true', 'remote'); + }); + + dfd.fail(function() { + xhr.abort(); + }); + + return dfd; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.step = { + /** + * Return true if the input value is valid step one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - baseValue: The base value + * - step: The step + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options = $.extend({}, { baseValue: 0, step: 1 }, options); + value = parseFloat(value); + if (isNaN(value) || !isFinite(value)) { + return false; + } + + var round = function(x, precision) { + var m = Math.pow(10, precision); + x = x * m; + var sign = (x > 0) | -(x < 0), + isHalf = (x % 1 === 0.5 * sign); + if (isHalf) { + return (Math.floor(x) + (sign > 0)) / m; + } else { + return Math.round(x) / m; + } + }, + floatMod = function(x, y) { + if (y == 0.0) { + return 1.0; + } + var dotX = (x + '').split('.'), + dotY = (y + '').split('.'), + precision = ((dotX.length == 1) ? 0 : dotX[1].length) + ((dotY.length == 1) ? 0 : dotY[1].length); + return round(x - y * Math.floor(x / y), precision); + }; + + var mod = floatMod(value - options.baseValue, options.step); + return (mod == 0.0 || mod == options.step); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var length = $.trim(value).length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.zipCode = { + /** + * Return true if and only if the input value is a valid country zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - country: The ISO 3166 country code + * + * Currently it supports the following countries: + * - US (United State) + * - DK (Denmark) + * - SE (Sweden) + * + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '' || !options.country) { + return true; + } + + options.country = options.country || 'US'; + switch (options.country.toUpperCase()) { + case 'DK': + return /^(DK(-|\s)?)?\d{4}$/i.test(value); + case 'SE': + return /^(S-)?\d{3}\s?\d{2}$/i.test(value); + case 'US': + default: + return /^\d{5}([\-]\d{4})?$/.test(value); + } + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.3.3/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.3.3/js/bootstrapValidator.min.js new file mode 100644 index 000000000..2bd45b3d1 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.3.3/js/bootstrapValidator.min.js @@ -0,0 +1,12 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.3.3 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),this.dfds={},this.results={},this.invalidField=null,this.$submitButton=null,this._init(),this.STATUS_NOT_VALIDATED="NOT_VALIDATED",this.STATUS_VALIDATING="VALIDATING",this.STATUS_INVALID="INVALID",this.STATUS_VALID="VALID"};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",feedbackIcons:{valid:null,invalid:null,validating:null},submitButtons:'button[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){if(null!=this.options.fields){var b=this;this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit.bootstrapValidator",function(a){a.preventDefault(),b.validate()}).find(this.options.submitButtons).on("click",function(){b.$submitButton=a(this)});for(var c in this.options.fields)this._initField(c);this._setLiveValidating()}},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){this.dfds[b]={},this.results[b]={};var c=this.getFieldElements(b);if(null==c)return delete this.options.fields[b],void delete this.dfds[b];c.attr("data-bv-field",b);var d=a(c[0]),e=d.parents(".form-group"),f=this.options.fields[b].container?e.find(this.options.fields[b].container):this._getMessageContainer(d);d.data("bootstrapValidator.messageContainer",f);for(var g in this.options.fields[b].validators)a.fn.bootstrapValidator.validators[g]?(this.results[b][g]=this.STATUS_NOT_VALIDATED,a("").css("display","none").attr("data-bv-validator",g).html(this.options.fields[b].validators[g].message||this.options.message).addClass("help-block").appendTo(f)):delete this.options.fields[b].validators[g];if(this.options.feedbackIcons&&this.options.feedbackIcons.validating&&this.options.feedbackIcons.invalid&&this.options.feedbackIcons.valid){e.addClass("has-feedback");var h=a("").css("display","none").addClass("form-control-feedback").attr("data-bv-field",b).insertAfter(a(c[c.length-1]));0==e.find("label").length&&h.css("top",0)}null==this.options.fields[b].enabled&&(this.options.fields[b].enabled=!0);var i=this,j=c.attr("type"),k="radio"==j||"checkbox"==j||"file"==j||"SELECT"==c[0].tagName?"change":"keyup";c.on(k+".bootstrapValidator",function(){i.updateStatus(d,i.STATUS_NOT_VALIDATED,null)})}},_getMessageContainer:function(a){var b=a.parent();if(b.hasClass("form-group"))return b;var c=b.attr("class");if(!c)return this._getMessageContainer(b);c=c.split(" ");for(var d=c.length,e=0;d>e;e++)if(/^col-(xs|sm|md|lg)-\d+$/.test(c[e])||/^col-(xs|sm|md|lg)-offset-\d+$/.test(c[e]))return b;return this._getMessageContainer(b)},_setLiveValidating:function(){if("enabled"==this.options.live){var a=this;for(var b in this.options.fields)!function(b){var c=a.getFieldElements(b);if(c){var d=c.attr("type"),e="radio"==d||"checkbox"==d||"file"==d||"SELECT"==c[0].tagName?"change":"keyup";c.on(e+".bootstrapValidator",function(){a.validateField(b)})}}(b)}},_disableSubmitButtons:function(a){a?"disabled"!=this.options.live&&this.$form.find(this.options.submitButtons).attr("disabled","disabled"):this.$form.find(this.options.submitButtons).removeAttr("disabled")},_submit:function(){return this.isValid()?(this._disableSubmitButtons(!0),void(this.options.submitHandler&&"function"==typeof this.options.submitHandler?(this.$form.off("submit.bootstrapValidator"),this.options.submitHandler.call(this,this,this.$form,this.$submitButton)):this.$form.off("submit.bootstrapValidator").submit())):("submitted"==this.options.live&&(this.options.live="enabled",this._setLiveValidating()),void(this.invalidField&&this.getFieldElements(this.invalidField).focus()))},getFieldElements:function(a){var b=this.$form.find(this.options.fields[a].selector||'[name="'+a+'"]');return 0==b.length?null:b},validate:function(){if(!this.options.fields)return this;this._disableSubmitButtons(!0);for(var a in this.options.fields)this.validateField(a);return this._submit(),this},validateField:function(b){if(this.options.fields[b].enabled){var c,d,e=this,f=this.getFieldElements(b),g=a(f[0]),h=this.options.fields[b].validators;if(1==f.length&&f.is(":disabled"))return delete this.options.fields[b],void delete this.dfds[b];for(c in h)this.dfds[b][c]&&this.dfds[b][c].reject(),this.results[b][c]!=this.STATUS_VALID&&this.results[b][c]!=this.STATUS_INVALID&&(this.results[b][c]=this.STATUS_VALIDATING,d=a.fn.bootstrapValidator.validators[c].validate(this,g,h[c]),"object"==typeof d?(this.updateStatus(g,this.STATUS_VALIDATING,c),this.dfds[b][c]=d,d.done(function(a,c){delete e.dfds[b][c],e.updateStatus(g,a?e.STATUS_VALID:e.STATUS_INVALID,c),a&&"disabled"==e.options.live&&e._submit()})):"boolean"==typeof d&&this.updateStatus(g,d?this.STATUS_VALID:this.STATUS_INVALID,c))}},isValid:function(){var a,b;for(a in this.results)if(null!=this.options.fields[a]&&this.options.fields[a].enabled)for(b in this.results[a]){if(this.results[a][b]==this.STATUS_NOT_VALIDATED||this.results[a][b]==this.STATUS_VALIDATING)return!1;if(this.results[a][b]==this.STATUS_INVALID)return this.invalidField=a,!1}return!0},updateStatus:function(b,c,d){var e="string"==typeof b?this.getFieldElements(b):b,f=this,b=e.attr("data-bv-field"),g=e.parents(".form-group"),h=e.data("bootstrapValidator.messageContainer"),i=h.find(".help-block[data-bv-validator]"),j=g.find('.form-control-feedback[data-bv-field="'+b+'"]');if(d)this.results[b][d]=c;else for(var k in this.options.fields[b].validators)this.results[b][k]=c;switch(c){case this.STATUS_VALIDATING:this._disableSubmitButtons(!0),g.removeClass("has-success").removeClass("has-error"),d?i.filter('.help-block[data-bv-validator="'+d+'"]').hide():i.hide(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show();break;case this.STATUS_INVALID:this._disableSubmitButtons(!0),g.removeClass("has-success").addClass("has-error"),d?i.filter('[data-bv-validator="'+d+'"]').show():i.show(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show();break;case this.STATUS_VALID:d?i.filter('[data-bv-validator="'+d+'"]').hide():i.hide(),0==i.filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||f.results[b][d]!=f.STATUS_VALID}).length&&(this._disableSubmitButtons(!1),g.removeClass("has-error").addClass("has-success"),j&&j.removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.valid).show());break;case this.STATUS_NOT_VALIDATED:default:this._disableSubmitButtons(!1),g.removeClass("has-success").removeClass("has-error"),d?i.filter('.help-block[data-bv-validator="'+d+'"]').hide():i.hide(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide()}return this},resetForm:function(a){var b,c,d;for(b in this.options.fields)this.dfds[b]={},this.results[b]={},c=this.getFieldElements(b),this.updateStatus(c,this.STATUS_NOT_VALIDATED,null),a&&(d=c.attr("type"),"radio"==d||"checkbox"==d?c.removeAttr("checked").removeAttr("selected"):c.val(""));return this.invalidField=null,this.$submitButton=null,this._disableSubmitButtons(!1),this},enableFieldValidators:function(a,b){return this.options.fields[a].enabled=b,this.updateStatus(a,this.STATUS_NOT_VALIDATED,null),this}},a.fn.bootstrapValidator=function(c){return this.each(function(){var d=a(this),e=d.data("bootstrapValidator");e||d.data("bootstrapValidator",e=new b(this,c)),"string"==typeof c&&e[c]()})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.base64={validate:function(a,b){var c=b.val();return""==c?!0:/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(b,c,d){var e=c.val();if(d.callback&&"function"==typeof d.callback){var f=new a.Deferred;return f.resolve(d.callback.call(this,e,b),"callback"),f}return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.choice={validate:function(a,b,c){var d=a.getFieldElements(b.attr("data-bv-field")).filter(":checked").length;return c.min&&dc.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(a,b){var c=b.val();if(""==c)return!0;if(/[^0-9-\s]+/.test(c))return!1;c=c.replace(/\D/g,"");for(var d=0,e=0,f=!1,g=c.length,h=g-1;h>=0;h--)e=parseInt(c.charAt(h),10),f&&(e*=2)>9&&(e-=9),d+=e,f=!f;if(d%10!=0)return!1;var i,j,k={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["3528","3529","353","354","355","356","357","358"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}};for(i in k)for(j in k[i].prefix)if(c.substr(0,k[i].prefix[j].length)==k[i].prefix[j]&&-1!=k[i].length.indexOf(c.length))return!0;return!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.cvv={validate:function(a,b,c){var d=b.val();if(""==d)return!0;if(!/^[0-9]{3,4}$/.test(d))return!1;if(!c.creditCardField)return!0;var e=a.getFieldElements(c.creditCardField).val();if(""==e)return!0;var f,g,h={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["3528","3529","353","354","355","356","357","358"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}},i=null;for(f in h)for(g in h[f].prefix)if(e.substr(0,h[f].prefix[g].length)==h[f].prefix[g]&&-1!=h[f].length.indexOf(e.length)){i=f;break}return null==i?!1:"AMERICAN_EXPRESS"==i?4==d.length:3==d.length}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.date={validate:function(a,b,c){var d=b.val();if(""==d)return!0;c.format=c.format||"MM/DD/YYYY";var e=-1!=c.format.indexOf("/")?"/":-1!=c.format.indexOf("-")?"-":null;if(null==e)return!1;var f,g,h,i,j=null,k=null;switch(!0){case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/DD/MM"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-DD-MM"==c.format:h=i[1],g=i[2],f=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"DD/MM/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"DD-MM-YYYY"==c.format:g=i[1],f=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/MM/DD"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-MM-DD"==c.format:h=i[1],f=i[2],g=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"MM/DD/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"MM-DD-YYYY"==c.format:f=i[1],g=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/DD/MM h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-DD-MM h:m A"==c.format:h=i[1],g=i[2],f=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD/MM/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD-MM-YYYY h:m A"==c.format:g=i[1],f=i[2],h=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/MM/DD h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-MM-DD h:m A"==c.format:h=i[1],f=i[2],g=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM/DD/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM-DD-YYYY h:m A"==c.format:f=i[1],g=i[2],h=i[3],k=i[4],j=i[5];break;default:return!1}if(k&&j&&(k=parseInt(k,10),j=parseInt(j,10),1>k||k>12||0>j||j>59))return!1;if(g=parseInt(g,10),f=parseInt(f,10),h=parseInt(h,10),1e3>h||h>9999||0==f||f>12)return!1;var l=[31,28,31,30,31,30,31,31,30,31,30,31];return(h%400==0||h%100!=0&&h%4==0)&&(l[1]=29),g>0&&g<=l[f-1]}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d!=e.val()?(a.updateStatus(e,a.STATUS_VALID,"different"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){var c=b.val();return""==c?!0:/^\d+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={validate:function(a,b){var c=b.val();if(""==c)return!0;var d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.value:d>=c.value)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={validate:function(a,b){var c=b.val();return""==c?!0:/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d==e.val()?(a.updateStatus(e,a.STATUS_VALID,"identical"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.ip={validate:function(b,c,d){var e=c.val();return""==e?!0:(d=a.extend({},{ipv4:!0,ipv6:!0},d),d.ipv4?/^(?:(?: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(e):d.ipv6?/^\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(str):!1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.isbn={validate:function(a,b){var c=b.val();if(""==c)return!0;c=c.replace(/[^\dX]/gi,"");var d,e=c.split(""),f=0;switch(e.length){case 10:f=0;for(var g=0;9>g;g++)f+=(10-g)*parseInt(e[g]);return d=11-f%11,11==d?d=0:10==d&&(d="X"),d==e[9];case 13:f=0;for(var g=0;12>g;g++)f+=g%2==0?parseInt(e[g]):3*parseInt(e[g]);return d=10-f%10,10==d&&(d="0"),d==e[12];default:return!1}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d0:""!=a.trim(c.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.phone={validate:function(a,b,c){var d=b.val();if(""==d)return!0;switch(c.country=c.country||"US",c.country.toUpperCase()){case"US":default:return d=d.replace(/\(|\)|\s+/g,""),/^(?:1\-?)?(\d{3})[\-\.]?(\d{3})[\-\.]?(\d{4})$/.test(d)}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.regexp={validate:function(a,b,c){var d=b.val();return""==d?!0:c.regexp.test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.remote={validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=c.attr("data-bv-field"),g=d.data;null==g&&(g={}),"function"==typeof g&&(g=g.call(this,b)),g[f]=e;var h=new a.Deferred,i=a.ajax({type:"POST",url:d.url,dataType:"json",data:g});return i.then(function(a){h.resolve(a.valid===!0||"true"===a.valid,"remote")}),h.fail(function(){i.abort()}),h}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.step={validate:function(b,c,d){var e=c.val();if(""==e)return!0;if(d=a.extend({},{baseValue:0,step:1},d),e=parseFloat(e),isNaN(e)||!isFinite(e))return!1;var f=function(a,b){var c=Math.pow(10,b);a*=c;var d=a>0|-(0>a),e=a%1===.5*d;return e?(Math.floor(a)+(d>0))/c:Math.round(a)/c},g=function(a,b){if(0==b)return 1;var c=(a+"").split("."),d=(b+"").split("."),e=(1==c.length?0:c[1].length)+(1==d.length?0:d[1].length);return f(a-b*Math.floor(a/b),e)},h=g(e-d.baseValue,d.step);return 0==h||h==d.step}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringLength={validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=a.trim(e).length;return d.min&&fd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={validate:function(a,b){var c=b.val();if(""==c)return!0;var d=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.zipCode={validate:function(a,b,c){var d=b.val();if(""==d||!c.country)return!0;switch(c.country=c.country||"US",c.country.toUpperCase()){case"DK":return/^(DK(-|\s)?)?\d{4}$/i.test(d);case"SE":return/^(S-)?\d{3}\s?\d{2}$/i.test(d);case"US":default:return/^\d{5}([\-]\d{4})?$/.test(d)}}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.0/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.4.0/css/bootstrapValidator.css new file mode 100644 index 000000000..20b84ba8d --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.0/css/bootstrapValidator.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form .help-block { + margin-bottom: 0; +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.0/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.4.0/css/bootstrapValidator.min.css new file mode 100644 index 000000000..c2e54e0ed --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.0/css/bootstrapValidator.min.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.0 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.0/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.4.0/js/bootstrapValidator.js new file mode 100644 index 000000000..0e47e963d --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.0/js/bootstrapValidator.js @@ -0,0 +1,2185 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.0 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + this.$invalidField = null; // First invalid field + this.$submitButton = null; // The submit button which is clicked to submit form + + // Validating status + this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED'; + this.STATUS_VALIDATING = 'VALIDATING'; + this.STATUS_INVALID = 'INVALID'; + this.STATUS_VALID = 'VALID'; + + this._init(); + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // Shows ok/error/loading icons based on the field validity. + // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation). + // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically. + // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later. + // + // Examples: + // - Use Glyphicons icons: + // feedbackIcons: { + // valid: 'glyphicon glyphicon-ok', + // invalid: 'glyphicon glyphicon-remove', + // validating: 'glyphicon glyphicon-refresh' + // } + // - Use FontAwesome icons: + // feedbackIcons: { + // valid: 'fa fa-check', + // invalid: 'fa fa-times', + // validating: 'fa fa-refresh' + // } + feedbackIcons: { + valid: null, + invalid: null, + validating: null + }, + + // The submit buttons selector + // These buttons will be disabled to prevent the valid form from multiple submissions + submitButtons: 'button[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submission + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating option + // Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + var that = this, + options = { + trigger: this.$form.attr('data-bv-trigger'), + message: this.$form.attr('data-bv-message'), + submitButtons: this.$form.attr('data-bv-submitbuttons'), + live: this.$form.attr('data-bv-live'), + 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') + } + }, + validator, + v, // Validator name + enabled, + optionName, + optionValue, + html5AttrName, + html5Attrs; + + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + // Disable the default submission first + .on('submit.bv', function(e) { + e.preventDefault(); + that.validate(); + }) + .on('click', this.options.submitButtons, function() { + that.$submitButton = $(this); + }) + // Find all fields which have either "name" or "data-bv-field" attribute + .find('[name], [data-bv-field]').each(function() { + var $field = $(this); + // Don't initialize hidden input + if ('hidden' == $field.attr('type')) { + return; + } + + var field = $field.attr('name') || $field.attr('data-bv-field'); + $field.attr('data-bv-field', field); + + options.fields[field] = $.extend({}, { + trigger: $field.attr('data-bv-trigger'), + message: $field.attr('data-bv-message'), + container: $field.attr('data-bv-container'), + selector: $field.attr('data-bv-selector'), + validators: {} + }, options.fields[field]); + + for (v in $.fn.bootstrapValidator.validators) { + validator = $.fn.bootstrapValidator.validators[v]; + enabled = $field.attr('data-bv-' + v.toLowerCase()) + ''; + html5Attrs = ('function' == typeof validator.enableByHtml5) ? validator.enableByHtml5($(this)) : null; + + if ((html5Attrs && enabled != 'false') + || (html5Attrs !== true && ('' == enabled || 'true' == enabled))) + { + // Try to parse the options via attributes + validator.html5Attributes = validator.html5Attributes || { message: 'message' }; + options.fields[field]['validators'][v] = $.extend({}, html5Attrs == true ? {} : html5Attrs, options.fields[field]['validators'][v]); + + for (html5AttrName in validator.html5Attributes) { + optionName = validator.html5Attributes[html5AttrName]; + optionValue = $field.attr('data-bv-' + v.toLowerCase() + '-' + html5AttrName); + if (optionValue) { + if ('true' == optionValue) { + optionValue = true; + } else if ('false' == optionValue) { + optionValue = false; + } + options.fields[field]['validators'][v][optionName] = optionValue; + } + } + } + } + }); + + this.options = $.extend(true, this.options, options); + + for (var field in this.options.fields) { + this._initField(field); + } + + this.setLiveMode(this.options.live); + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + var fields = this.getFieldElements(field); + + // We don't need to validate non-existing fields + if (fields == null) { + delete this.options.fields[field]; + return; + } + for (var validatorName in this.options.fields[field].validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + delete this.options.fields[field].validators[validatorName]; + } + } + + var that = this, + type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup', + total = fields.length, + updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type); + + for (var i = 0; i < total; i++) { + var $field = $(fields[i]), + $parent = $field.parents('.form-group'), + // Allow user to indicate where the error messages are shown + $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field); + + // Set the attribute to indicate the fields which are defined by selector + if (!$field.attr('data-bv-field')) { + $field.attr('data-bv-field', field); + } + + // Whenever the user change the field value, mark it as not validated yet + $field.on(event + '.update.bv', function() { + updateAll ? that.updateStatus(field, that.STATUS_NOT_VALIDATED, null) + : that.updateElementStatus($(this), that.STATUS_NOT_VALIDATED, null); + }); + + // Create help block elements for showing the error messages + $field.data('bv.messages', $message); + for (validatorName in this.options.fields[field].validators) { + $field.data('bv.result.' + validatorName, this.STATUS_NOT_VALIDATED); + + if (!updateAll || i == total - 1) { + $('') + .css('display', 'none') + .attr('data-bv-validator', validatorName) + .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message) + .addClass('help-block') + .appendTo($message); + } + } + + // Prepare the feedback icons + // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation) + if (this.options.feedbackIcons + && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid + && (!updateAll || i == total - 1)) + { + $parent.addClass('has-feedback'); + var $icon = $('').css('display', 'none').addClass('form-control-feedback').attr('data-bv-field', field).insertAfter($field); + // The feedback icon does not render correctly if there is no label + // https://github.com/twbs/bootstrap/issues/12873 + if ($parent.find('label').length == 0) { + $icon.css('top', 0); + } + } + } + + if (this.options.fields[field]['enabled'] == null) { + this.options.fields[field]['enabled'] = true; + } + }, + + /** + * Get the element to place the error messages + * + * @param {jQuery} $field The field element + * @returns {jQuery} + */ + _getMessageContainer: function($field) { + var $parent = $field.parent(); + if ($parent.hasClass('form-group')) { + return $parent; + } + + var cssClasses = $parent.attr('class'); + if (!cssClasses) { + return this._getMessageContainer($parent); + } + + cssClasses = cssClasses.split(' '); + var n = cssClasses.length; + for (var i = 0; i < n; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i]) || /^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + return $parent; + } + } + + return this._getMessageContainer($parent); + }, + + /** + * Called when all validations are completed + */ + _submit: function() { + if (!this.isValid()) { + if ('submitted' == this.options.live) { + this.setLiveMode('enabled'); + } + + // Focus to the first invalid field + if (this.$invalidField) { + this.$invalidField.focus(); + } + return; + } + + // Call the custom submission if enabled + if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + // Turn off the submit handler, so user can call form.submit() inside their submitHandler method + this.$form.off('submit.bv'); + this.options.submitHandler.call(this, this, this.$form, this.$submitButton); + } else { + this.disableSubmitButtons(true); + + // Submit form + this.$form.off('submit.bv').submit(); + } + }, + + // --- Public methods --- + + /** + * Retrieve the field elements by given name + * + * @param {String} field The field name + * @returns {null|jQuery[]} + */ + getFieldElements: function(field) { + var fields = this.$form.find(this.options.fields[field].selector || '[name="' + field + '"]'); + return (fields.length == 0) ? null : fields; + }, + + /** + * Set live validating mode + * + * @param {String} mode Live validating mode. Can be 'enabled', 'disabled', 'submitted' + * @returns {BootstrapValidator} + */ + setLiveMode: function(mode) { + this.options.live = mode; + if ('submitted' == mode) { + return this; + } + + var that = this; + for (var field in this.options.fields) { + (function(f) { + var fields = that.getFieldElements(f); + if (fields) { + var type = fields.attr('type'), + total = fields.length, + updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type), + trigger = that.options.fields[field].trigger + || that.options.trigger + || (('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup'), + events = trigger.split(' ').map(function(item) { + return item + '.live.bv'; + }).join(' '); + + for (var i = 0; i < total; i++) { + ('enabled' == mode) + ? $(fields[i]).on(events, function() { + updateAll ? that.validateField(f) : that.validateFieldElement($(this), false); + }) + : $(fields[i]).off(events); + } + } + })(field); + } + + return this; + }, + + /** + * Disable/enable submit buttons + * + * @param {Boolean} disabled Can be true or false + * @returns {BootstrapValidator} + */ + disableSubmitButtons: function(disabled) { + if (!disabled) { + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + } else if (this.options.live != 'disabled') { + // Don't disable if the live validating mode is disabled + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + } + return this; + }, + + /** + * Validate the form + * + * @return {BootstrapValidator} + */ + validate: function() { + if (!this.options.fields) { + return this; + } + this.disableSubmitButtons(true); + + for (var field in this.options.fields) { + this.validateField(field); + } + + this._submit(); + return this; + }, + + /** + * Validate given field + * + * @param {String} field The field element + * @returns {BootstrapValidator} + */ + validateField: function(field) { + var fields = this.getFieldElements(field), + type = fields.attr('type'), + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (var i = 0; i < n; i++) { + this.validateFieldElement($(fields[i]), (n == 1)); + } + + return this; + }, + + /** + * Validate field element + * + * @param {jQuery} $field The field element + * @param {Boolean} updateAll If true, update status of all elements which have the same name + * @returns {BootstrapValidator} + */ + validateFieldElement: function($field, updateAll) { + var that = this, + field = $field.attr('data-bv-field'), + validators = this.options.fields[field].validators, + validatorName, + validateResult; + + // We don't need to validate disabled, hidden field + if ($field.is(':disabled') || $field.is(':hidden') || !$field.is(':visible')) { + return this; + } + + for (validatorName in validators) { + if ($field.data('bv.dfs.' + validatorName)) { + $field.data('bv.dfs.' + validatorName).reject(); + } + + // Don't validate field if it is already done + var result = $field.data('bv.result.' + validatorName); + if (result == this.STATUS_VALID || result == this.STATUS_INVALID) { + continue; + } + + $field.data('bv.result.' + validatorName, this.STATUS_VALIDATING); + validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]); + + if ('object' == typeof validateResult) { + updateAll ? this.updateStatus(field, this.STATUS_VALIDATING, validatorName) + : this.updateElementStatus($field, this.STATUS_VALIDATING, validatorName); + $field.data('bv.dfs.' + validatorName, validateResult); + + validateResult.done(function($f, v, isValid) { + // v is validator name + $f.removeData('bv.dfs.' + v); + updateAll ? that.updateStatus($f.attr('data-bv-field'), isValid ? that.STATUS_VALID : that.STATUS_INVALID, v) + : that.updateElementStatus($f, isValid ? that.STATUS_VALID : that.STATUS_INVALID, v); + + if (isValid && 'disabled' == that.options.live) { + that._submit(); + } + }); + } else if ('boolean' == typeof validateResult) { + updateAll ? this.updateStatus(field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName) + : this.updateElementStatus($field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName); + } + } + + return this; + }, + + /** + * Update all validating results of elements which have the same field name + * + * @param {String} field The field name + * @param {String} status The status + * Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String|null} validatorName The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateStatus: function(field, status, validatorName) { + var fields = this.getFieldElements(field), + type = fields.attr('type'), + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (var i = 0; i < n; i++) { + this.updateElementStatus($(fields[i]), status, validatorName); + } + + return this; + }, + + /** + * Update validating result of given element + * + * @param {String} field The field name + * @param {String} status The status + * Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String|null} validatorName The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateElementStatus: function($field, status, validatorName) { + var that = this, + field = $field.attr('data-bv-field'), + $parent = $field.parents('.form-group'), + $message = $field.data('bv.messages'), + $errors = $message.find('.help-block[data-bv-validator]'), + $icon = $parent.find('.form-control-feedback[data-bv-field="' + field + '"]'); + + // Update status + if (validatorName) { + $field.data('bv.result.' + validatorName, status); + } else { + for (var v in this.options.fields[field].validators) { + $field.data('bv.result.' + v, status); + } + } + + // Show/hide error elements and feedback icons + switch (status) { + case this.STATUS_VALIDATING: + this.disableSubmitButtons(true); + $parent.removeClass('has-success').removeClass('has-error'); + // TODO: Show validating message + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(); + } + break; + + case this.STATUS_INVALID: + this.disableSubmitButtons(true); + $parent.removeClass('has-success').addClass('has-error'); + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').show() : $errors.show(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(); + } + break; + + case this.STATUS_VALID: + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + + // If the field is valid (passes all validators) + if ($errors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || ($field.data('bv.result.' + v) != that.STATUS_VALID); + }).length == 0) + { + this.disableSubmitButtons(false); + $parent.removeClass('has-error').addClass('has-success'); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.valid).show(); + } + } else { + this.disableSubmitButtons(true); + $parent.removeClass('has-success').addClass('has-error'); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(); + } + } + break; + + case this.STATUS_NOT_VALIDATED: + default: + this.disableSubmitButtons(false); + $parent.removeClass('has-success').removeClass('has-error'); + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide(); + } + break; + } + + return this; + }, + + /** + * Check the form validity + * + * @returns {Boolean} + */ + isValid: function() { + var fields, field, $field, + type, status, validatorName, + n, i; + for (field in this.options.fields) { + if (this.options.fields[field] == null || !this.options.fields[field]['enabled']) { + continue; + } + + fields = this.getFieldElements(field); + type = fields.attr('type'); + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (i = 0; i < n; i++) { + $field = $(fields[i]); + if ($field.is(':disabled') || $field.is(':hidden') || !$field.is(':visible')) { + continue; + } + + for (validatorName in this.options.fields[field].validators) { + status = $field.data('bv.result.' + validatorName); + if (status == this.STATUS_NOT_VALIDATED || status == this.STATUS_VALIDATING) { + return false; + } + + if (status == this.STATUS_INVALID) { + this.$invalidField = $field; + return false; + } + } + } + } + + return true; + }, + + // Useful APIs which aren't used internally + + /** + * Reset the form + * + * @param {Boolean} resetFormData Reset current form data + * @return {BootstrapValidator} + */ + resetForm: function(resetFormData) { + var field, fields, total, type, validator; + for (field in this.options.fields) { + fields = this.getFieldElements(field); + total = fields.length; + + for (var i = 0; i < total; i++) { + for (validator in this.options.fields[field].validators) { + $(fields[i]).removeData('bv.dfs.' + validator); + } + } + + // Mark field as not validated yet + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + if (resetFormData) { + type = fields.attr('type'); + ('radio' == type || 'checkbox' == type) ? fields.removeAttr('checked').removeAttr('selected') : fields.val(''); + } + } + + this.$invalidField = null; + this.$submitButton = null; + + // Enable submit buttons + this.disableSubmitButtons(false); + + return this; + }, + + /** + * Enable/Disable all validators to given field + * + * @param {String} field The field name + * @param {Boolean} enabled Enable/Disable field validators + * @return {BootstrapValidator} + */ + enableFieldValidators: function(field, enabled) { + this.options.fields[field]['enabled'] = enabled; + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + return this; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(options) { + return this.each(function() { + var $this = $(this), data = $this.data('bootstrapValidator'); + if (!data) { + $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options))); + } + if ('string' == typeof options) { + data[options](); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.base64 = { + /** + * Return true if the input value is a base 64 encoded string. + * + * @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; + } + + return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + if ('range' == $field.attr('type')) { + return { + min: $field.attr('min'), + max: $field.attr('max') + }; + } + + return false; + }, + + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = parseFloat(value); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {Boolean|Deferred} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (options.callback && 'function' == typeof options.callback) { + var dfd = new $.Deferred(); + dfd.resolve($field, 'callback', options.callback.call(this, value, validator)); + return dfd; + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.choice = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max' + }, + + /** + * Check if the number of checked boxes are less or more than a given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var numChoices = validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length; + if ((options.min && numChoices < options.min) || (options.max && numChoices > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + value = value.replace(/\D/g, ''); + + // Validate the check sum + // The Luhn Algorithm + // http://en.wikipedia.org/wiki/Luhn + var check = 0, digit = 0, even = false, length = value.length; + + for (var n = length - 1; n >= 0; n--) { + digit = parseInt(value.charAt(n), 10); + + if (even) { + if ((digit *= 2) > 9) { + digit -= 9; + } + } + + check += digit; + even = !even; + } + + if ((check % 10) != 0) { + return false; + } + + // Validate the card number based on prefix (IIN ranges) and length + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + + var type, i; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (value.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(value.length) != -1) // and length + { + return true; + } + } + } + + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.cvv = { + html5Attributes: { + message: 'message', + ccfield: 'creditCardField' + }, + + /** + * Return true if the input value is a valid CVV number. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - creditCardField: The credit card number field. It can be null + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^[0-9]{3,4}$/.test(value)) { + return false; + } + + if (!options.creditCardField) { + return true; + } + + // Get the credit card number + var creditCard = validator.getFieldElements(options.creditCardField).val(); + if (creditCard == '') { + return true; + } + + // Supported credit card types + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + var type, i, creditCardType = null; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (creditCard.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(creditCard.length) != -1) // and length + { + creditCardType = type; + break; + } + } + } + + return (creditCardType == null) + ? false + : (('AMERICAN_EXPRESS' == creditCardType) ? (value.length == 4) : (value.length == 3)); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.date = { + html5Attributes: { + message: 'message', + format: 'format' + }, + + /** + * Return true if the input value is valid date + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - format: The date format. Default is MM/DD/YYYY + * Support the following formats: + * YYYY/DD/MM + * YYYY/DD/MM h:m A + * YYYY/MM/DD + * YYYY/MM/DD h:m A + * + * YYYY-DD-MM + * YYYY-DD-MM h:m A + * YYYY-MM-DD + * YYYY-MM-DD h:m A + * + * MM/DD/YYYY + * MM/DD/YYYY h:m A + * DD/MM/YYYY + * DD/MM/YYYY h:m A + * + * MM-DD-YYYY + * MM-DD-YYYY h:m A + * DD-MM-YYYY + * DD-MM-YYYY h:m A + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + // Determine the separator + options.format = options.format || 'MM/DD/YYYY'; + var separator = (options.format.indexOf('/') != -1) + ? '/' + : ((options.format.indexOf('-') != -1) ? '-' : null); + if (separator == null) { + return false; + } + + var month, day, year, minutes = null, hours = null, matches; + switch (true) { + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/DD/MM'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-DD-MM'): + year = matches[1]; day = matches[2]; month = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'DD/MM/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'DD-MM-YYYY'): + day = matches[1]; month = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/MM/DD'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-MM-DD'): + year = matches[1]; month = matches[2]; day = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'MM/DD/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'MM-DD-YYYY'): + month = matches[1]; day = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/DD/MM h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-DD-MM h:m A'): + year = matches[1]; day = matches[2]; month = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD/MM/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD-MM-YYYY h:m A'): + day = matches[1]; month = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/MM/DD h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-MM-DD h:m A'): + year = matches[1]; month = matches[2]; day = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM/DD/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM-DD-YYYY h:m A'): + month = matches[1]; day = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + default: + return false; + } + + // Validate hours and minutes + if (hours && minutes) { + hours = parseInt(hours, 10); + minutes = parseInt(minutes, 10); + if (hours < 1 || hours > 12 || minutes < 0 || minutes > 59) { + return false; + } + } + + // Validate day, month, and year + day = parseInt(day, 10); + month = parseInt(month, 10); + year = parseInt(year, 10); + + if (year < 1000 || year > 9999 || month == 0 || month > 12) { + return false; + } + + var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + // Update the number of days in Feb of leap year + if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) { + numDays[1] = 29; + } + + // Check the day + return (day > 0 && day <= numDays[month - 1]); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.different = { + html5Attributes: { + message: 'message', + field: 'field' + }, + + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value != compareWith.val()) { + validator.updateStatus(options.field, validator.STATUS_VALID, 'different'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^\d+$/.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + enableByHtml5: function($field) { + return ('email' == $field.attr('type')); + }, + + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + html5Attributes: { + message: 'message', + value: 'value', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + var min = $field.attr('min'); + if (min) { + return { + value: min + }; + } + + return false; + }, + + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hex = { + /** + * Return true if and only if the input value is a valid hexadecimal number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^[0-9a-fA-F]+$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + enableByHtml5: function($field) { + return ('color' == $field.attr('type')); + }, + + /** + * Return true if the input value is a valid hex color + * + * @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; + } + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.iban = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Validate an International Bank Account Number (IBAN) + * To test it, take the sample IBAN from + * http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html + * + * @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 + * - country: The ISO 3166-1 country code + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // See + // http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf + // http://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country + var ibanRegex = { + '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 + }; + value = value.replace(/[^a-zA-Z0-9]/g, '').toUpperCase(); + var country = options.country || value.substr(0, 2); + if (!ibanRegex[country]) { + return false; + } + if (!(new RegExp('^' + ibanRegex[country] + '$')).test(value)) { + return false; + } + + value = value.substr(4) + value.substr(0, 4); + value = value.split('').map(function(n) { + var code = n.charCodeAt(0); + return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) + // Replace A, B, C, ..., Z with 10, 11, ..., 35 + ? (code - 'A'.charCodeAt(0) + 10) + : n; + }).join(''); + + var temp = parseInt(value.substr(0, 1), 10), + length = value.length; + for (var i = 1; i < length; ++i) { + temp = (temp * 10 + parseInt(value.substr(i, 1), 10)) % 97; + } + return (temp == 1); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + html5Attributes: { + message: 'message', + field: 'field' + }, + + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value == compareWith.val()) { + validator.updateStatus(options.field, validator.STATUS_VALID, 'identical'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.integer = { + enableByHtml5: function($field) { + return ('number' == $field.attr('type')); + }, + + /** + * Return true if the input value is an integer + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + return /^(?:-?(?:0|[1-9][0-9]*))$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.ip = { + html5Attributes: { + message: 'message', + ipv4: 'ipv4', + ipv6: 'ipv6' + }, + + /** + * Return true if the input value is a IP address. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - ipv4: Enable IPv4 validator, default to true + * - ipv6: Enable IPv6 validator, default to true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + options = $.extend({}, { ipv4: true, ipv6: true }, options); + + if (options.ipv4) { + return /^(?:(?: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); + } else if (options.ipv6) { + return /^\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(str); + } + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.isbn = { + /** + * Return true if the input value is a valid ISBN 10 or ISBN 13 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; + } + + // Replace all special characters except digits and X + value = value.replace(/[^\dX]/gi, ''); + var chars = value.split(''), + sum = 0, + checksum; + + // See http://en.wikipedia.org/wiki/International_Standard_Book_Number + switch (chars.length) { + // ISBN 10 + case 10: + sum = 0; + for (var i = 0; i < 9; i++) { + sum += ((10 - i) * parseInt(chars[i])); + } + checksum = 11 - (sum % 11); + if (checksum == 11) { + checksum = 0; + } else if (checksum == 10) { + checksum = 'X'; + } + return (checksum == chars[9]); + + // ISBN 13 + case 13: + sum = 0; + for (var i = 0; i < 12; i++) { + sum += ((i % 2 == 0) ? parseInt(chars[i]) : (parseInt(chars[i]) * 3)); + } + checksum = 10 - (sum % 10); + if (checksum == 10) { + checksum = '0'; + } + return (checksum == chars[12]); + + default: + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + html5Attributes: { + message: 'message', + value: 'value', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + var max = $field.attr('max'); + if (max) { + return { + value: max + }; + } + + return false; + }, + + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === false) ? (value <= options.value) : (value < options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.mac = { + /** + * Return true if the input value is a MAC address. + * + * @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; + } + + return /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + enableByHtml5: function($field) { + var required = $field.attr('required') + ''; + return ('required' == required || 'true' == required); + }, + + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + if ('radio' == type || 'checkbox' == type) { + return validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length > 0; + } + + return $.trim($field.val()) != ''; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.numeric = { + /** + * Validate decimal number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return !isNaN(parseFloat(value)) && isFinite(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.phone = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Return true if the input value contains a valid US phone number only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166 country code + * Currently it only supports United State (US) country + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options.country = options.country || 'US'; + switch (options.country.toUpperCase()) { + case 'US': + default: + value = value.replace(/\(|\)|\s+/g, ''); + return (/^(?:1\-?)?(\d{3})[\-\.]?(\d{3})[\-\.]?(\d{4})$/).test(value); + } + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + html5Attributes: { + message: 'message', + regexp: 'regexp' + }, + + enableByHtml5: function($field) { + var pattern = $field.attr('pattern'); + if (pattern) { + return { + regexp: pattern + }; + } + + return false; + }, + + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var regexp = ('string' == typeof options.regexp) ? new RegExp(options.regexp) : options.regexp; + return regexp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.remote = { + html5Attributes: { + message: 'message', + url: 'url' + }, + + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - message: The invalid message + * @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; + if (data == null) { + data = {}; + } + // Support dynamic data + if ('function' == typeof data) { + data = data.call(this, validator); + } + data[name] = value; + + var dfd = new $.Deferred(); + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }); + xhr.then(function(response) { + dfd.resolve($field, 'remote', response.valid === true || response.valid === 'true'); + }); + + dfd.fail(function() { + xhr.abort(); + }); + + return dfd; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.step = { + html5Attributes: { + message: 'message', + base: 'baseValue', + step: 'step' + }, + + /** + * Return true if the input value is valid step one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - baseValue: The base value + * - step: The step + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options = $.extend({}, { baseValue: 0, step: 1 }, options); + value = parseFloat(value); + if (isNaN(value) || !isFinite(value)) { + return false; + } + + var round = function(x, precision) { + var m = Math.pow(10, precision); + x = x * m; + var sign = (x > 0) | -(x < 0), + isHalf = (x % 1 === 0.5 * sign); + if (isHalf) { + return (Math.floor(x) + (sign > 0)) / m; + } else { + return Math.round(x) / m; + } + }, + floatMod = function(x, y) { + if (y == 0.0) { + return 1.0; + } + var dotX = (x + '').split('.'), + dotY = (y + '').split('.'), + precision = ((dotX.length == 1) ? 0 : dotX[1].length) + ((dotY.length == 1) ? 0 : dotY[1].length); + return round(x - y * Math.floor(x / y), precision); + }; + + var mod = floatMod(value - options.baseValue, options.step); + return (mod == 0.0 || mod == options.step); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringCase = { + html5Attributes: { + message: 'message', + case: 'case' + }, + + /** + * Check if a string is a lower or upper case one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - case: Can be 'lower' (default) or 'upper' + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var stringCase = (options.case || 'lower').toLowerCase(); + switch (stringCase) { + case 'upper': + return value === value.toUpperCase(); + case 'lower': + default: + return value === value.toLowerCase(); + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max' + }, + + enableByHtml5: function($field) { + var maxLength = $field.attr('maxlength'); + if (maxLength) { + return { + max: parseInt(maxLength, 10) + }; + } + + return false; + }, + + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var length = $.trim(value).length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + enableByHtml5: function($field) { + return ('url' == $field.attr('type')); + }, + + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uuid = { + html5Attributes: { + message: 'message', + version: 'version' + }, + + /** + * Return true if and only if the input value is a valid UUID string + * + * @see http://en.wikipedia.org/wiki/Universally_unique_identifier + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - version: Can be 3, 4, 5, null + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // See the format at http://en.wikipedia.org/wiki/Universally_unique_identifier#Variants_and_versions + var patterns = { + '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, + '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i + }, + version = options.version ? (options.version + '') : 'all'; + return (null == patterns[version]) ? true : patterns[version].test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.zipCode = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Return true if and only if the input value is a valid country zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166 country code + * + * Currently it supports the following countries: + * - US (United State) + * - DK (Denmark) + * - SE (Sweden) + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '' || !options.country) { + return true; + } + + options.country = options.country || 'US'; + switch (options.country.toUpperCase()) { + case 'DK': + return /^(DK(-|\s)?)?\d{4}$/i.test(value); + case 'SE': + return /^(S-)?\d{3}\s?\d{2}$/i.test(value); + case 'US': + default: + return /^\d{5}([\-]\d{4})?$/.test(value); + } + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.0/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.4.0/js/bootstrapValidator.min.js new file mode 100644 index 000000000..883e547b9 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.0/js/bootstrapValidator.min.js @@ -0,0 +1,12 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.0 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),this.$invalidField=null,this.$submitButton=null,this.STATUS_NOT_VALIDATED="NOT_VALIDATED",this.STATUS_VALIDATING="VALIDATING",this.STATUS_INVALID="INVALID",this.STATUS_VALID="VALID",this._init()};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",feedbackIcons:{valid:null,invalid:null,validating:null},submitButtons:'button[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){var b,c,d,e,f,g,h,i=this,j={trigger:this.$form.attr("data-bv-trigger"),message:this.$form.attr("data-bv-message"),submitButtons:this.$form.attr("data-bv-submitbuttons"),live:this.$form.attr("data-bv-live"),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")}};this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit.bv",function(a){a.preventDefault(),i.validate()}).on("click",this.options.submitButtons,function(){i.$submitButton=a(this)}).find("[name], [data-bv-field]").each(function(){var i=a(this);if("hidden"!=i.attr("type")){var k=i.attr("name")||i.attr("data-bv-field");i.attr("data-bv-field",k),j.fields[k]=a.extend({},{trigger:i.attr("data-bv-trigger"),message:i.attr("data-bv-message"),container:i.attr("data-bv-container"),selector:i.attr("data-bv-selector"),validators:{}},j.fields[k]);for(c in a.fn.bootstrapValidator.validators)if(b=a.fn.bootstrapValidator.validators[c],d=i.attr("data-bv-"+c.toLowerCase())+"",h="function"==typeof b.enableByHtml5?b.enableByHtml5(a(this)):null,h&&"false"!=d||h!==!0&&(""==d||"true"==d)){b.html5Attributes=b.html5Attributes||{message:"message"},j.fields[k].validators[c]=a.extend({},1==h?{}:h,j.fields[k].validators[c]);for(g in b.html5Attributes)e=b.html5Attributes[g],f=i.attr("data-bv-"+c.toLowerCase()+"-"+g),f&&("true"==f?f=!0:"false"==f&&(f=!1),j.fields[k].validators[c][e]=f)}}}),this.options=a.extend(!0,this.options,j);for(var k in this.options.fields)this._initField(k);this.setLiveMode(this.options.live)},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){var c=this.getFieldElements(b);if(null==c)return void delete this.options.fields[b];for(var d in this.options.fields[b].validators)a.fn.bootstrapValidator.validators[d]||delete this.options.fields[b].validators[d];for(var e=this,f=c.attr("type"),g="radio"==f||"checkbox"==f||"file"==f||"SELECT"==c[0].tagName?"change":"keyup",h=c.length,i=1==h||"radio"==f||"checkbox"==f,j=0;h>j;j++){var k=a(c[j]),l=k.parents(".form-group"),m=this.options.fields[b].container?l.find(this.options.fields[b].container):this._getMessageContainer(k);k.attr("data-bv-field")||k.attr("data-bv-field",b),k.on(g+".update.bv",function(){i?e.updateStatus(b,e.STATUS_NOT_VALIDATED,null):e.updateElementStatus(a(this),e.STATUS_NOT_VALIDATED,null)}),k.data("bv.messages",m);for(d in this.options.fields[b].validators)k.data("bv.result."+d,this.STATUS_NOT_VALIDATED),i&&j!=h-1||a("").css("display","none").attr("data-bv-validator",d).html(this.options.fields[b].validators[d].message||this.options.fields[b].message||this.options.message).addClass("help-block").appendTo(m);if(this.options.feedbackIcons&&this.options.feedbackIcons.validating&&this.options.feedbackIcons.invalid&&this.options.feedbackIcons.valid&&(!i||j==h-1)){l.addClass("has-feedback");var n=a("").css("display","none").addClass("form-control-feedback").attr("data-bv-field",b).insertAfter(k);0==l.find("label").length&&n.css("top",0)}}null==this.options.fields[b].enabled&&(this.options.fields[b].enabled=!0)}},_getMessageContainer:function(a){var b=a.parent();if(b.hasClass("form-group"))return b;var c=b.attr("class");if(!c)return this._getMessageContainer(b);c=c.split(" ");for(var d=c.length,e=0;d>e;e++)if(/^col-(xs|sm|md|lg)-\d+$/.test(c[e])||/^col-(xs|sm|md|lg)-offset-\d+$/.test(c[e]))return b;return this._getMessageContainer(b)},_submit:function(){return this.isValid()?void(this.options.submitHandler&&"function"==typeof this.options.submitHandler?(this.$form.off("submit.bv"),this.options.submitHandler.call(this,this,this.$form,this.$submitButton)):(this.disableSubmitButtons(!0),this.$form.off("submit.bv").submit())):("submitted"==this.options.live&&this.setLiveMode("enabled"),void(this.$invalidField&&this.$invalidField.focus()))},getFieldElements:function(a){var b=this.$form.find(this.options.fields[a].selector||'[name="'+a+'"]');return 0==b.length?null:b},setLiveMode:function(b){if(this.options.live=b,"submitted"==b)return this;var c=this;for(var d in this.options.fields)!function(e){var f=c.getFieldElements(e);if(f)for(var g=f.attr("type"),h=f.length,i=1==h||"radio"==g||"checkbox"==g,j=c.options.fields[d].trigger||c.options.trigger||("radio"==g||"checkbox"==g||"file"==g||"SELECT"==f[0].tagName?"change":"keyup"),k=j.split(" ").map(function(a){return a+".live.bv"}).join(" "),l=0;h>l;l++)"enabled"==b?a(f[l]).on(k,function(){i?c.validateField(e):c.validateFieldElement(a(this),!1)}):a(f[l]).off(k)}(d);return this},disableSubmitButtons:function(a){return a?"disabled"!=this.options.live&&this.$form.find(this.options.submitButtons).attr("disabled","disabled"):this.$form.find(this.options.submitButtons).removeAttr("disabled"),this},validate:function(){if(!this.options.fields)return this;this.disableSubmitButtons(!0);for(var a in this.options.fields)this.validateField(a);return this._submit(),this},validateField:function(b){for(var c=this.getFieldElements(b),d=c.attr("type"),e="radio"==d||"checkbox"==d?1:c.length,f=0;e>f;f++)this.validateFieldElement(a(c[f]),1==e);return this},validateFieldElement:function(b,c){var d,e,f=this,g=b.attr("data-bv-field"),h=this.options.fields[g].validators;if(b.is(":disabled")||b.is(":hidden")||!b.is(":visible"))return this;for(d in h){b.data("bv.dfs."+d)&&b.data("bv.dfs."+d).reject();var i=b.data("bv.result."+d);i!=this.STATUS_VALID&&i!=this.STATUS_INVALID&&(b.data("bv.result."+d,this.STATUS_VALIDATING),e=a.fn.bootstrapValidator.validators[d].validate(this,b,h[d]),"object"==typeof e?(c?this.updateStatus(g,this.STATUS_VALIDATING,d):this.updateElementStatus(b,this.STATUS_VALIDATING,d),b.data("bv.dfs."+d,e),e.done(function(a,b,d){a.removeData("bv.dfs."+b),c?f.updateStatus(a.attr("data-bv-field"),d?f.STATUS_VALID:f.STATUS_INVALID,b):f.updateElementStatus(a,d?f.STATUS_VALID:f.STATUS_INVALID,b),d&&"disabled"==f.options.live&&f._submit()})):"boolean"==typeof e&&(c?this.updateStatus(g,e?this.STATUS_VALID:this.STATUS_INVALID,d):this.updateElementStatus(b,e?this.STATUS_VALID:this.STATUS_INVALID,d)))}return this},updateStatus:function(b,c,d){for(var e=this.getFieldElements(b),f=e.attr("type"),g="radio"==f||"checkbox"==f?1:e.length,h=0;g>h;h++)this.updateElementStatus(a(e[h]),c,d);return this},updateElementStatus:function(b,c,d){var e=this,f=b.attr("data-bv-field"),g=b.parents(".form-group"),h=b.data("bv.messages"),i=h.find(".help-block[data-bv-validator]"),j=g.find('.form-control-feedback[data-bv-field="'+f+'"]');if(d)b.data("bv.result."+d,c);else for(var k in this.options.fields[f].validators)b.data("bv.result."+k,c);switch(c){case this.STATUS_VALIDATING:this.disableSubmitButtons(!0),g.removeClass("has-success").removeClass("has-error"),d?i.filter('.help-block[data-bv-validator="'+d+'"]').hide():i.hide(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show();break;case this.STATUS_INVALID:this.disableSubmitButtons(!0),g.removeClass("has-success").addClass("has-error"),d?i.filter('[data-bv-validator="'+d+'"]').show():i.show(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show();break;case this.STATUS_VALID:d?i.filter('[data-bv-validator="'+d+'"]').hide():i.hide(),0==i.filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||b.data("bv.result."+d)!=e.STATUS_VALID}).length?(this.disableSubmitButtons(!1),g.removeClass("has-error").addClass("has-success"),j&&j.removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.valid).show()):(this.disableSubmitButtons(!0),g.removeClass("has-success").addClass("has-error"),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show());break;case this.STATUS_NOT_VALIDATED:default:this.disableSubmitButtons(!1),g.removeClass("has-success").removeClass("has-error"),d?i.filter('.help-block[data-bv-validator="'+d+'"]').hide():i.hide(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide()}return this},isValid:function(){var b,c,d,e,f,g,h,i;for(c in this.options.fields)if(null!=this.options.fields[c]&&this.options.fields[c].enabled)for(b=this.getFieldElements(c),e=b.attr("type"),h="radio"==e||"checkbox"==e?1:b.length,i=0;h>i;i++)if(d=a(b[i]),!d.is(":disabled")&&!d.is(":hidden")&&d.is(":visible"))for(g in this.options.fields[c].validators){if(f=d.data("bv.result."+g),f==this.STATUS_NOT_VALIDATED||f==this.STATUS_VALIDATING)return!1;if(f==this.STATUS_INVALID)return this.$invalidField=d,!1}return!0},resetForm:function(b){var c,d,e,f,g;for(c in this.options.fields){d=this.getFieldElements(c),e=d.length;for(var h=0;e>h;h++)for(g in this.options.fields[c].validators)a(d[h]).removeData("bv.dfs."+g);this.updateStatus(c,this.STATUS_NOT_VALIDATED,null),b&&(f=d.attr("type"),"radio"==f||"checkbox"==f?d.removeAttr("checked").removeAttr("selected"):d.val(""))}return this.$invalidField=null,this.$submitButton=null,this.disableSubmitButtons(!1),this},enableFieldValidators:function(a,b){return this.options.fields[a].enabled=b,this.updateStatus(a,this.STATUS_NOT_VALIDATED,null),this}},a.fn.bootstrapValidator=function(c){return this.each(function(){var d=a(this),e=d.data("bootstrapValidator");e||d.data("bootstrapValidator",e=new b(this,c)),"string"==typeof c&&e[c]()})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.base64={validate:function(a,b){var c=b.val();return""==c?!0:/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={html5Attributes:{message:"message",min:"min",max:"max",inclusive:"inclusive"},enableByHtml5:function(a){return"range"==a.attr("type")?{min:a.attr("min"),max:a.attr("max")}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(b,c,d){var e=c.val();if(d.callback&&"function"==typeof d.callback){var f=new a.Deferred;return f.resolve(c,"callback",d.callback.call(this,e,b)),f}return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.choice={html5Attributes:{message:"message",min:"min",max:"max"},validate:function(a,b,c){var d=a.getFieldElements(b.attr("data-bv-field")).filter(":checked").length;return c.min&&dc.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(a,b){var c=b.val();if(""==c)return!0;if(/[^0-9-\s]+/.test(c))return!1;c=c.replace(/\D/g,"");for(var d=0,e=0,f=!1,g=c.length,h=g-1;h>=0;h--)e=parseInt(c.charAt(h),10),f&&(e*=2)>9&&(e-=9),d+=e,f=!f;if(d%10!=0)return!1;var i,j,k={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["3528","3529","353","354","355","356","357","358"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}};for(i in k)for(j in k[i].prefix)if(c.substr(0,k[i].prefix[j].length)==k[i].prefix[j]&&-1!=k[i].length.indexOf(c.length))return!0;return!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.cvv={html5Attributes:{message:"message",ccfield:"creditCardField"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;if(!/^[0-9]{3,4}$/.test(d))return!1;if(!c.creditCardField)return!0;var e=a.getFieldElements(c.creditCardField).val();if(""==e)return!0;var f,g,h={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["3528","3529","353","354","355","356","357","358"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}},i=null;for(f in h)for(g in h[f].prefix)if(e.substr(0,h[f].prefix[g].length)==h[f].prefix[g]&&-1!=h[f].length.indexOf(e.length)){i=f;break}return null==i?!1:"AMERICAN_EXPRESS"==i?4==d.length:3==d.length}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.date={html5Attributes:{message:"message",format:"format"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;c.format=c.format||"MM/DD/YYYY";var e=-1!=c.format.indexOf("/")?"/":-1!=c.format.indexOf("-")?"-":null;if(null==e)return!1;var f,g,h,i,j=null,k=null;switch(!0){case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/DD/MM"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-DD-MM"==c.format:h=i[1],g=i[2],f=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"DD/MM/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"DD-MM-YYYY"==c.format:g=i[1],f=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/MM/DD"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-MM-DD"==c.format:h=i[1],f=i[2],g=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"MM/DD/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"MM-DD-YYYY"==c.format:f=i[1],g=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/DD/MM h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-DD-MM h:m A"==c.format:h=i[1],g=i[2],f=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD/MM/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD-MM-YYYY h:m A"==c.format:g=i[1],f=i[2],h=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/MM/DD h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-MM-DD h:m A"==c.format:h=i[1],f=i[2],g=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM/DD/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM-DD-YYYY h:m A"==c.format:f=i[1],g=i[2],h=i[3],k=i[4],j=i[5];break;default:return!1}if(k&&j&&(k=parseInt(k,10),j=parseInt(j,10),1>k||k>12||0>j||j>59))return!1;if(g=parseInt(g,10),f=parseInt(f,10),h=parseInt(h,10),1e3>h||h>9999||0==f||f>12)return!1;var l=[31,28,31,30,31,30,31,31,30,31,30,31];return(h%400==0||h%100!=0&&h%4==0)&&(l[1]=29),g>0&&g<=l[f-1]}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={html5Attributes:{message:"message",field:"field"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d!=e.val()?(a.updateStatus(c.field,a.STATUS_VALID,"different"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){var c=b.val();return""==c?!0:/^\d+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={enableByHtml5:function(a){return"email"==a.attr("type")},validate:function(a,b){var c=b.val();if(""==c)return!0;var d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={html5Attributes:{message:"message",value:"value",inclusive:"inclusive"},enableByHtml5:function(a){var b=a.attr("min");return b?{value:b}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.value:d>=c.value)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hex={validate:function(a,b){var c=b.val();return""==c?!0:/^[0-9a-fA-F]+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={enableByHtml5:function(a){return"color"==a.attr("type")},validate:function(a,b){var c=b.val();return""==c?!0:/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.iban={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e={AD:"AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}",AE:"AE[0-9]{2}[0-9]{3}[0-9]{16}",AL:"AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}",AO:"AO[0-9]{2}[0-9]{21}",AT:"AT[0-9]{2}[0-9]{5}[0-9]{11}",AZ:"AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}",BA:"BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}",BE:"BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}",BF:"BF[0-9]{2}[0-9]{23}",BG:"BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}",BH:"BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}",BI:"BI[0-9]{2}[0-9]{12}",BJ:"BJ[0-9]{2}[A-Z]{1}[0-9]{23}",BR:"BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]",CH:"CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}",CI:"CI[0-9]{2}[A-Z]{1}[0-9]{23}",CM:"CM[0-9]{2}[0-9]{23}",CR:"CR[0-9]{2}[0-9]{3}[0-9]{14}",CV:"CV[0-9]{2}[0-9]{21}",CY:"CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}",CZ:"CZ[0-9]{2}[0-9]{20}",DE:"DE[0-9]{2}[0-9]{8}[0-9]{10}",DK:"DK[0-9]{2}[0-9]{14}",DO:"DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}",DZ:"DZ[0-9]{2}[0-9]{20}",EE:"EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}",ES:"ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}",FI:"FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}",FO:"FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}",FR:"FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}",GB:"GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}",GE:"GE[0-9]{2}[A-Z]{2}[0-9]{16}",GI:"GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}",GL:"GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}",GR:"GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}",GT:"GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}",HR:"HR[0-9]{2}[0-9]{7}[0-9]{10}",HU:"HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}",IE:"IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}",IL:"IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}",IR:"IR[0-9]{2}[0-9]{22}",IS:"IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}",IT:"IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}",JO:"JO[0-9]{2}[A-Z]{4}[0-9]{4}[0]{8}[A-Z0-9]{10}",KW:"KW[0-9]{2}[A-Z]{4}[0-9]{22}",KZ:"KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}",LB:"LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}",LI:"LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}",LT:"LT[0-9]{2}[0-9]{5}[0-9]{11}",LU:"LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}",LV:"LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}",MC:"MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}",MD:"MD[0-9]{2}[A-Z0-9]{20}",ME:"ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",MG:"MG[0-9]{2}[0-9]{23}",MK:"MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}",ML:"ML[0-9]{2}[A-Z]{1}[0-9]{23}",MR:"MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}",MT:"MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}",MU:"MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}",MZ:"MZ[0-9]{2}[0-9]{21}",NL:"NL[0-9]{2}[A-Z]{4}[0-9]{10}",NO:"NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}",PK:"PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}",PL:"PL[0-9]{2}[0-9]{8}[0-9]{16}",PS:"PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}",PT:"PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}",QA:"QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}",RO:"RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}",RS:"RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",SA:"SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}",SE:"SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}",SI:"SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}",SK:"SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}",SM:"SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}",SN:"SN[0-9]{2}[A-Z]{1}[0-9]{23}",TN:"TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",TR:"TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}",VG:"VG[0-9]{2}[A-Z]{4}[0-9]{16}"};d=d.replace(/[^a-zA-Z0-9]/g,"").toUpperCase();var f=c.country||d.substr(0,2);if(!e[f])return!1;if(!new RegExp("^"+e[f]+"$").test(d))return!1;d=d.substr(4)+d.substr(0,4),d=d.split("").map(function(a){var b=a.charCodeAt(0);return b>="A".charCodeAt(0)&&b<="Z".charCodeAt(0)?b-"A".charCodeAt(0)+10:a}).join("");for(var g=parseInt(d.substr(0,1),10),h=d.length,i=1;h>i;++i)g=(10*g+parseInt(d.substr(i,1),10))%97;return 1==g}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={html5Attributes:{message:"message",field:"field"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d==e.val()?(a.updateStatus(c.field,a.STATUS_VALID,"identical"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.integer={enableByHtml5:function(a){return"number"==a.attr("type")},validate:function(a,b){var c=b.val();return""==c?!0:/^(?:-?(?:0|[1-9][0-9]*))$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.ip={html5Attributes:{message:"message",ipv4:"ipv4",ipv6:"ipv6"},validate:function(b,c,d){var e=c.val();return""==e?!0:(d=a.extend({},{ipv4:!0,ipv6:!0},d),d.ipv4?/^(?:(?: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(e):d.ipv6?/^\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(str):!1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.isbn={validate:function(a,b){var c=b.val();if(""==c)return!0;c=c.replace(/[^\dX]/gi,"");var d,e=c.split(""),f=0;switch(e.length){case 10:f=0;for(var g=0;9>g;g++)f+=(10-g)*parseInt(e[g]);return d=11-f%11,11==d?d=0:10==d&&(d="X"),d==e[9];case 13:f=0;for(var g=0;12>g;g++)f+=g%2==0?parseInt(e[g]):3*parseInt(e[g]);return d=10-f%10,10==d&&(d="0"),d==e[12];default:return!1}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={html5Attributes:{message:"message",value:"value",inclusive:"inclusive"},enableByHtml5:function(a){var b=a.attr("max");return b?{value:b}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!1?d<=c.value:d0:""!=a.trim(c.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.numeric={validate:function(a,b){var c=b.val();return""==c?!0:!isNaN(parseFloat(c))&&isFinite(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.phone={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;switch(c.country=c.country||"US",c.country.toUpperCase()){case"US":default:return d=d.replace(/\(|\)|\s+/g,""),/^(?:1\-?)?(\d{3})[\-\.]?(\d{3})[\-\.]?(\d{4})$/.test(d)}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.regexp={html5Attributes:{message:"message",regexp:"regexp"},enableByHtml5:function(a){var b=a.attr("pattern");return b?{regexp:b}:!1},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e="string"==typeof c.regexp?new RegExp(c.regexp):c.regexp;return e.test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.remote={html5Attributes:{message:"message",url:"url"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=c.attr("data-bv-field"),g=d.data;null==g&&(g={}),"function"==typeof g&&(g=g.call(this,b)),g[f]=e;var h=new a.Deferred,i=a.ajax({type:"POST",url:d.url,dataType:"json",data:g});return i.then(function(a){h.resolve(c,"remote",a.valid===!0||"true"===a.valid)}),h.fail(function(){i.abort()}),h}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.step={html5Attributes:{message:"message",base:"baseValue",step:"step"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;if(d=a.extend({},{baseValue:0,step:1},d),e=parseFloat(e),isNaN(e)||!isFinite(e))return!1;var f=function(a,b){var c=Math.pow(10,b);a*=c;var d=a>0|-(0>a),e=a%1===.5*d;return e?(Math.floor(a)+(d>0))/c:Math.round(a)/c},g=function(a,b){if(0==b)return 1;var c=(a+"").split("."),d=(b+"").split("."),e=(1==c.length?0:c[1].length)+(1==d.length?0:d[1].length);return f(a-b*Math.floor(a/b),e)},h=g(e-d.baseValue,d.step);return 0==h||h==d.step}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringCase={html5Attributes:{message:"message","case":"case"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=(c.case||"lower").toLowerCase();switch(e){case"upper":return d===d.toUpperCase();case"lower":default:return d===d.toLowerCase()}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringLength={html5Attributes:{message:"message",min:"min",max:"max"},enableByHtml5:function(a){var b=a.attr("maxlength");return b?{max:parseInt(b,10)}:!1},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=a.trim(e).length;return d.min&&fd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={enableByHtml5:function(a){return"url"==a.attr("type")},validate:function(a,b){var c=b.val();if(""==c)return!0;var d=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uuid={html5Attributes:{message:"message",version:"version"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i},f=c.version?c.version+"":"all";return null==e[f]?!0:e[f].test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.zipCode={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d||!c.country)return!0;switch(c.country=c.country||"US",c.country.toUpperCase()){case"DK":return/^(DK(-|\s)?)?\d{4}$/i.test(d);case"SE":return/^(S-)?\d{3}\s?\d{2}$/i.test(d);case"US":default:return/^\d{5}([\-]\d{4})?$/.test(d)}}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.1/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.4.1/css/bootstrapValidator.css new file mode 100644 index 000000000..20b84ba8d --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.1/css/bootstrapValidator.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form .help-block { + margin-bottom: 0; +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.1/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.4.1/css/bootstrapValidator.min.css new file mode 100644 index 000000000..71211fb5e --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.1/css/bootstrapValidator.min.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.1 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.1/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.4.1/js/bootstrapValidator.js new file mode 100644 index 000000000..86e6e2656 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.1/js/bootstrapValidator.js @@ -0,0 +1,2212 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.1 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + this.$invalidField = null; // First invalid field + this.$submitButton = null; // The submit button which is clicked to submit form + + // Validating status + this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED'; + this.STATUS_VALIDATING = 'VALIDATING'; + this.STATUS_INVALID = 'INVALID'; + this.STATUS_VALID = 'VALID'; + + // Determine the event that is fired when user change the field value + // Most modern browsers supports input event except IE 7, 8. + // IE 9 supports input event but the event is still not fired if I press the backspace key. + // In that case I will use the keydown event + var el = document.createElement('div'); + this._changeEvent = ('oninput' in el) ? 'input' : 'keydown'; + + // The flag to indicate that the form is ready to submit when a remote/callback validator returns + this._submitIfValid = null; + + this._init(); + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // Shows ok/error/loading icons based on the field validity. + // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation). + // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically. + // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later. + // + // Examples: + // - Use Glyphicons icons: + // feedbackIcons: { + // valid: 'glyphicon glyphicon-ok', + // invalid: 'glyphicon glyphicon-remove', + // validating: 'glyphicon glyphicon-refresh' + // } + // - Use FontAwesome icons: + // feedbackIcons: { + // valid: 'fa fa-check', + // invalid: 'fa fa-times', + // validating: 'fa fa-refresh' + // } + feedbackIcons: { + valid: null, + invalid: null, + validating: null + }, + + // The submit buttons selector + // These buttons will be disabled to prevent the valid form from multiple submissions + submitButtons: 'button[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submission + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating option + // Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + var that = this, + options = { + trigger: this.$form.attr('data-bv-trigger'), + message: this.$form.attr('data-bv-message'), + submitButtons: this.$form.attr('data-bv-submitbuttons'), + live: this.$form.attr('data-bv-live'), + 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') + } + }, + validator, + v, // Validator name + enabled, + optionName, + optionValue, + html5AttrName, + html5Attrs; + + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + // Disable the default submission first + .on('submit.bv', function(e) { + e.preventDefault(); + that.validate(); + }) + .on('click', this.options.submitButtons, function() { + that.$submitButton = $(this); + // The user just click the submit button + that._submitIfValid = true; + }) + // Find all fields which have either "name" or "data-bv-field" attribute + .find('[name], [data-bv-field]').each(function() { + var $field = $(this); + // Don't initialize hidden input + if ('hidden' == $field.attr('type')) { + return; + } + + var field = $field.attr('name') || $field.attr('data-bv-field'); + $field.attr('data-bv-field', field); + + options.fields[field] = $.extend({}, { + trigger: $field.attr('data-bv-trigger'), + message: $field.attr('data-bv-message'), + container: $field.attr('data-bv-container'), + selector: $field.attr('data-bv-selector'), + validators: {} + }, options.fields[field]); + + for (v in $.fn.bootstrapValidator.validators) { + validator = $.fn.bootstrapValidator.validators[v]; + enabled = $field.attr('data-bv-' + v.toLowerCase()) + ''; + html5Attrs = ('function' == typeof validator.enableByHtml5) ? validator.enableByHtml5($(this)) : null; + + if ((html5Attrs && enabled != 'false') + || (html5Attrs !== true && ('' == enabled || 'true' == enabled))) + { + // Try to parse the options via attributes + validator.html5Attributes = validator.html5Attributes || { message: 'message' }; + options.fields[field]['validators'][v] = $.extend({}, html5Attrs == true ? {} : html5Attrs, options.fields[field]['validators'][v]); + + for (html5AttrName in validator.html5Attributes) { + optionName = validator.html5Attributes[html5AttrName]; + optionValue = $field.attr('data-bv-' + v.toLowerCase() + '-' + html5AttrName); + if (optionValue) { + if ('true' == optionValue) { + optionValue = true; + } else if ('false' == optionValue) { + optionValue = false; + } + options.fields[field]['validators'][v][optionName] = optionValue; + } + } + } + } + }); + + this.options = $.extend(true, this.options, options); + + for (var field in this.options.fields) { + this._initField(field); + } + + this.setLiveMode(this.options.live); + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + var fields = this.getFieldElements(field); + + // We don't need to validate non-existing fields + if (fields == null) { + delete this.options.fields[field]; + return; + } + for (var validatorName in this.options.fields[field].validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + delete this.options.fields[field].validators[validatorName]; + } + } + + var that = this, + type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent, + total = fields.length, + updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type); + + for (var i = 0; i < total; i++) { + var $field = $(fields[i]), + $parent = $field.parents('.form-group'), + // Allow user to indicate where the error messages are shown + $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field); + + // Set the attribute to indicate the fields which are defined by selector + if (!$field.attr('data-bv-field')) { + $field.attr('data-bv-field', field); + } + + // Whenever the user change the field value, mark it as not validated yet + $field.on(event + '.update.bv', function() { + // Reset the flag + that._submitIfValid = false; + updateAll ? that.updateStatus(field, that.STATUS_NOT_VALIDATED, null) + : that.updateElementStatus($(this), that.STATUS_NOT_VALIDATED, null); + }); + + // Create help block elements for showing the error messages + $field.data('bv.messages', $message); + for (validatorName in this.options.fields[field].validators) { + $field.data('bv.result.' + validatorName, this.STATUS_NOT_VALIDATED); + + if (!updateAll || i == total - 1) { + $('') + .css('display', 'none') + .attr('data-bv-validator', validatorName) + .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message) + .addClass('help-block') + .appendTo($message); + } + } + + // Prepare the feedback icons + // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation) + if (this.options.feedbackIcons + && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid + && (!updateAll || i == total - 1)) + { + $parent.addClass('has-feedback'); + var $icon = $('').css('display', 'none').addClass('form-control-feedback').attr('data-bv-field', field).insertAfter($field); + // The feedback icon does not render correctly if there is no label + // https://github.com/twbs/bootstrap/issues/12873 + if ($parent.find('label').length == 0) { + $icon.css('top', 0); + } + } + } + + if (this.options.fields[field]['enabled'] == null) { + this.options.fields[field]['enabled'] = true; + } + }, + + /** + * Get the element to place the error messages + * + * @param {jQuery} $field The field element + * @returns {jQuery} + */ + _getMessageContainer: function($field) { + var $parent = $field.parent(); + if ($parent.hasClass('form-group')) { + return $parent; + } + + var cssClasses = $parent.attr('class'); + if (!cssClasses) { + return this._getMessageContainer($parent); + } + + cssClasses = cssClasses.split(' '); + var n = cssClasses.length; + for (var i = 0; i < n; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i]) || /^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + return $parent; + } + } + + return this._getMessageContainer($parent); + }, + + /** + * Called when all validations are completed + */ + _submit: function() { + if (!this.isValid()) { + if ('submitted' == this.options.live) { + this.setLiveMode('enabled'); + } + + // Focus to the first invalid field + if (this.$invalidField) { + this.$invalidField.focus(); + } + return; + } + + // Call the custom submission if enabled + if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + // If you want to submit the form inside your submit handler, please call defaultSubmit() method + this.options.submitHandler.call(this, this, this.$form, this.$submitButton); + } else { + this.disableSubmitButtons(true).defaultSubmit(); + } + }, + + // --- Public methods --- + + /** + * Retrieve the field elements by given name + * + * @param {String} field The field name + * @returns {null|jQuery[]} + */ + getFieldElements: function(field) { + var fields = this.options.fields[field].selector ? $(this.options.fields[field].selector) : this.$form.find('[name="' + field + '"]'); + return (fields.length == 0) ? null : fields; + }, + + /** + * Set live validating mode + * + * @param {String} mode Live validating mode. Can be 'enabled', 'disabled', 'submitted' + * @returns {BootstrapValidator} + */ + setLiveMode: function(mode) { + this.options.live = mode; + if ('submitted' == mode) { + return this; + } + + var that = this; + for (var field in this.options.fields) { + (function(f) { + var fields = that.getFieldElements(f); + if (fields) { + var type = fields.attr('type'), + total = fields.length, + updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type), + trigger = that.options.fields[field].trigger + || that.options.trigger + || (('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent), + events = $.map(trigger.split(' '), function(item) { + return item + '.live.bv'; + }).join(' '); + + for (var i = 0; i < total; i++) { + ('enabled' == mode) + ? $(fields[i]).on(events, function() { + updateAll ? that.validateField(f) : that.validateFieldElement($(this), false); + }) + : $(fields[i]).off(events); + } + } + })(field); + } + + return this; + }, + + /** + * Disable/enable submit buttons + * + * @param {Boolean} disabled Can be true or false + * @returns {BootstrapValidator} + */ + disableSubmitButtons: function(disabled) { + if (!disabled) { + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + } else if (this.options.live != 'disabled') { + // Don't disable if the live validating mode is disabled + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + } + + return this; + }, + + /** + * Validate the form + * + * @return {BootstrapValidator} + */ + validate: function() { + if (!this.options.fields) { + return this; + } + this.disableSubmitButtons(true); + + for (var field in this.options.fields) { + this.validateField(field); + } + + // Check if whether the submit button is clicked + if (this.$submitButton) { + this._submit(); + } + + return this; + }, + + /** + * Validate given field + * + * @param {String} field The field name + * @returns {BootstrapValidator} + */ + validateField: function(field) { + var fields = this.getFieldElements(field), + type = fields.attr('type'), + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (var i = 0; i < n; i++) { + this.validateFieldElement($(fields[i]), (n == 1)); + } + + return this; + }, + + /** + * Validate field element + * + * @param {jQuery} $field The field element + * @param {Boolean} updateAll If true, update status of all elements which have the same name + * @returns {BootstrapValidator} + */ + validateFieldElement: function($field, updateAll) { + var that = this, + field = $field.attr('data-bv-field'), + validators = this.options.fields[field].validators, + validatorName, + validateResult; + + // We don't need to validate disabled, hidden field + if ($field.is(':disabled') || $field.is(':hidden') || !$field.is(':visible')) { + return this; + } + + for (validatorName in validators) { + if ($field.data('bv.dfs.' + validatorName)) { + $field.data('bv.dfs.' + validatorName).reject(); + } + + // Don't validate field if it is already done + var result = $field.data('bv.result.' + validatorName); + if (result == this.STATUS_VALID || result == this.STATUS_INVALID) { + continue; + } + + $field.data('bv.result.' + validatorName, this.STATUS_VALIDATING); + validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]); + + if ('object' == typeof validateResult) { + updateAll ? this.updateStatus(field, this.STATUS_VALIDATING, validatorName) + : this.updateElementStatus($field, this.STATUS_VALIDATING, validatorName); + $field.data('bv.dfs.' + validatorName, validateResult); + + validateResult.done(function($f, v, isValid) { + // v is validator name + $f.removeData('bv.dfs.' + v); + updateAll ? that.updateStatus($f.attr('data-bv-field'), isValid ? that.STATUS_VALID : that.STATUS_INVALID, v) + : that.updateElementStatus($f, isValid ? that.STATUS_VALID : that.STATUS_INVALID, v); + + if (isValid && that._submitIfValid == true) { + // If a remote validator returns true and the form is ready to submit, then do it + that._submit(); + } + }); + } else if ('boolean' == typeof validateResult) { + updateAll ? this.updateStatus(field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName) + : this.updateElementStatus($field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName); + } + } + + return this; + }, + + /** + * Update all validating results of elements which have the same field name + * + * @param {String} field The field name + * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateStatus: function(field, status, validatorName) { + var fields = this.getFieldElements(field), + type = fields.attr('type'), + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (var i = 0; i < n; i++) { + this.updateElementStatus($(fields[i]), status, validatorName); + } + + return this; + }, + + /** + * Update validating result of given element + * + * @param {jQuery} $field The field element + * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateElementStatus: function($field, status, validatorName) { + var that = this, + field = $field.attr('data-bv-field'), + $parent = $field.parents('.form-group'), + $message = $field.data('bv.messages'), + $rowErrors = $parent.find('.help-block[data-bv-validator]'), + $errors = $message.find('.help-block[data-bv-validator]'), + $icon = $parent.find('.form-control-feedback[data-bv-field="' + field + '"]'); + + // Update status + if (validatorName) { + $field.data('bv.result.' + validatorName, status); + } else { + for (var v in this.options.fields[field].validators) { + $field.data('bv.result.' + v, status); + } + } + + // Show/hide error elements and feedback icons + switch (status) { + case this.STATUS_VALIDATING: + this.disableSubmitButtons(true); + $parent.removeClass('has-success').removeClass('has-error'); + // TODO: Show validating message + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(); + } + break; + + case this.STATUS_INVALID: + this.disableSubmitButtons(true); + $parent.removeClass('has-success').addClass('has-error'); + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').show() : $errors.show(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(); + } + break; + + case this.STATUS_VALID: + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + + // If the field is valid (passes all validators) + var validField = ($errors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || ($field.data('bv.result.' + v) != that.STATUS_VALID); + }).length == 0); + this.disableSubmitButtons(validField ? false : true); + if ($icon) { + $icon + .removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid) + .addClass(validField ? this.options.feedbackIcons.valid : this.options.feedbackIcons.invalid) + .show(); + } + + // Check if all fields in the same row are valid + var validRow = ($rowErrors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || ($field.data('bv.result.' + v) != that.STATUS_VALID); + }).length == 0); + $parent.removeClass('has-error has-success').addClass(validRow ? 'has-success' : 'has-error'); + break; + + case this.STATUS_NOT_VALIDATED: + default: + this.disableSubmitButtons(false); + $parent.removeClass('has-success').removeClass('has-error'); + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide(); + } + break; + } + + return this; + }, + + /** + * Check the form validity + * + * @returns {Boolean} + */ + isValid: function() { + var fields, field, $field, + type, status, validatorName, + n, i; + for (field in this.options.fields) { + if (this.options.fields[field] == null || !this.options.fields[field]['enabled']) { + continue; + } + + fields = this.getFieldElements(field); + type = fields.attr('type'); + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (i = 0; i < n; i++) { + $field = $(fields[i]); + if ($field.is(':disabled') || $field.is(':hidden') || !$field.is(':visible')) { + continue; + } + + for (validatorName in this.options.fields[field].validators) { + status = $field.data('bv.result.' + validatorName); + if (status == this.STATUS_NOT_VALIDATED || status == this.STATUS_VALIDATING) { + return false; + } + + if (status == this.STATUS_INVALID) { + this.$invalidField = $field; + return false; + } + } + } + } + + return true; + }, + + /** + * Submit the form using default submission. + * It also does not perform any validations when submitting the form + * + * It might be used when you want to submit the form right inside the submitHandler() + */ + defaultSubmit: function() { + this.$form.off('submit.bv').submit(); + }, + + // Useful APIs which aren't used internally + + /** + * Reset the form + * + * @param {Boolean} resetFormData Reset current form data + * @return {BootstrapValidator} + */ + resetForm: function(resetFormData) { + var field, fields, total, type, validator; + for (field in this.options.fields) { + fields = this.getFieldElements(field); + total = fields.length; + + for (var i = 0; i < total; i++) { + for (validator in this.options.fields[field].validators) { + $(fields[i]).removeData('bv.dfs.' + validator); + } + } + + // Mark field as not validated yet + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + if (resetFormData) { + type = fields.attr('type'); + ('radio' == type || 'checkbox' == type) ? fields.removeAttr('checked').removeAttr('selected') : fields.val(''); + } + } + + this.$invalidField = null; + this.$submitButton = null; + + // Enable submit buttons + this.disableSubmitButtons(false); + + return this; + }, + + /** + * Enable/Disable all validators to given field + * + * @param {String} field The field name + * @param {Boolean} enabled Enable/Disable field validators + * @return {BootstrapValidator} + */ + enableFieldValidators: function(field, enabled) { + this.options.fields[field]['enabled'] = enabled; + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + return this; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(options) { + return this.each(function() { + var $this = $(this), data = $this.data('bootstrapValidator'); + if (!data) { + $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options))); + } + if ('string' == typeof options) { + data[options](); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.base64 = { + /** + * Return true if the input value is a base 64 encoded string. + * + * @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; + } + + return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + if ('range' == $field.attr('type')) { + return { + min: $field.attr('min'), + max: $field.attr('max') + }; + } + + return false; + }, + + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = parseFloat(value); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {Boolean|Deferred} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (options.callback && 'function' == typeof options.callback) { + var dfd = new $.Deferred(); + dfd.resolve($field, 'callback', options.callback.call(this, value, validator)); + return dfd; + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.choice = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max' + }, + + /** + * Check if the number of checked boxes are less or more than a given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var numChoices = validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length; + if ((options.min && numChoices < options.min) || (options.max && numChoices > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + value = value.replace(/\D/g, ''); + + // Validate the check sum + // The Luhn Algorithm + // http://en.wikipedia.org/wiki/Luhn + var check = 0, digit = 0, even = false, length = value.length; + + for (var n = length - 1; n >= 0; n--) { + digit = parseInt(value.charAt(n), 10); + + if (even) { + if ((digit *= 2) > 9) { + digit -= 9; + } + } + + check += digit; + even = !even; + } + + if ((check % 10) != 0) { + return false; + } + + // Validate the card number based on prefix (IIN ranges) and length + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + + var type, i; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (value.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(value.length) != -1) // and length + { + return true; + } + } + } + + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.cvv = { + html5Attributes: { + message: 'message', + ccfield: 'creditCardField' + }, + + /** + * Return true if the input value is a valid CVV number. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - creditCardField: The credit card number field. It can be null + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^[0-9]{3,4}$/.test(value)) { + return false; + } + + if (!options.creditCardField) { + return true; + } + + // Get the credit card number + var creditCard = validator.getFieldElements(options.creditCardField).val(); + if (creditCard == '') { + return true; + } + + // Supported credit card types + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + var type, i, creditCardType = null; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (creditCard.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(creditCard.length) != -1) // and length + { + creditCardType = type; + break; + } + } + } + + return (creditCardType == null) + ? false + : (('AMERICAN_EXPRESS' == creditCardType) ? (value.length == 4) : (value.length == 3)); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.date = { + html5Attributes: { + message: 'message', + format: 'format' + }, + + /** + * Return true if the input value is valid date + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - format: The date format. Default is MM/DD/YYYY + * Support the following formats: + * YYYY/DD/MM + * YYYY/DD/MM h:m A + * YYYY/MM/DD + * YYYY/MM/DD h:m A + * + * YYYY-DD-MM + * YYYY-DD-MM h:m A + * YYYY-MM-DD + * YYYY-MM-DD h:m A + * + * MM/DD/YYYY + * MM/DD/YYYY h:m A + * DD/MM/YYYY + * DD/MM/YYYY h:m A + * + * MM-DD-YYYY + * MM-DD-YYYY h:m A + * DD-MM-YYYY + * DD-MM-YYYY h:m A + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + // Determine the separator + options.format = options.format || 'MM/DD/YYYY'; + var separator = (options.format.indexOf('/') != -1) + ? '/' + : ((options.format.indexOf('-') != -1) ? '-' : null); + if (separator == null) { + return false; + } + + var month, day, year, minutes = null, hours = null, matches; + switch (true) { + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/DD/MM'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-DD-MM'): + year = matches[1]; day = matches[2]; month = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'DD/MM/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'DD-MM-YYYY'): + day = matches[1]; month = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/MM/DD'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-MM-DD'): + year = matches[1]; month = matches[2]; day = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'MM/DD/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'MM-DD-YYYY'): + month = matches[1]; day = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/DD/MM h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-DD-MM h:m A'): + year = matches[1]; day = matches[2]; month = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD/MM/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD-MM-YYYY h:m A'): + day = matches[1]; month = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/MM/DD h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-MM-DD h:m A'): + year = matches[1]; month = matches[2]; day = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM/DD/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM-DD-YYYY h:m A'): + month = matches[1]; day = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + default: + return false; + } + + // Validate hours and minutes + if (hours && minutes) { + hours = parseInt(hours, 10); + minutes = parseInt(minutes, 10); + if (hours < 1 || hours > 12 || minutes < 0 || minutes > 59) { + return false; + } + } + + // Validate day, month, and year + day = parseInt(day, 10); + month = parseInt(month, 10); + year = parseInt(year, 10); + + if (year < 1000 || year > 9999 || month == 0 || month > 12) { + return false; + } + + var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + // Update the number of days in Feb of leap year + if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) { + numDays[1] = 29; + } + + // Check the day + return (day > 0 && day <= numDays[month - 1]); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.different = { + html5Attributes: { + message: 'message', + field: 'field' + }, + + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value != compareWith.val()) { + validator.updateStatus(options.field, validator.STATUS_VALID, 'different'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^\d+$/.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + enableByHtml5: function($field) { + return ('email' == $field.attr('type')); + }, + + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + html5Attributes: { + message: 'message', + value: 'value', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + var min = $field.attr('min'); + if (min) { + return { + value: min + }; + } + + return false; + }, + + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hex = { + /** + * Return true if and only if the input value is a valid hexadecimal number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^[0-9a-fA-F]+$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + enableByHtml5: function($field) { + return ('color' == $field.attr('type')); + }, + + /** + * Return true if the input value is a valid hex color + * + * @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; + } + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.iban = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Validate an International Bank Account Number (IBAN) + * To test it, take the sample IBAN from + * http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html + * + * @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 + * - country: The ISO 3166-1 country code + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // See + // http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf + // http://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country + var ibanRegex = { + '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 + }; + value = value.replace(/[^a-zA-Z0-9]/g, '').toUpperCase(); + var country = options.country || value.substr(0, 2); + if (!ibanRegex[country]) { + return false; + } + if (!(new RegExp('^' + ibanRegex[country] + '$')).test(value)) { + return false; + } + + value = value.substr(4) + value.substr(0, 4); + value = value.split('').map(function(n) { + var code = n.charCodeAt(0); + return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) + // Replace A, B, C, ..., Z with 10, 11, ..., 35 + ? (code - 'A'.charCodeAt(0) + 10) + : n; + }).join(''); + + var temp = parseInt(value.substr(0, 1), 10), + length = value.length; + for (var i = 1; i < length; ++i) { + temp = (temp * 10 + parseInt(value.substr(i, 1), 10)) % 97; + } + return (temp == 1); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + html5Attributes: { + message: 'message', + field: 'field' + }, + + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value == compareWith.val()) { + validator.updateStatus(options.field, validator.STATUS_VALID, 'identical'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.integer = { + enableByHtml5: function($field) { + return ('number' == $field.attr('type')); + }, + + /** + * Return true if the input value is an integer + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + return /^(?:-?(?:0|[1-9][0-9]*))$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.ip = { + html5Attributes: { + message: 'message', + ipv4: 'ipv4', + ipv6: 'ipv6' + }, + + /** + * Return true if the input value is a IP address. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - ipv4: Enable IPv4 validator, default to true + * - ipv6: Enable IPv6 validator, default to true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + options = $.extend({}, { ipv4: true, ipv6: true }, options); + + if (options.ipv4) { + return /^(?:(?: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); + } else if (options.ipv6) { + return /^\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(str); + } + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.isbn = { + /** + * Return true if the input value is a valid ISBN 10 or ISBN 13 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; + } + + // Replace all special characters except digits and X + value = value.replace(/[^\dX]/gi, ''); + var chars = value.split(''), + sum = 0, + checksum; + + // See http://en.wikipedia.org/wiki/International_Standard_Book_Number + switch (chars.length) { + // ISBN 10 + case 10: + sum = 0; + for (var i = 0; i < 9; i++) { + sum += ((10 - i) * parseInt(chars[i])); + } + checksum = 11 - (sum % 11); + if (checksum == 11) { + checksum = 0; + } else if (checksum == 10) { + checksum = 'X'; + } + return (checksum == chars[9]); + + // ISBN 13 + case 13: + sum = 0; + for (var i = 0; i < 12; i++) { + sum += ((i % 2 == 0) ? parseInt(chars[i]) : (parseInt(chars[i]) * 3)); + } + checksum = 10 - (sum % 10); + if (checksum == 10) { + checksum = '0'; + } + return (checksum == chars[12]); + + default: + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + html5Attributes: { + message: 'message', + value: 'value', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + var max = $field.attr('max'); + if (max) { + return { + value: max + }; + } + + return false; + }, + + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === false) ? (value <= options.value) : (value < options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.mac = { + /** + * Return true if the input value is a MAC address. + * + * @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; + } + + return /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + enableByHtml5: function($field) { + var required = $field.attr('required') + ''; + return ('required' == required || 'true' == required); + }, + + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + if ('radio' == type || 'checkbox' == type) { + return validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length > 0; + } + + return $.trim($field.val()) != ''; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.numeric = { + /** + * Validate decimal number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return !isNaN(parseFloat(value)) && isFinite(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.phone = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Return true if the input value contains a valid US phone number only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166 country code + * Currently it only supports United State (US) country + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var country = (options.country || 'US').toUpperCase(); + switch (country) { + case 'US': + default: + // Make sure US phone numbers have 10 digits + value = value.replace(/\(|\)|\s+/g, ''); + return (/^(?:1\-?)?(\d{3})[\-\.]?(\d{3})[\-\.]?(\d{4})$/).test(value) && (value.length == 10); + } + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + html5Attributes: { + message: 'message', + regexp: 'regexp' + }, + + enableByHtml5: function($field) { + var pattern = $field.attr('pattern'); + if (pattern) { + return { + regexp: pattern + }; + } + + return false; + }, + + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var regexp = ('string' == typeof options.regexp) ? new RegExp(options.regexp) : options.regexp; + return regexp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.remote = { + html5Attributes: { + message: 'message', + url: 'url' + }, + + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - message: The invalid message + * @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; + if (data == null) { + data = {}; + } + // Support dynamic data + if ('function' == typeof data) { + data = data.call(this, validator); + } + data[name] = value; + + var dfd = new $.Deferred(); + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }); + xhr.then(function(response) { + dfd.resolve($field, 'remote', response.valid === true || response.valid === 'true'); + }); + + dfd.fail(function() { + xhr.abort(); + }); + + return dfd; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.step = { + html5Attributes: { + message: 'message', + base: 'baseValue', + step: 'step' + }, + + /** + * Return true if the input value is valid step one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - baseValue: The base value + * - step: The step + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options = $.extend({}, { baseValue: 0, step: 1 }, options); + value = parseFloat(value); + if (isNaN(value) || !isFinite(value)) { + return false; + } + + var round = function(x, precision) { + var m = Math.pow(10, precision); + x = x * m; + var sign = (x > 0) | -(x < 0), + isHalf = (x % 1 === 0.5 * sign); + if (isHalf) { + return (Math.floor(x) + (sign > 0)) / m; + } else { + return Math.round(x) / m; + } + }, + floatMod = function(x, y) { + if (y == 0.0) { + return 1.0; + } + var dotX = (x + '').split('.'), + dotY = (y + '').split('.'), + precision = ((dotX.length == 1) ? 0 : dotX[1].length) + ((dotY.length == 1) ? 0 : dotY[1].length); + return round(x - y * Math.floor(x / y), precision); + }; + + var mod = floatMod(value - options.baseValue, options.step); + return (mod == 0.0 || mod == options.step); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringCase = { + html5Attributes: { + message: 'message', + 'case': 'case' + }, + + /** + * Check if a string is a lower or upper case one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - case: Can be 'lower' (default) or 'upper' + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var stringCase = (options['case'] || 'lower').toLowerCase(); + switch (stringCase) { + case 'upper': + return value === value.toUpperCase(); + case 'lower': + default: + return value === value.toLowerCase(); + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max' + }, + + enableByHtml5: function($field) { + var maxLength = $field.attr('maxlength'); + if (maxLength) { + return { + max: parseInt(maxLength, 10) + }; + } + + return false; + }, + + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var length = $.trim(value).length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + enableByHtml5: function($field) { + return ('url' == $field.attr('type')); + }, + + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uuid = { + html5Attributes: { + message: 'message', + version: 'version' + }, + + /** + * Return true if and only if the input value is a valid UUID string + * + * @see http://en.wikipedia.org/wiki/Universally_unique_identifier + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - version: Can be 3, 4, 5, null + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // See the format at http://en.wikipedia.org/wiki/Universally_unique_identifier#Variants_and_versions + var patterns = { + '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, + '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i + }, + version = options.version ? (options.version + '') : 'all'; + return (null == patterns[version]) ? true : patterns[version].test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.zipCode = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Return true if and only if the input value is a valid country zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166 country code + * + * Currently it supports the following countries: + * - US (United State) + * - DK (Denmark) + * - SE (Sweden) + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '' || !options.country) { + return true; + } + + options.country = options.country || 'US'; + switch (options.country.toUpperCase()) { + case 'DK': + return /^(DK(-|\s)?)?\d{4}$/i.test(value); + case 'SE': + return /^(S-)?\d{3}\s?\d{2}$/i.test(value); + case 'US': + default: + return /^\d{5}([\-]\d{4})?$/.test(value); + } + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.1/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.4.1/js/bootstrapValidator.min.js new file mode 100644 index 000000000..953a07586 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.1/js/bootstrapValidator.min.js @@ -0,0 +1,12 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.1 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),this.$invalidField=null,this.$submitButton=null,this.STATUS_NOT_VALIDATED="NOT_VALIDATED",this.STATUS_VALIDATING="VALIDATING",this.STATUS_INVALID="INVALID",this.STATUS_VALID="VALID";var e=document.createElement("div");this._changeEvent="oninput"in e?"input":"keydown",this._submitIfValid=null,this._init()};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",feedbackIcons:{valid:null,invalid:null,validating:null},submitButtons:'button[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){var b,c,d,e,f,g,h,i=this,j={trigger:this.$form.attr("data-bv-trigger"),message:this.$form.attr("data-bv-message"),submitButtons:this.$form.attr("data-bv-submitbuttons"),live:this.$form.attr("data-bv-live"),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")}};this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit.bv",function(a){a.preventDefault(),i.validate()}).on("click",this.options.submitButtons,function(){i.$submitButton=a(this),i._submitIfValid=!0}).find("[name], [data-bv-field]").each(function(){var i=a(this);if("hidden"!=i.attr("type")){var k=i.attr("name")||i.attr("data-bv-field");i.attr("data-bv-field",k),j.fields[k]=a.extend({},{trigger:i.attr("data-bv-trigger"),message:i.attr("data-bv-message"),container:i.attr("data-bv-container"),selector:i.attr("data-bv-selector"),validators:{}},j.fields[k]);for(c in a.fn.bootstrapValidator.validators)if(b=a.fn.bootstrapValidator.validators[c],d=i.attr("data-bv-"+c.toLowerCase())+"",h="function"==typeof b.enableByHtml5?b.enableByHtml5(a(this)):null,h&&"false"!=d||h!==!0&&(""==d||"true"==d)){b.html5Attributes=b.html5Attributes||{message:"message"},j.fields[k].validators[c]=a.extend({},1==h?{}:h,j.fields[k].validators[c]);for(g in b.html5Attributes)e=b.html5Attributes[g],f=i.attr("data-bv-"+c.toLowerCase()+"-"+g),f&&("true"==f?f=!0:"false"==f&&(f=!1),j.fields[k].validators[c][e]=f)}}}),this.options=a.extend(!0,this.options,j);for(var k in this.options.fields)this._initField(k);this.setLiveMode(this.options.live)},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){var c=this.getFieldElements(b);if(null==c)return void delete this.options.fields[b];for(var d in this.options.fields[b].validators)a.fn.bootstrapValidator.validators[d]||delete this.options.fields[b].validators[d];for(var e=this,f=c.attr("type"),g="radio"==f||"checkbox"==f||"file"==f||"SELECT"==c[0].tagName?"change":e._changeEvent,h=c.length,i=1==h||"radio"==f||"checkbox"==f,j=0;h>j;j++){var k=a(c[j]),l=k.parents(".form-group"),m=this.options.fields[b].container?l.find(this.options.fields[b].container):this._getMessageContainer(k);k.attr("data-bv-field")||k.attr("data-bv-field",b),k.on(g+".update.bv",function(){e._submitIfValid=!1,i?e.updateStatus(b,e.STATUS_NOT_VALIDATED,null):e.updateElementStatus(a(this),e.STATUS_NOT_VALIDATED,null)}),k.data("bv.messages",m);for(d in this.options.fields[b].validators)k.data("bv.result."+d,this.STATUS_NOT_VALIDATED),i&&j!=h-1||a("").css("display","none").attr("data-bv-validator",d).html(this.options.fields[b].validators[d].message||this.options.fields[b].message||this.options.message).addClass("help-block").appendTo(m);if(this.options.feedbackIcons&&this.options.feedbackIcons.validating&&this.options.feedbackIcons.invalid&&this.options.feedbackIcons.valid&&(!i||j==h-1)){l.addClass("has-feedback");var n=a("").css("display","none").addClass("form-control-feedback").attr("data-bv-field",b).insertAfter(k);0==l.find("label").length&&n.css("top",0)}}null==this.options.fields[b].enabled&&(this.options.fields[b].enabled=!0)}},_getMessageContainer:function(a){var b=a.parent();if(b.hasClass("form-group"))return b;var c=b.attr("class");if(!c)return this._getMessageContainer(b);c=c.split(" ");for(var d=c.length,e=0;d>e;e++)if(/^col-(xs|sm|md|lg)-\d+$/.test(c[e])||/^col-(xs|sm|md|lg)-offset-\d+$/.test(c[e]))return b;return this._getMessageContainer(b)},_submit:function(){return this.isValid()?void(this.options.submitHandler&&"function"==typeof this.options.submitHandler?this.options.submitHandler.call(this,this,this.$form,this.$submitButton):this.disableSubmitButtons(!0).defaultSubmit()):("submitted"==this.options.live&&this.setLiveMode("enabled"),void(this.$invalidField&&this.$invalidField.focus()))},getFieldElements:function(b){var c=this.options.fields[b].selector?a(this.options.fields[b].selector):this.$form.find('[name="'+b+'"]');return 0==c.length?null:c},setLiveMode:function(b){if(this.options.live=b,"submitted"==b)return this;var c=this;for(var d in this.options.fields)!function(e){var f=c.getFieldElements(e);if(f)for(var g=f.attr("type"),h=f.length,i=1==h||"radio"==g||"checkbox"==g,j=c.options.fields[d].trigger||c.options.trigger||("radio"==g||"checkbox"==g||"file"==g||"SELECT"==f[0].tagName?"change":c._changeEvent),k=a.map(j.split(" "),function(a){return a+".live.bv"}).join(" "),l=0;h>l;l++)"enabled"==b?a(f[l]).on(k,function(){i?c.validateField(e):c.validateFieldElement(a(this),!1)}):a(f[l]).off(k)}(d);return this},disableSubmitButtons:function(a){return a?"disabled"!=this.options.live&&this.$form.find(this.options.submitButtons).attr("disabled","disabled"):this.$form.find(this.options.submitButtons).removeAttr("disabled"),this},validate:function(){if(!this.options.fields)return this;this.disableSubmitButtons(!0);for(var a in this.options.fields)this.validateField(a);return this.$submitButton&&this._submit(),this},validateField:function(b){for(var c=this.getFieldElements(b),d=c.attr("type"),e="radio"==d||"checkbox"==d?1:c.length,f=0;e>f;f++)this.validateFieldElement(a(c[f]),1==e);return this},validateFieldElement:function(b,c){var d,e,f=this,g=b.attr("data-bv-field"),h=this.options.fields[g].validators;if(b.is(":disabled")||b.is(":hidden")||!b.is(":visible"))return this;for(d in h){b.data("bv.dfs."+d)&&b.data("bv.dfs."+d).reject();var i=b.data("bv.result."+d);i!=this.STATUS_VALID&&i!=this.STATUS_INVALID&&(b.data("bv.result."+d,this.STATUS_VALIDATING),e=a.fn.bootstrapValidator.validators[d].validate(this,b,h[d]),"object"==typeof e?(c?this.updateStatus(g,this.STATUS_VALIDATING,d):this.updateElementStatus(b,this.STATUS_VALIDATING,d),b.data("bv.dfs."+d,e),e.done(function(a,b,d){a.removeData("bv.dfs."+b),c?f.updateStatus(a.attr("data-bv-field"),d?f.STATUS_VALID:f.STATUS_INVALID,b):f.updateElementStatus(a,d?f.STATUS_VALID:f.STATUS_INVALID,b),d&&1==f._submitIfValid&&f._submit()})):"boolean"==typeof e&&(c?this.updateStatus(g,e?this.STATUS_VALID:this.STATUS_INVALID,d):this.updateElementStatus(b,e?this.STATUS_VALID:this.STATUS_INVALID,d)))}return this},updateStatus:function(b,c,d){for(var e=this.getFieldElements(b),f=e.attr("type"),g="radio"==f||"checkbox"==f?1:e.length,h=0;g>h;h++)this.updateElementStatus(a(e[h]),c,d);return this},updateElementStatus:function(b,c,d){var e=this,f=b.attr("data-bv-field"),g=b.parents(".form-group"),h=b.data("bv.messages"),i=g.find(".help-block[data-bv-validator]"),j=h.find(".help-block[data-bv-validator]"),k=g.find('.form-control-feedback[data-bv-field="'+f+'"]');if(d)b.data("bv.result."+d,c);else for(var l in this.options.fields[f].validators)b.data("bv.result."+l,c);switch(c){case this.STATUS_VALIDATING:this.disableSubmitButtons(!0),g.removeClass("has-success").removeClass("has-error"),d?j.filter('.help-block[data-bv-validator="'+d+'"]').hide():j.hide(),k&&k.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show();break;case this.STATUS_INVALID:this.disableSubmitButtons(!0),g.removeClass("has-success").addClass("has-error"),d?j.filter('[data-bv-validator="'+d+'"]').show():j.show(),k&&k.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show();break;case this.STATUS_VALID:d?j.filter('[data-bv-validator="'+d+'"]').hide():j.hide();var m=0==j.filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||b.data("bv.result."+d)!=e.STATUS_VALID}).length;this.disableSubmitButtons(m?!1:!0),k&&k.removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid).addClass(m?this.options.feedbackIcons.valid:this.options.feedbackIcons.invalid).show();var n=0==i.filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||b.data("bv.result."+d)!=e.STATUS_VALID}).length;g.removeClass("has-error has-success").addClass(n?"has-success":"has-error");break;case this.STATUS_NOT_VALIDATED:default:this.disableSubmitButtons(!1),g.removeClass("has-success").removeClass("has-error"),d?j.filter('.help-block[data-bv-validator="'+d+'"]').hide():j.hide(),k&&k.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide()}return this},isValid:function(){var b,c,d,e,f,g,h,i;for(c in this.options.fields)if(null!=this.options.fields[c]&&this.options.fields[c].enabled)for(b=this.getFieldElements(c),e=b.attr("type"),h="radio"==e||"checkbox"==e?1:b.length,i=0;h>i;i++)if(d=a(b[i]),!d.is(":disabled")&&!d.is(":hidden")&&d.is(":visible"))for(g in this.options.fields[c].validators){if(f=d.data("bv.result."+g),f==this.STATUS_NOT_VALIDATED||f==this.STATUS_VALIDATING)return!1;if(f==this.STATUS_INVALID)return this.$invalidField=d,!1}return!0},defaultSubmit:function(){this.$form.off("submit.bv").submit()},resetForm:function(b){var c,d,e,f,g;for(c in this.options.fields){d=this.getFieldElements(c),e=d.length;for(var h=0;e>h;h++)for(g in this.options.fields[c].validators)a(d[h]).removeData("bv.dfs."+g);this.updateStatus(c,this.STATUS_NOT_VALIDATED,null),b&&(f=d.attr("type"),"radio"==f||"checkbox"==f?d.removeAttr("checked").removeAttr("selected"):d.val(""))}return this.$invalidField=null,this.$submitButton=null,this.disableSubmitButtons(!1),this},enableFieldValidators:function(a,b){return this.options.fields[a].enabled=b,this.updateStatus(a,this.STATUS_NOT_VALIDATED,null),this}},a.fn.bootstrapValidator=function(c){return this.each(function(){var d=a(this),e=d.data("bootstrapValidator");e||d.data("bootstrapValidator",e=new b(this,c)),"string"==typeof c&&e[c]()})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.base64={validate:function(a,b){var c=b.val();return""==c?!0:/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={html5Attributes:{message:"message",min:"min",max:"max",inclusive:"inclusive"},enableByHtml5:function(a){return"range"==a.attr("type")?{min:a.attr("min"),max:a.attr("max")}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(b,c,d){var e=c.val();if(d.callback&&"function"==typeof d.callback){var f=new a.Deferred;return f.resolve(c,"callback",d.callback.call(this,e,b)),f}return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.choice={html5Attributes:{message:"message",min:"min",max:"max"},validate:function(a,b,c){var d=a.getFieldElements(b.attr("data-bv-field")).filter(":checked").length;return c.min&&dc.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(a,b){var c=b.val();if(""==c)return!0;if(/[^0-9-\s]+/.test(c))return!1;c=c.replace(/\D/g,"");for(var d=0,e=0,f=!1,g=c.length,h=g-1;h>=0;h--)e=parseInt(c.charAt(h),10),f&&(e*=2)>9&&(e-=9),d+=e,f=!f;if(d%10!=0)return!1;var i,j,k={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["3528","3529","353","354","355","356","357","358"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}};for(i in k)for(j in k[i].prefix)if(c.substr(0,k[i].prefix[j].length)==k[i].prefix[j]&&-1!=k[i].length.indexOf(c.length))return!0;return!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.cvv={html5Attributes:{message:"message",ccfield:"creditCardField"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;if(!/^[0-9]{3,4}$/.test(d))return!1;if(!c.creditCardField)return!0;var e=a.getFieldElements(c.creditCardField).val();if(""==e)return!0;var f,g,h={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["3528","3529","353","354","355","356","357","358"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}},i=null;for(f in h)for(g in h[f].prefix)if(e.substr(0,h[f].prefix[g].length)==h[f].prefix[g]&&-1!=h[f].length.indexOf(e.length)){i=f;break}return null==i?!1:"AMERICAN_EXPRESS"==i?4==d.length:3==d.length}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.date={html5Attributes:{message:"message",format:"format"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;c.format=c.format||"MM/DD/YYYY";var e=-1!=c.format.indexOf("/")?"/":-1!=c.format.indexOf("-")?"-":null;if(null==e)return!1;var f,g,h,i,j=null,k=null;switch(!0){case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/DD/MM"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-DD-MM"==c.format:h=i[1],g=i[2],f=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"DD/MM/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"DD-MM-YYYY"==c.format:g=i[1],f=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/MM/DD"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-MM-DD"==c.format:h=i[1],f=i[2],g=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"MM/DD/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"MM-DD-YYYY"==c.format:f=i[1],g=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/DD/MM h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-DD-MM h:m A"==c.format:h=i[1],g=i[2],f=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD/MM/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD-MM-YYYY h:m A"==c.format:g=i[1],f=i[2],h=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/MM/DD h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-MM-DD h:m A"==c.format:h=i[1],f=i[2],g=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM/DD/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM-DD-YYYY h:m A"==c.format:f=i[1],g=i[2],h=i[3],k=i[4],j=i[5];break;default:return!1}if(k&&j&&(k=parseInt(k,10),j=parseInt(j,10),1>k||k>12||0>j||j>59))return!1;if(g=parseInt(g,10),f=parseInt(f,10),h=parseInt(h,10),1e3>h||h>9999||0==f||f>12)return!1;var l=[31,28,31,30,31,30,31,31,30,31,30,31];return(h%400==0||h%100!=0&&h%4==0)&&(l[1]=29),g>0&&g<=l[f-1]}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={html5Attributes:{message:"message",field:"field"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d!=e.val()?(a.updateStatus(c.field,a.STATUS_VALID,"different"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){var c=b.val();return""==c?!0:/^\d+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={enableByHtml5:function(a){return"email"==a.attr("type")},validate:function(a,b){var c=b.val();if(""==c)return!0;var d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={html5Attributes:{message:"message",value:"value",inclusive:"inclusive"},enableByHtml5:function(a){var b=a.attr("min");return b?{value:b}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.value:d>=c.value)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hex={validate:function(a,b){var c=b.val();return""==c?!0:/^[0-9a-fA-F]+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={enableByHtml5:function(a){return"color"==a.attr("type")},validate:function(a,b){var c=b.val();return""==c?!0:/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.iban={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e={AD:"AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}",AE:"AE[0-9]{2}[0-9]{3}[0-9]{16}",AL:"AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}",AO:"AO[0-9]{2}[0-9]{21}",AT:"AT[0-9]{2}[0-9]{5}[0-9]{11}",AZ:"AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}",BA:"BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}",BE:"BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}",BF:"BF[0-9]{2}[0-9]{23}",BG:"BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}",BH:"BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}",BI:"BI[0-9]{2}[0-9]{12}",BJ:"BJ[0-9]{2}[A-Z]{1}[0-9]{23}",BR:"BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]",CH:"CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}",CI:"CI[0-9]{2}[A-Z]{1}[0-9]{23}",CM:"CM[0-9]{2}[0-9]{23}",CR:"CR[0-9]{2}[0-9]{3}[0-9]{14}",CV:"CV[0-9]{2}[0-9]{21}",CY:"CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}",CZ:"CZ[0-9]{2}[0-9]{20}",DE:"DE[0-9]{2}[0-9]{8}[0-9]{10}",DK:"DK[0-9]{2}[0-9]{14}",DO:"DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}",DZ:"DZ[0-9]{2}[0-9]{20}",EE:"EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}",ES:"ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}",FI:"FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}",FO:"FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}",FR:"FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}",GB:"GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}",GE:"GE[0-9]{2}[A-Z]{2}[0-9]{16}",GI:"GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}",GL:"GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}",GR:"GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}",GT:"GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}",HR:"HR[0-9]{2}[0-9]{7}[0-9]{10}",HU:"HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}",IE:"IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}",IL:"IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}",IR:"IR[0-9]{2}[0-9]{22}",IS:"IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}",IT:"IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}",JO:"JO[0-9]{2}[A-Z]{4}[0-9]{4}[0]{8}[A-Z0-9]{10}",KW:"KW[0-9]{2}[A-Z]{4}[0-9]{22}",KZ:"KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}",LB:"LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}",LI:"LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}",LT:"LT[0-9]{2}[0-9]{5}[0-9]{11}",LU:"LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}",LV:"LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}",MC:"MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}",MD:"MD[0-9]{2}[A-Z0-9]{20}",ME:"ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",MG:"MG[0-9]{2}[0-9]{23}",MK:"MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}",ML:"ML[0-9]{2}[A-Z]{1}[0-9]{23}",MR:"MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}",MT:"MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}",MU:"MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}",MZ:"MZ[0-9]{2}[0-9]{21}",NL:"NL[0-9]{2}[A-Z]{4}[0-9]{10}",NO:"NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}",PK:"PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}",PL:"PL[0-9]{2}[0-9]{8}[0-9]{16}",PS:"PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}",PT:"PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}",QA:"QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}",RO:"RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}",RS:"RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",SA:"SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}",SE:"SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}",SI:"SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}",SK:"SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}",SM:"SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}",SN:"SN[0-9]{2}[A-Z]{1}[0-9]{23}",TN:"TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",TR:"TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}",VG:"VG[0-9]{2}[A-Z]{4}[0-9]{16}"};d=d.replace(/[^a-zA-Z0-9]/g,"").toUpperCase();var f=c.country||d.substr(0,2);if(!e[f])return!1;if(!new RegExp("^"+e[f]+"$").test(d))return!1;d=d.substr(4)+d.substr(0,4),d=d.split("").map(function(a){var b=a.charCodeAt(0);return b>="A".charCodeAt(0)&&b<="Z".charCodeAt(0)?b-"A".charCodeAt(0)+10:a}).join("");for(var g=parseInt(d.substr(0,1),10),h=d.length,i=1;h>i;++i)g=(10*g+parseInt(d.substr(i,1),10))%97;return 1==g}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={html5Attributes:{message:"message",field:"field"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d==e.val()?(a.updateStatus(c.field,a.STATUS_VALID,"identical"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.integer={enableByHtml5:function(a){return"number"==a.attr("type")},validate:function(a,b){var c=b.val();return""==c?!0:/^(?:-?(?:0|[1-9][0-9]*))$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.ip={html5Attributes:{message:"message",ipv4:"ipv4",ipv6:"ipv6"},validate:function(b,c,d){var e=c.val();return""==e?!0:(d=a.extend({},{ipv4:!0,ipv6:!0},d),d.ipv4?/^(?:(?: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(e):d.ipv6?/^\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(str):!1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.isbn={validate:function(a,b){var c=b.val();if(""==c)return!0;c=c.replace(/[^\dX]/gi,"");var d,e=c.split(""),f=0;switch(e.length){case 10:f=0;for(var g=0;9>g;g++)f+=(10-g)*parseInt(e[g]);return d=11-f%11,11==d?d=0:10==d&&(d="X"),d==e[9];case 13:f=0;for(var g=0;12>g;g++)f+=g%2==0?parseInt(e[g]):3*parseInt(e[g]);return d=10-f%10,10==d&&(d="0"),d==e[12];default:return!1}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={html5Attributes:{message:"message",value:"value",inclusive:"inclusive"},enableByHtml5:function(a){var b=a.attr("max");return b?{value:b}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!1?d<=c.value:d0:""!=a.trim(c.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.numeric={validate:function(a,b){var c=b.val();return""==c?!0:!isNaN(parseFloat(c))&&isFinite(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.phone={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=(c.country||"US").toUpperCase();switch(e){case"US":default:return d=d.replace(/\(|\)|\s+/g,""),/^(?:1\-?)?(\d{3})[\-\.]?(\d{3})[\-\.]?(\d{4})$/.test(d)&&10==d.length}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.regexp={html5Attributes:{message:"message",regexp:"regexp"},enableByHtml5:function(a){var b=a.attr("pattern");return b?{regexp:b}:!1},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e="string"==typeof c.regexp?new RegExp(c.regexp):c.regexp;return e.test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.remote={html5Attributes:{message:"message",url:"url"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=c.attr("data-bv-field"),g=d.data;null==g&&(g={}),"function"==typeof g&&(g=g.call(this,b)),g[f]=e;var h=new a.Deferred,i=a.ajax({type:"POST",url:d.url,dataType:"json",data:g});return i.then(function(a){h.resolve(c,"remote",a.valid===!0||"true"===a.valid)}),h.fail(function(){i.abort()}),h}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.step={html5Attributes:{message:"message",base:"baseValue",step:"step"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;if(d=a.extend({},{baseValue:0,step:1},d),e=parseFloat(e),isNaN(e)||!isFinite(e))return!1;var f=function(a,b){var c=Math.pow(10,b);a*=c;var d=a>0|-(0>a),e=a%1===.5*d;return e?(Math.floor(a)+(d>0))/c:Math.round(a)/c},g=function(a,b){if(0==b)return 1;var c=(a+"").split("."),d=(b+"").split("."),e=(1==c.length?0:c[1].length)+(1==d.length?0:d[1].length);return f(a-b*Math.floor(a/b),e)},h=g(e-d.baseValue,d.step);return 0==h||h==d.step}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringCase={html5Attributes:{message:"message","case":"case"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=(c["case"]||"lower").toLowerCase();switch(e){case"upper":return d===d.toUpperCase();case"lower":default:return d===d.toLowerCase()}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringLength={html5Attributes:{message:"message",min:"min",max:"max"},enableByHtml5:function(a){var b=a.attr("maxlength");return b?{max:parseInt(b,10)}:!1},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=a.trim(e).length;return d.min&&fd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={enableByHtml5:function(a){return"url"==a.attr("type")},validate:function(a,b){var c=b.val();if(""==c)return!0;var d=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uuid={html5Attributes:{message:"message",version:"version"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i},f=c.version?c.version+"":"all";return null==e[f]?!0:e[f].test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.zipCode={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d||!c.country)return!0;switch(c.country=c.country||"US",c.country.toUpperCase()){case"DK":return/^(DK(-|\s)?)?\d{4}$/i.test(d);case"SE":return/^(S-)?\d{3}\s?\d{2}$/i.test(d);case"US":default:return/^\d{5}([\-]\d{4})?$/.test(d)}}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.2/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.4.2/css/bootstrapValidator.css new file mode 100644 index 000000000..20b84ba8d --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.2/css/bootstrapValidator.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form .help-block { + margin-bottom: 0; +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.2/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.4.2/css/bootstrapValidator.min.css new file mode 100644 index 000000000..b006898c9 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.2/css/bootstrapValidator.min.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.2 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.2/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.4.2/js/bootstrapValidator.js new file mode 100644 index 000000000..64892cda4 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.2/js/bootstrapValidator.js @@ -0,0 +1,2382 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.2 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + this.$invalidField = null; // First invalid field + this.$submitButton = null; // The submit button which is clicked to submit form + + // Validating status + this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED'; + this.STATUS_VALIDATING = 'VALIDATING'; + this.STATUS_INVALID = 'INVALID'; + this.STATUS_VALID = 'VALID'; + + // Determine the event that is fired when user change the field value + // Most modern browsers supports input event except IE 7, 8. + // IE 9 supports input event but the event is still not fired if I press the backspace key. + // In that case I will use the keydown event + var el = document.createElement('div'); + this._changeEvent = ('oninput' in el) ? 'input' : 'keydown'; + + // The flag to indicate that the form is ready to submit when a remote/callback validator returns + this._submitIfValid = null; + + this._init(); + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // Indicate fields which won't be validated + // By default, the plugin will not validate the following kind of fields: + // - disabled + // - hidden + // - invisible + // + // The setting consists of jQuery filters. Accept 3 formats: + // - A string. Use a comma to separate filter + // - An array. Each element is a filter + // - An array. Each element can be a callback function + // function($field, validator) { + // $field is jQuery object representing the field element + // validator is the BootstrapValidator instance + // return true or false; + // } + // + // The 3 following settings are equivalent: + // + // 1) ':disabled, :hidden, :not(:visible)' + // 2) [':disabled', ':hidden', ':not(:visible)'] + // 3) [':disabled', ':hidden', function($field) { + // return !$field.is(':visible'); + // }] + excluded: [':disabled', ':hidden', ':not(:visible)'], + + // Shows ok/error/loading icons based on the field validity. + // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation). + // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically. + // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later. + // + // Examples: + // - Use Glyphicons icons: + // feedbackIcons: { + // valid: 'glyphicon glyphicon-ok', + // invalid: 'glyphicon glyphicon-remove', + // validating: 'glyphicon glyphicon-refresh' + // } + // - Use FontAwesome icons: + // feedbackIcons: { + // valid: 'fa fa-check', + // invalid: 'fa fa-times', + // validating: 'fa fa-refresh' + // } + feedbackIcons: { + valid: null, + invalid: null, + validating: null + }, + + // The submit buttons selector + // These buttons will be disabled to prevent the valid form from multiple submissions + submitButtons: 'button[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submission + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating option + // Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + var that = this, + options = { + excluded: this.$form.attr('data-bv-excluded'), + trigger: this.$form.attr('data-bv-trigger'), + message: this.$form.attr('data-bv-message'), + submitButtons: this.$form.attr('data-bv-submitbuttons'), + live: this.$form.attr('data-bv-live'), + 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') + } + }, + validator, + v, // Validator name + enabled, + optionName, + optionValue, + html5AttrName, + html5Attrs; + + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + // Disable the default submission first + .on('submit.bv', function(e) { + e.preventDefault(); + that.validate(); + }) + .on('click', this.options.submitButtons, function() { + that.$submitButton = $(this); + // The user just click the submit button + that._submitIfValid = true; + }) + // Find all fields which have either "name" or "data-bv-field" attribute + .find('[name], [data-bv-field]').each(function() { + var $field = $(this); + // Don't initialize hidden input + if ('hidden' == $field.attr('type')) { + return; + } + + var field = $field.attr('name') || $field.attr('data-bv-field'); + $field.attr('data-bv-field', field); + + options.fields[field] = $.extend({}, { + trigger: $field.attr('data-bv-trigger'), + message: $field.attr('data-bv-message'), + container: $field.attr('data-bv-container'), + selector: $field.attr('data-bv-selector'), + validators: {} + }, options.fields[field]); + + for (v in $.fn.bootstrapValidator.validators) { + validator = $.fn.bootstrapValidator.validators[v]; + enabled = $field.attr('data-bv-' + v.toLowerCase()) + ''; + html5Attrs = ('function' == typeof validator.enableByHtml5) ? validator.enableByHtml5($(this)) : null; + + if ((html5Attrs && enabled != 'false') + || (html5Attrs !== true && ('' == enabled || 'true' == enabled))) + { + // Try to parse the options via attributes + validator.html5Attributes = validator.html5Attributes || { message: 'message' }; + options.fields[field]['validators'][v] = $.extend({}, html5Attrs == true ? {} : html5Attrs, options.fields[field]['validators'][v]); + + for (html5AttrName in validator.html5Attributes) { + optionName = validator.html5Attributes[html5AttrName]; + optionValue = $field.attr('data-bv-' + v.toLowerCase() + '-' + html5AttrName); + if (optionValue) { + if ('true' == optionValue) { + optionValue = true; + } else if ('false' == optionValue) { + optionValue = false; + } + options.fields[field]['validators'][v][optionName] = optionValue; + } + } + } + } + }); + + this.options = $.extend(true, this.options, options); + if ('string' == typeof this.options.excluded) { + this.options.excluded = $.map(this.options.excluded.split(','), function(item) { + // Trim the spaces + return item.trim(); + }); + } + + for (var field in this.options.fields) { + this._initField(field); + } + + this.setLiveMode(this.options.live); + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + var fields = this.getFieldElements(field); + + // We don't need to validate non-existing fields + if (fields == null) { + delete this.options.fields[field]; + return; + } + for (var validatorName in this.options.fields[field].validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + delete this.options.fields[field].validators[validatorName]; + } + } + + var that = this, + type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent, + total = fields.length, + updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type); + + for (var i = 0; i < total; i++) { + var $field = $(fields[i]), + $parent = $field.parents('.form-group'), + // Allow user to indicate where the error messages are shown + $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field); + + // Set the attribute to indicate the fields which are defined by selector + if (!$field.attr('data-bv-field')) { + $field.attr('data-bv-field', field); + } + + // Whenever the user change the field value, mark it as not validated yet + $field.on(event + '.update.bv', function() { + // Reset the flag + that._submitIfValid = false; + updateAll ? that.updateStatus(field, that.STATUS_NOT_VALIDATED, null) + : that.updateElementStatus($(this), that.STATUS_NOT_VALIDATED, null); + }); + + // Create help block elements for showing the error messages + $field.data('bv.messages', $message); + for (validatorName in this.options.fields[field].validators) { + $field.data('bv.result.' + validatorName, this.STATUS_NOT_VALIDATED); + + if (!updateAll || i == total - 1) { + $('') + .css('display', 'none') + .attr('data-bv-validator', validatorName) + .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message) + .addClass('help-block') + .appendTo($message); + } + } + + // Prepare the feedback icons + // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation) + if (this.options.feedbackIcons + && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid + && (!updateAll || i == total - 1)) + { + $parent.addClass('has-feedback'); + var $icon = $('').css('display', 'none').addClass('form-control-feedback').attr('data-bv-field', field).insertAfter($field); + // The feedback icon does not render correctly if there is no label + // https://github.com/twbs/bootstrap/issues/12873 + if ($parent.find('label').length == 0) { + $icon.css('top', 0); + } + } + } + + if (this.options.fields[field]['enabled'] == null) { + this.options.fields[field]['enabled'] = true; + } + }, + + /** + * Get the element to place the error messages + * + * @param {jQuery} $field The field element + * @returns {jQuery} + */ + _getMessageContainer: function($field) { + var $parent = $field.parent(); + if ($parent.hasClass('form-group')) { + return $parent; + } + + var cssClasses = $parent.attr('class'); + if (!cssClasses) { + return this._getMessageContainer($parent); + } + + cssClasses = cssClasses.split(' '); + var n = cssClasses.length; + for (var i = 0; i < n; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i]) || /^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + return $parent; + } + } + + return this._getMessageContainer($parent); + }, + + /** + * Called when all validations are completed + */ + _submit: function() { + if (!this.isValid()) { + if ('submitted' == this.options.live) { + this.setLiveMode('enabled'); + } + + // Focus to the first invalid field + if (this.$invalidField) { + this.$invalidField.focus(); + } + return; + } + + // Call the custom submission if enabled + if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + // If you want to submit the form inside your submit handler, please call defaultSubmit() method + this.options.submitHandler.call(this, this, this.$form, this.$submitButton); + } else { + this.disableSubmitButtons(true).defaultSubmit(); + } + }, + + /** + * Check if the field is excluded. + * Returning true means that the field will not be validated + * + * @param {jQuery} $field The field element + * @return {Boolean} + */ + _isExcluded: function($field) { + if (this.options.excluded) { + for (var i in this.options.excluded) { + if (('string' == typeof this.options.excluded[i] && $field.is(this.options.excluded[i])) + || ('function' == typeof this.options.excluded[i] && this.options.excluded[i].call(this, $field, this) == true)) + { + return true; + } + } + } + + return false; + }, + + // --- Public methods --- + + /** + * Retrieve the field elements by given name + * + * @param {String} field The field name + * @returns {null|jQuery[]} + */ + getFieldElements: function(field) { + var fields = this.options.fields[field].selector ? $(this.options.fields[field].selector) : this.$form.find('[name="' + field + '"]'); + return (fields.length == 0) ? null : fields; + }, + + /** + * Set live validating mode + * + * @param {String} mode Live validating mode. Can be 'enabled', 'disabled', 'submitted' + * @returns {BootstrapValidator} + */ + setLiveMode: function(mode) { + this.options.live = mode; + if ('submitted' == mode) { + return this; + } + + var that = this; + for (var field in this.options.fields) { + (function(f) { + var fields = that.getFieldElements(f); + if (fields) { + var type = fields.attr('type'), + total = fields.length, + updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type), + trigger = that.options.fields[field].trigger + || that.options.trigger + || (('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent), + events = $.map(trigger.split(' '), function(item) { + return item + '.live.bv'; + }).join(' '); + + for (var i = 0; i < total; i++) { + ('enabled' == mode) + ? $(fields[i]).on(events, function() { + updateAll ? that.validateField(f) : that.validateFieldElement($(this), false); + }) + : $(fields[i]).off(events); + } + } + })(field); + } + + return this; + }, + + /** + * Disable/enable submit buttons + * + * @param {Boolean} disabled Can be true or false + * @returns {BootstrapValidator} + */ + disableSubmitButtons: function(disabled) { + if (!disabled) { + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + } else if (this.options.live != 'disabled') { + // Don't disable if the live validating mode is disabled + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + } + + return this; + }, + + /** + * Validate the form + * + * @return {BootstrapValidator} + */ + validate: function() { + if (!this.options.fields) { + return this; + } + this.disableSubmitButtons(true); + + for (var field in this.options.fields) { + this.validateField(field); + } + + // Check if whether the submit button is clicked + if (this.$submitButton) { + this._submit(); + } + + return this; + }, + + /** + * Validate given field + * + * @param {String} field The field name + * @returns {BootstrapValidator} + */ + validateField: function(field) { + var fields = this.getFieldElements(field), + type = fields.attr('type'), + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (var i = 0; i < n; i++) { + this.validateFieldElement($(fields[i]), (n == 1)); + } + + return this; + }, + + /** + * Validate field element + * + * @param {jQuery} $field The field element + * @param {Boolean} updateAll If true, update status of all elements which have the same name + * @returns {BootstrapValidator} + */ + validateFieldElement: function($field, updateAll) { + var that = this, + field = $field.attr('data-bv-field'), + validators = this.options.fields[field].validators, + validatorName, + validateResult; + + if (!this.options.fields[field]['enabled'] || this._isExcluded($field)) { + return this; + } + + for (validatorName in validators) { + if ($field.data('bv.dfs.' + validatorName)) { + $field.data('bv.dfs.' + validatorName).reject(); + } + + // Don't validate field if it is already done + var result = $field.data('bv.result.' + validatorName); + if (result == this.STATUS_VALID || result == this.STATUS_INVALID) { + continue; + } + + $field.data('bv.result.' + validatorName, this.STATUS_VALIDATING); + validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]); + + if ('object' == typeof validateResult) { + updateAll ? this.updateStatus(field, this.STATUS_VALIDATING, validatorName) + : this.updateElementStatus($field, this.STATUS_VALIDATING, validatorName); + $field.data('bv.dfs.' + validatorName, validateResult); + + validateResult.done(function($f, v, isValid) { + // v is validator name + $f.removeData('bv.dfs.' + v); + updateAll ? that.updateStatus($f.attr('data-bv-field'), isValid ? that.STATUS_VALID : that.STATUS_INVALID, v) + : that.updateElementStatus($f, isValid ? that.STATUS_VALID : that.STATUS_INVALID, v); + + if (isValid && that._submitIfValid == true) { + // If a remote validator returns true and the form is ready to submit, then do it + that._submit(); + } + }); + } else if ('boolean' == typeof validateResult) { + updateAll ? this.updateStatus(field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName) + : this.updateElementStatus($field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName); + } + } + + return this; + }, + + /** + * Update all validating results of elements which have the same field name + * + * @param {String} field The field name + * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateStatus: function(field, status, validatorName) { + var fields = this.getFieldElements(field), + type = fields.attr('type'), + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (var i = 0; i < n; i++) { + this.updateElementStatus($(fields[i]), status, validatorName); + } + + return this; + }, + + /** + * Update validating result of given element + * + * @param {jQuery} $field The field element + * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateElementStatus: function($field, status, validatorName) { + var that = this, + field = $field.attr('data-bv-field'), + $parent = $field.parents('.form-group'), + $message = $field.data('bv.messages'), + $rowErrors = $parent.find('.help-block[data-bv-validator]'), + $errors = $message.find('.help-block[data-bv-validator]'), + $icon = $parent.find('.form-control-feedback[data-bv-field="' + field + '"]'); + + // Update status + if (validatorName) { + $field.data('bv.result.' + validatorName, status); + } else { + for (var v in this.options.fields[field].validators) { + $field.data('bv.result.' + v, status); + } + } + + // Show/hide error elements and feedback icons + switch (status) { + case this.STATUS_VALIDATING: + this.disableSubmitButtons(true); + $parent.removeClass('has-success').removeClass('has-error'); + // TODO: Show validating message + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(); + } + break; + + case this.STATUS_INVALID: + this.disableSubmitButtons(true); + $parent.removeClass('has-success').addClass('has-error'); + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').show() : $errors.show(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(); + } + break; + + case this.STATUS_VALID: + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + + // If the field is valid (passes all validators) + var validField = ($errors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || ($field.data('bv.result.' + v) != that.STATUS_VALID); + }).length == 0); + this.disableSubmitButtons(validField ? false : true); + if ($icon) { + $icon + .removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid) + .addClass(validField ? this.options.feedbackIcons.valid : this.options.feedbackIcons.invalid) + .show(); + } + + // Check if all fields in the same row are valid + var validRow = ($rowErrors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || ($field.data('bv.result.' + v) != that.STATUS_VALID); + }).length == 0); + $parent.removeClass('has-error has-success').addClass(validRow ? 'has-success' : 'has-error'); + break; + + case this.STATUS_NOT_VALIDATED: + default: + this.disableSubmitButtons(false); + $parent.removeClass('has-success').removeClass('has-error'); + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide(); + } + break; + } + + return this; + }, + + /** + * Check the form validity + * + * @returns {Boolean} + */ + isValid: function() { + var fields, field, $field, + type, status, validatorName, + n, i; + for (field in this.options.fields) { + if (this.options.fields[field] == null || !this.options.fields[field]['enabled']) { + continue; + } + + fields = this.getFieldElements(field); + type = fields.attr('type'); + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (i = 0; i < n; i++) { + $field = $(fields[i]); + if (this._isExcluded($field)) { + continue; + } + + for (validatorName in this.options.fields[field].validators) { + status = $field.data('bv.result.' + validatorName); + if (status == this.STATUS_NOT_VALIDATED || status == this.STATUS_VALIDATING) { + return false; + } + + if (status == this.STATUS_INVALID) { + this.$invalidField = $field; + return false; + } + } + } + } + + return true; + }, + + /** + * Submit the form using default submission. + * It also does not perform any validations when submitting the form + * + * It might be used when you want to submit the form right inside the submitHandler() + */ + defaultSubmit: function() { + this.$form.off('submit.bv').submit(); + }, + + // Useful APIs which aren't used internally + + /** + * Reset the form + * + * @param {Boolean} resetFormData Reset current form data + * @return {BootstrapValidator} + */ + resetForm: function(resetFormData) { + var field, fields, total, type, validator; + for (field in this.options.fields) { + fields = this.getFieldElements(field); + total = fields.length; + + for (var i = 0; i < total; i++) { + for (validator in this.options.fields[field].validators) { + $(fields[i]).removeData('bv.dfs.' + validator); + } + } + + // Mark field as not validated yet + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + if (resetFormData) { + type = fields.attr('type'); + ('radio' == type || 'checkbox' == type) ? fields.removeAttr('checked').removeAttr('selected') : fields.val(''); + } + } + + this.$invalidField = null; + this.$submitButton = null; + + // Enable submit buttons + this.disableSubmitButtons(false); + + return this; + }, + + /** + * Enable/Disable all validators to given field + * + * @param {String} field The field name + * @param {Boolean} enabled Enable/Disable field validators + * @return {BootstrapValidator} + */ + enableFieldValidators: function(field, enabled) { + this.options.fields[field]['enabled'] = enabled; + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + return this; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(options) { + return this.each(function() { + var $this = $(this), data = $this.data('bootstrapValidator'); + if (!data) { + $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options))); + } + if ('string' == typeof options) { + data[options](); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.base64 = { + /** + * Return true if the input value is a base 64 encoded string. + * + * @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; + } + + return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + if ('range' == $field.attr('type')) { + return { + min: $field.attr('min'), + max: $field.attr('max') + }; + } + + return false; + }, + + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = parseFloat(value); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {Boolean|Deferred} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (options.callback && 'function' == typeof options.callback) { + var dfd = new $.Deferred(); + dfd.resolve($field, 'callback', options.callback.call(this, value, validator)); + return dfd; + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.choice = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max' + }, + + /** + * Check if the number of checked boxes are less or more than a given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var numChoices = validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length; + if ((options.min && numChoices < options.min) || (options.max && numChoices > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + value = value.replace(/\D/g, ''); + + // Validate the check sum + // The Luhn Algorithm + // http://en.wikipedia.org/wiki/Luhn + var check = 0, digit = 0, even = false, length = value.length; + + for (var n = length - 1; n >= 0; n--) { + digit = parseInt(value.charAt(n), 10); + + if (even) { + if ((digit *= 2) > 9) { + digit -= 9; + } + } + + check += digit; + even = !even; + } + + if ((check % 10) != 0) { + return false; + } + + // Validate the card number based on prefix (IIN ranges) and length + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + + var type, i; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (value.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(value.length) != -1) // and length + { + return true; + } + } + } + + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.cvv = { + html5Attributes: { + message: 'message', + ccfield: 'creditCardField' + }, + + /** + * Return true if the input value is a valid CVV number. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - creditCardField: The credit card number field. It can be null + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^[0-9]{3,4}$/.test(value)) { + return false; + } + + if (!options.creditCardField) { + return true; + } + + // Get the credit card number + var creditCard = validator.getFieldElements(options.creditCardField).val(); + if (creditCard == '') { + return true; + } + + // Supported credit card types + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + var type, i, creditCardType = null; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (creditCard.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(creditCard.length) != -1) // and length + { + creditCardType = type; + break; + } + } + } + + return (creditCardType == null) + ? false + : (('AMERICAN_EXPRESS' == creditCardType) ? (value.length == 4) : (value.length == 3)); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.date = { + html5Attributes: { + message: 'message', + format: 'format' + }, + + /** + * Return true if the input value is valid date + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - format: The date format. Default is MM/DD/YYYY + * Support the following formats: + * YYYY/DD/MM + * YYYY/DD/MM h:m A + * YYYY/MM/DD + * YYYY/MM/DD h:m A + * + * YYYY-DD-MM + * YYYY-DD-MM h:m A + * YYYY-MM-DD + * YYYY-MM-DD h:m A + * + * MM/DD/YYYY + * MM/DD/YYYY h:m A + * DD/MM/YYYY + * DD/MM/YYYY h:m A + * + * MM-DD-YYYY + * MM-DD-YYYY h:m A + * DD-MM-YYYY + * DD-MM-YYYY h:m A + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + // Determine the separator + options.format = options.format || 'MM/DD/YYYY'; + var separator = (options.format.indexOf('/') != -1) + ? '/' + : ((options.format.indexOf('-') != -1) ? '-' : null); + if (separator == null) { + return false; + } + + var month, day, year, minutes = null, hours = null, matches; + switch (true) { + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/DD/MM'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-DD-MM'): + year = matches[1]; day = matches[2]; month = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'DD/MM/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'DD-MM-YYYY'): + day = matches[1]; month = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/MM/DD'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-MM-DD'): + year = matches[1]; month = matches[2]; day = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'MM/DD/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'MM-DD-YYYY'): + month = matches[1]; day = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/DD/MM h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-DD-MM h:m A'): + year = matches[1]; day = matches[2]; month = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD/MM/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD-MM-YYYY h:m A'): + day = matches[1]; month = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/MM/DD h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-MM-DD h:m A'): + year = matches[1]; month = matches[2]; day = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM/DD/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM-DD-YYYY h:m A'): + month = matches[1]; day = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + default: + return false; + } + + // Validate hours and minutes + if (hours && minutes) { + hours = parseInt(hours, 10); + minutes = parseInt(minutes, 10); + if (hours < 1 || hours > 12 || minutes < 0 || minutes > 59) { + return false; + } + } + + // Validate day, month, and year + day = parseInt(day, 10); + month = parseInt(month, 10); + year = parseInt(year, 10); + + if (year < 1000 || year > 9999 || month == 0 || month > 12) { + return false; + } + + var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + // Update the number of days in Feb of leap year + if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) { + numDays[1] = 29; + } + + // Check the day + return (day > 0 && day <= numDays[month - 1]); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.different = { + html5Attributes: { + message: 'message', + field: 'field' + }, + + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value != compareWith.val()) { + validator.updateStatus(options.field, validator.STATUS_VALID, 'different'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^\d+$/.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + enableByHtml5: function($field) { + return ('email' == $field.attr('type')); + }, + + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + html5Attributes: { + message: 'message', + value: 'value', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + var min = $field.attr('min'); + if (min) { + return { + value: min + }; + } + + return false; + }, + + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hex = { + /** + * Return true if and only if the input value is a valid hexadecimal number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^[0-9a-fA-F]+$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + enableByHtml5: function($field) { + return ('color' == $field.attr('type')); + }, + + /** + * Return true if the input value is a valid hex color + * + * @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; + } + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.iban = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Validate an International Bank Account Number (IBAN) + * To test it, take the sample IBAN from + * http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html + * + * @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 + * - country: The ISO 3166-1 country code + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // See + // http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf + // http://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country + var ibanRegex = { + '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 + }; + value = value.replace(/[^a-zA-Z0-9]/g, '').toUpperCase(); + var country = options.country || value.substr(0, 2); + if (!ibanRegex[country]) { + return false; + } + if (!(new RegExp('^' + ibanRegex[country] + '$')).test(value)) { + return false; + } + + value = value.substr(4) + value.substr(0, 4); + value = value.split('').map(function(n) { + var code = n.charCodeAt(0); + return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) + // Replace A, B, C, ..., Z with 10, 11, ..., 35 + ? (code - 'A'.charCodeAt(0) + 10) + : n; + }).join(''); + + var temp = parseInt(value.substr(0, 1), 10), + length = value.length; + for (var i = 1; i < length; ++i) { + temp = (temp * 10 + parseInt(value.substr(i, 1), 10)) % 97; + } + return (temp == 1); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + html5Attributes: { + message: 'message', + field: 'field' + }, + + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value == compareWith.val()) { + validator.updateStatus(options.field, validator.STATUS_VALID, 'identical'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.integer = { + enableByHtml5: function($field) { + return ('number' == $field.attr('type')); + }, + + /** + * Return true if the input value is an integer + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + return /^(?:-?(?:0|[1-9][0-9]*))$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.ip = { + html5Attributes: { + message: 'message', + ipv4: 'ipv4', + ipv6: 'ipv6' + }, + + /** + * Return true if the input value is a IP address. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - ipv4: Enable IPv4 validator, default to true + * - ipv6: Enable IPv6 validator, default to true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + options = $.extend({}, { ipv4: true, ipv6: true }, options); + + if (options.ipv4) { + return /^(?:(?: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); + } else if (options.ipv6) { + return /^\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(str); + } + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.isbn = { + /** + * Return true if the input value is a valid ISBN 10 or ISBN 13 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; + } + + // Replace all special characters except digits and X + value = value.replace(/[^\dX]/gi, ''); + var chars = value.split(''), + sum = 0, + checksum; + + // See http://en.wikipedia.org/wiki/International_Standard_Book_Number + switch (chars.length) { + // ISBN 10 + case 10: + sum = 0; + for (var i = 0; i < 9; i++) { + sum += ((10 - i) * parseInt(chars[i])); + } + checksum = 11 - (sum % 11); + if (checksum == 11) { + checksum = 0; + } else if (checksum == 10) { + checksum = 'X'; + } + return (checksum == chars[9]); + + // ISBN 13 + case 13: + sum = 0; + for (var i = 0; i < 12; i++) { + sum += ((i % 2 == 0) ? parseInt(chars[i]) : (parseInt(chars[i]) * 3)); + } + checksum = 10 - (sum % 10); + if (checksum == 10) { + checksum = '0'; + } + return (checksum == chars[12]); + + default: + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + html5Attributes: { + message: 'message', + value: 'value', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + var max = $field.attr('max'); + if (max) { + return { + value: max + }; + } + + return false; + }, + + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === false) ? (value <= options.value) : (value < options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.mac = { + /** + * Return true if the input value is a MAC address. + * + * @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; + } + + return /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + enableByHtml5: function($field) { + var required = $field.attr('required') + ''; + return ('required' == required || 'true' == required); + }, + + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + if ('radio' == type || 'checkbox' == type) { + return validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length > 0; + } + + return $.trim($field.val()) != ''; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.numeric = { + /** + * Validate decimal number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return !isNaN(parseFloat(value)) && isFinite(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.phone = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Return true if the input value contains a valid US phone number only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166 country code + * Currently it only supports United State (US) country + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var country = (options.country || 'US').toUpperCase(); + switch (country) { + case 'US': + default: + // Make sure US phone numbers have 10 digits + // May start with 1, +1, or 1-; should discard + // Area code may be delimited with (), & sections may be delimited with . or - + // Test: http://regexr.com/38mqi + value = value.replace(/\D/g, ''); + return (/^(?:(1\-?)|(\+1 ?))?\(?(\d{3})[\)\-\.]?(\d{3})[\-\.]?(\d{4})$/).test(value) && (value.length == 10); + } + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + html5Attributes: { + message: 'message', + regexp: 'regexp' + }, + + enableByHtml5: function($field) { + var pattern = $field.attr('pattern'); + if (pattern) { + return { + regexp: pattern + }; + } + + return false; + }, + + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var regexp = ('string' == typeof options.regexp) ? new RegExp(options.regexp) : options.regexp; + return regexp.test(value); + } + }; +}(window.jQuery)); +;(function ($) { + $.fn.bootstrapValidator.validators.remote = { + html5Attributes: { + message: 'message', + url: 'url', + name: 'name' + }, + + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - name [optional]: Override the field name for the request. + * - message: The invalid message + * @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; + if (data == null) { + data = {}; + } + // Support dynamic data + if ('function' == typeof data) { + data = data.call(this, validator); + } + data[options.name || name] = value; + + var dfd = new $.Deferred(); + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }); + xhr.then(function(response) { + dfd.resolve($field, 'remote', response.valid === true || response.valid === 'true'); + }); + + dfd.fail(function() { + xhr.abort(); + }); + + return dfd; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.siren = { + /** + * Check if a string is a siren number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var sum = 0, + length = value.length, + tmp; + for (var i = 0; i < length; i++) { + tmp = parseInt(value.charAt(i)); + if ((i % 2) == 1) { + tmp = tmp * 2; + if (tmp > 9) { + tmp -= 9; + } + } + sum += tmp; + } + return ((sum % 10) == 0); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.siret = { + /** + * Check if a string is a siret number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var sum = 0, + length = value.length, + tmp; + for (var i = 0; i < length; i++) { + tmp = parseInt(value.charAt(i)); + if ((i % 2) == 0) { + tmp = tmp * 2; + if (tmp > 9) { + tmp -= 9; + } + } + sum += tmp; + } + return ((sum % 10) == 0); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.step = { + html5Attributes: { + message: 'message', + base: 'baseValue', + step: 'step' + }, + + /** + * Return true if the input value is valid step one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - baseValue: The base value + * - step: The step + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options = $.extend({}, { baseValue: 0, step: 1 }, options); + value = parseFloat(value); + if (isNaN(value) || !isFinite(value)) { + return false; + } + + var round = function(x, precision) { + var m = Math.pow(10, precision); + x = x * m; + var sign = (x > 0) | -(x < 0), + isHalf = (x % 1 === 0.5 * sign); + if (isHalf) { + return (Math.floor(x) + (sign > 0)) / m; + } else { + return Math.round(x) / m; + } + }, + floatMod = function(x, y) { + if (y == 0.0) { + return 1.0; + } + var dotX = (x + '').split('.'), + dotY = (y + '').split('.'), + precision = ((dotX.length == 1) ? 0 : dotX[1].length) + ((dotY.length == 1) ? 0 : dotY[1].length); + return round(x - y * Math.floor(x / y), precision); + }; + + var mod = floatMod(value - options.baseValue, options.step); + return (mod == 0.0 || mod == options.step); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringCase = { + html5Attributes: { + message: 'message', + 'case': 'case' + }, + + /** + * Check if a string is a lower or upper case one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - case: Can be 'lower' (default) or 'upper' + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var stringCase = (options['case'] || 'lower').toLowerCase(); + switch (stringCase) { + case 'upper': + return value === value.toUpperCase(); + case 'lower': + default: + return value === value.toLowerCase(); + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max' + }, + + enableByHtml5: function($field) { + var maxLength = $field.attr('maxlength'); + if (maxLength) { + return { + max: parseInt(maxLength, 10) + }; + } + + return false; + }, + + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var length = $.trim(value).length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + enableByHtml5: function($field) { + return ('url' == $field.attr('type')); + }, + + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uuid = { + html5Attributes: { + message: 'message', + version: 'version' + }, + + /** + * Return true if and only if the input value is a valid UUID string + * + * @see http://en.wikipedia.org/wiki/Universally_unique_identifier + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - version: Can be 3, 4, 5, null + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // See the format at http://en.wikipedia.org/wiki/Universally_unique_identifier#Variants_and_versions + var patterns = { + '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, + '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i + }, + version = options.version ? (options.version + '') : 'all'; + return (null == patterns[version]) ? true : patterns[version].test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.vin = { + /** + * Validate an US VIN (Vehicle Identification Number) + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Don't accept I, O, Q characters + if (!/^[a-hj-npr-z0-9]{8}[0-9xX][a-hj-npr-z0-9]{8}$/i.test(value)) { + return false; + } + + value = value.toUpperCase(); + var chars = { + A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8, + J: 1, K: 2, L: 3, M: 4, N: 5, P: 7, R: 9, + S: 2, T: 3, U: 4, V: 5, W: 6, X: 7, Y: 8, Z: 9, + '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '0': 0 + }, + weights = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2], + sum = 0, + length = value.length; + for (var i = 0; i < length; i++) { + sum += chars[value.charAt(i) + ''] * weights[i]; + } + + var reminder = sum % 11; + if (reminder == 10) { + reminder = 'X'; + } + + return reminder == value.charAt(8); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.zipCode = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Return true if and only if the input value is a valid country zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166 country code + * + * Currently it supports the following countries: + * - US (United State) + * - DK (Denmark) + * - SE (Sweden) + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '' || !options.country) { + return true; + } + + options.country = options.country || 'US'; + switch (options.country.toUpperCase()) { + case 'DK': + return /^(DK(-|\s)?)?\d{4}$/i.test(value); + case 'SE': + return /^(S-)?\d{3}\s?\d{2}$/i.test(value); + case 'US': + default: + return /^\d{4,5}([\-]\d{4})?$/.test(value); + } + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.2/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.4.2/js/bootstrapValidator.min.js new file mode 100644 index 000000000..7a4490433 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.2/js/bootstrapValidator.min.js @@ -0,0 +1,12 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.2 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),this.$invalidField=null,this.$submitButton=null,this.STATUS_NOT_VALIDATED="NOT_VALIDATED",this.STATUS_VALIDATING="VALIDATING",this.STATUS_INVALID="INVALID",this.STATUS_VALID="VALID";var e=document.createElement("div");this._changeEvent="oninput"in e?"input":"keydown",this._submitIfValid=null,this._init()};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",excluded:[":disabled",":hidden",":not(:visible)"],feedbackIcons:{valid:null,invalid:null,validating:null},submitButtons:'button[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){var b,c,d,e,f,g,h,i=this,j={excluded:this.$form.attr("data-bv-excluded"),trigger:this.$form.attr("data-bv-trigger"),message:this.$form.attr("data-bv-message"),submitButtons:this.$form.attr("data-bv-submitbuttons"),live:this.$form.attr("data-bv-live"),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")}};this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit.bv",function(a){a.preventDefault(),i.validate()}).on("click",this.options.submitButtons,function(){i.$submitButton=a(this),i._submitIfValid=!0}).find("[name], [data-bv-field]").each(function(){var i=a(this);if("hidden"!=i.attr("type")){var k=i.attr("name")||i.attr("data-bv-field");i.attr("data-bv-field",k),j.fields[k]=a.extend({},{trigger:i.attr("data-bv-trigger"),message:i.attr("data-bv-message"),container:i.attr("data-bv-container"),selector:i.attr("data-bv-selector"),validators:{}},j.fields[k]);for(c in a.fn.bootstrapValidator.validators)if(b=a.fn.bootstrapValidator.validators[c],d=i.attr("data-bv-"+c.toLowerCase())+"",h="function"==typeof b.enableByHtml5?b.enableByHtml5(a(this)):null,h&&"false"!=d||h!==!0&&(""==d||"true"==d)){b.html5Attributes=b.html5Attributes||{message:"message"},j.fields[k].validators[c]=a.extend({},1==h?{}:h,j.fields[k].validators[c]);for(g in b.html5Attributes)e=b.html5Attributes[g],f=i.attr("data-bv-"+c.toLowerCase()+"-"+g),f&&("true"==f?f=!0:"false"==f&&(f=!1),j.fields[k].validators[c][e]=f)}}}),this.options=a.extend(!0,this.options,j),"string"==typeof this.options.excluded&&(this.options.excluded=a.map(this.options.excluded.split(","),function(a){return a.trim()}));for(var k in this.options.fields)this._initField(k);this.setLiveMode(this.options.live)},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){var c=this.getFieldElements(b);if(null==c)return void delete this.options.fields[b];for(var d in this.options.fields[b].validators)a.fn.bootstrapValidator.validators[d]||delete this.options.fields[b].validators[d];for(var e=this,f=c.attr("type"),g="radio"==f||"checkbox"==f||"file"==f||"SELECT"==c[0].tagName?"change":e._changeEvent,h=c.length,i=1==h||"radio"==f||"checkbox"==f,j=0;h>j;j++){var k=a(c[j]),l=k.parents(".form-group"),m=this.options.fields[b].container?l.find(this.options.fields[b].container):this._getMessageContainer(k);k.attr("data-bv-field")||k.attr("data-bv-field",b),k.on(g+".update.bv",function(){e._submitIfValid=!1,i?e.updateStatus(b,e.STATUS_NOT_VALIDATED,null):e.updateElementStatus(a(this),e.STATUS_NOT_VALIDATED,null)}),k.data("bv.messages",m);for(d in this.options.fields[b].validators)k.data("bv.result."+d,this.STATUS_NOT_VALIDATED),i&&j!=h-1||a("").css("display","none").attr("data-bv-validator",d).html(this.options.fields[b].validators[d].message||this.options.fields[b].message||this.options.message).addClass("help-block").appendTo(m);if(this.options.feedbackIcons&&this.options.feedbackIcons.validating&&this.options.feedbackIcons.invalid&&this.options.feedbackIcons.valid&&(!i||j==h-1)){l.addClass("has-feedback");var n=a("").css("display","none").addClass("form-control-feedback").attr("data-bv-field",b).insertAfter(k);0==l.find("label").length&&n.css("top",0)}}null==this.options.fields[b].enabled&&(this.options.fields[b].enabled=!0)}},_getMessageContainer:function(a){var b=a.parent();if(b.hasClass("form-group"))return b;var c=b.attr("class");if(!c)return this._getMessageContainer(b);c=c.split(" ");for(var d=c.length,e=0;d>e;e++)if(/^col-(xs|sm|md|lg)-\d+$/.test(c[e])||/^col-(xs|sm|md|lg)-offset-\d+$/.test(c[e]))return b;return this._getMessageContainer(b)},_submit:function(){return this.isValid()?void(this.options.submitHandler&&"function"==typeof this.options.submitHandler?this.options.submitHandler.call(this,this,this.$form,this.$submitButton):this.disableSubmitButtons(!0).defaultSubmit()):("submitted"==this.options.live&&this.setLiveMode("enabled"),void(this.$invalidField&&this.$invalidField.focus()))},_isExcluded:function(a){if(this.options.excluded)for(var b in this.options.excluded)if("string"==typeof this.options.excluded[b]&&a.is(this.options.excluded[b])||"function"==typeof this.options.excluded[b]&&1==this.options.excluded[b].call(this,a,this))return!0;return!1},getFieldElements:function(b){var c=this.options.fields[b].selector?a(this.options.fields[b].selector):this.$form.find('[name="'+b+'"]');return 0==c.length?null:c},setLiveMode:function(b){if(this.options.live=b,"submitted"==b)return this;var c=this;for(var d in this.options.fields)!function(e){var f=c.getFieldElements(e);if(f)for(var g=f.attr("type"),h=f.length,i=1==h||"radio"==g||"checkbox"==g,j=c.options.fields[d].trigger||c.options.trigger||("radio"==g||"checkbox"==g||"file"==g||"SELECT"==f[0].tagName?"change":c._changeEvent),k=a.map(j.split(" "),function(a){return a+".live.bv"}).join(" "),l=0;h>l;l++)"enabled"==b?a(f[l]).on(k,function(){i?c.validateField(e):c.validateFieldElement(a(this),!1)}):a(f[l]).off(k)}(d);return this},disableSubmitButtons:function(a){return a?"disabled"!=this.options.live&&this.$form.find(this.options.submitButtons).attr("disabled","disabled"):this.$form.find(this.options.submitButtons).removeAttr("disabled"),this},validate:function(){if(!this.options.fields)return this;this.disableSubmitButtons(!0);for(var a in this.options.fields)this.validateField(a);return this.$submitButton&&this._submit(),this},validateField:function(b){for(var c=this.getFieldElements(b),d=c.attr("type"),e="radio"==d||"checkbox"==d?1:c.length,f=0;e>f;f++)this.validateFieldElement(a(c[f]),1==e);return this},validateFieldElement:function(b,c){var d,e,f=this,g=b.attr("data-bv-field"),h=this.options.fields[g].validators;if(!this.options.fields[g].enabled||this._isExcluded(b))return this;for(d in h){b.data("bv.dfs."+d)&&b.data("bv.dfs."+d).reject();var i=b.data("bv.result."+d);i!=this.STATUS_VALID&&i!=this.STATUS_INVALID&&(b.data("bv.result."+d,this.STATUS_VALIDATING),e=a.fn.bootstrapValidator.validators[d].validate(this,b,h[d]),"object"==typeof e?(c?this.updateStatus(g,this.STATUS_VALIDATING,d):this.updateElementStatus(b,this.STATUS_VALIDATING,d),b.data("bv.dfs."+d,e),e.done(function(a,b,d){a.removeData("bv.dfs."+b),c?f.updateStatus(a.attr("data-bv-field"),d?f.STATUS_VALID:f.STATUS_INVALID,b):f.updateElementStatus(a,d?f.STATUS_VALID:f.STATUS_INVALID,b),d&&1==f._submitIfValid&&f._submit()})):"boolean"==typeof e&&(c?this.updateStatus(g,e?this.STATUS_VALID:this.STATUS_INVALID,d):this.updateElementStatus(b,e?this.STATUS_VALID:this.STATUS_INVALID,d)))}return this},updateStatus:function(b,c,d){for(var e=this.getFieldElements(b),f=e.attr("type"),g="radio"==f||"checkbox"==f?1:e.length,h=0;g>h;h++)this.updateElementStatus(a(e[h]),c,d);return this},updateElementStatus:function(b,c,d){var e=this,f=b.attr("data-bv-field"),g=b.parents(".form-group"),h=b.data("bv.messages"),i=g.find(".help-block[data-bv-validator]"),j=h.find(".help-block[data-bv-validator]"),k=g.find('.form-control-feedback[data-bv-field="'+f+'"]');if(d)b.data("bv.result."+d,c);else for(var l in this.options.fields[f].validators)b.data("bv.result."+l,c);switch(c){case this.STATUS_VALIDATING:this.disableSubmitButtons(!0),g.removeClass("has-success").removeClass("has-error"),d?j.filter('.help-block[data-bv-validator="'+d+'"]').hide():j.hide(),k&&k.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show();break;case this.STATUS_INVALID:this.disableSubmitButtons(!0),g.removeClass("has-success").addClass("has-error"),d?j.filter('[data-bv-validator="'+d+'"]').show():j.show(),k&&k.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show();break;case this.STATUS_VALID:d?j.filter('[data-bv-validator="'+d+'"]').hide():j.hide();var m=0==j.filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||b.data("bv.result."+d)!=e.STATUS_VALID}).length;this.disableSubmitButtons(m?!1:!0),k&&k.removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid).addClass(m?this.options.feedbackIcons.valid:this.options.feedbackIcons.invalid).show();var n=0==i.filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||b.data("bv.result."+d)!=e.STATUS_VALID}).length;g.removeClass("has-error has-success").addClass(n?"has-success":"has-error");break;case this.STATUS_NOT_VALIDATED:default:this.disableSubmitButtons(!1),g.removeClass("has-success").removeClass("has-error"),d?j.filter('.help-block[data-bv-validator="'+d+'"]').hide():j.hide(),k&&k.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide()}return this},isValid:function(){var b,c,d,e,f,g,h,i;for(c in this.options.fields)if(null!=this.options.fields[c]&&this.options.fields[c].enabled)for(b=this.getFieldElements(c),e=b.attr("type"),h="radio"==e||"checkbox"==e?1:b.length,i=0;h>i;i++)if(d=a(b[i]),!this._isExcluded(d))for(g in this.options.fields[c].validators){if(f=d.data("bv.result."+g),f==this.STATUS_NOT_VALIDATED||f==this.STATUS_VALIDATING)return!1;if(f==this.STATUS_INVALID)return this.$invalidField=d,!1}return!0},defaultSubmit:function(){this.$form.off("submit.bv").submit()},resetForm:function(b){var c,d,e,f,g;for(c in this.options.fields){d=this.getFieldElements(c),e=d.length;for(var h=0;e>h;h++)for(g in this.options.fields[c].validators)a(d[h]).removeData("bv.dfs."+g);this.updateStatus(c,this.STATUS_NOT_VALIDATED,null),b&&(f=d.attr("type"),"radio"==f||"checkbox"==f?d.removeAttr("checked").removeAttr("selected"):d.val(""))}return this.$invalidField=null,this.$submitButton=null,this.disableSubmitButtons(!1),this},enableFieldValidators:function(a,b){return this.options.fields[a].enabled=b,this.updateStatus(a,this.STATUS_NOT_VALIDATED,null),this}},a.fn.bootstrapValidator=function(c){return this.each(function(){var d=a(this),e=d.data("bootstrapValidator");e||d.data("bootstrapValidator",e=new b(this,c)),"string"==typeof c&&e[c]()})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.base64={validate:function(a,b){var c=b.val();return""==c?!0:/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={html5Attributes:{message:"message",min:"min",max:"max",inclusive:"inclusive"},enableByHtml5:function(a){return"range"==a.attr("type")?{min:a.attr("min"),max:a.attr("max")}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(b,c,d){var e=c.val();if(d.callback&&"function"==typeof d.callback){var f=new a.Deferred;return f.resolve(c,"callback",d.callback.call(this,e,b)),f}return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.choice={html5Attributes:{message:"message",min:"min",max:"max"},validate:function(a,b,c){var d=a.getFieldElements(b.attr("data-bv-field")).filter(":checked").length;return c.min&&dc.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(a,b){var c=b.val();if(""==c)return!0;if(/[^0-9-\s]+/.test(c))return!1;c=c.replace(/\D/g,"");for(var d=0,e=0,f=!1,g=c.length,h=g-1;h>=0;h--)e=parseInt(c.charAt(h),10),f&&(e*=2)>9&&(e-=9),d+=e,f=!f;if(d%10!=0)return!1;var i,j,k={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["3528","3529","353","354","355","356","357","358"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}};for(i in k)for(j in k[i].prefix)if(c.substr(0,k[i].prefix[j].length)==k[i].prefix[j]&&-1!=k[i].length.indexOf(c.length))return!0;return!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.cvv={html5Attributes:{message:"message",ccfield:"creditCardField"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;if(!/^[0-9]{3,4}$/.test(d))return!1;if(!c.creditCardField)return!0;var e=a.getFieldElements(c.creditCardField).val();if(""==e)return!0;var f,g,h={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["3528","3529","353","354","355","356","357","358"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}},i=null;for(f in h)for(g in h[f].prefix)if(e.substr(0,h[f].prefix[g].length)==h[f].prefix[g]&&-1!=h[f].length.indexOf(e.length)){i=f;break}return null==i?!1:"AMERICAN_EXPRESS"==i?4==d.length:3==d.length}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.date={html5Attributes:{message:"message",format:"format"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;c.format=c.format||"MM/DD/YYYY";var e=-1!=c.format.indexOf("/")?"/":-1!=c.format.indexOf("-")?"-":null;if(null==e)return!1;var f,g,h,i,j=null,k=null;switch(!0){case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/DD/MM"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-DD-MM"==c.format:h=i[1],g=i[2],f=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"DD/MM/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"DD-MM-YYYY"==c.format:g=i[1],f=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/MM/DD"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-MM-DD"==c.format:h=i[1],f=i[2],g=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"MM/DD/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"MM-DD-YYYY"==c.format:f=i[1],g=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/DD/MM h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-DD-MM h:m A"==c.format:h=i[1],g=i[2],f=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD/MM/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD-MM-YYYY h:m A"==c.format:g=i[1],f=i[2],h=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/MM/DD h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-MM-DD h:m A"==c.format:h=i[1],f=i[2],g=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM/DD/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM-DD-YYYY h:m A"==c.format:f=i[1],g=i[2],h=i[3],k=i[4],j=i[5];break;default:return!1}if(k&&j&&(k=parseInt(k,10),j=parseInt(j,10),1>k||k>12||0>j||j>59))return!1;if(g=parseInt(g,10),f=parseInt(f,10),h=parseInt(h,10),1e3>h||h>9999||0==f||f>12)return!1;var l=[31,28,31,30,31,30,31,31,30,31,30,31];return(h%400==0||h%100!=0&&h%4==0)&&(l[1]=29),g>0&&g<=l[f-1]}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={html5Attributes:{message:"message",field:"field"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d!=e.val()?(a.updateStatus(c.field,a.STATUS_VALID,"different"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){var c=b.val();return""==c?!0:/^\d+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={enableByHtml5:function(a){return"email"==a.attr("type")},validate:function(a,b){var c=b.val();if(""==c)return!0;var d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={html5Attributes:{message:"message",value:"value",inclusive:"inclusive"},enableByHtml5:function(a){var b=a.attr("min");return b?{value:b}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.value:d>=c.value)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hex={validate:function(a,b){var c=b.val();return""==c?!0:/^[0-9a-fA-F]+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={enableByHtml5:function(a){return"color"==a.attr("type")},validate:function(a,b){var c=b.val();return""==c?!0:/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.iban={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e={AD:"AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}",AE:"AE[0-9]{2}[0-9]{3}[0-9]{16}",AL:"AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}",AO:"AO[0-9]{2}[0-9]{21}",AT:"AT[0-9]{2}[0-9]{5}[0-9]{11}",AZ:"AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}",BA:"BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}",BE:"BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}",BF:"BF[0-9]{2}[0-9]{23}",BG:"BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}",BH:"BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}",BI:"BI[0-9]{2}[0-9]{12}",BJ:"BJ[0-9]{2}[A-Z]{1}[0-9]{23}",BR:"BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]",CH:"CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}",CI:"CI[0-9]{2}[A-Z]{1}[0-9]{23}",CM:"CM[0-9]{2}[0-9]{23}",CR:"CR[0-9]{2}[0-9]{3}[0-9]{14}",CV:"CV[0-9]{2}[0-9]{21}",CY:"CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}",CZ:"CZ[0-9]{2}[0-9]{20}",DE:"DE[0-9]{2}[0-9]{8}[0-9]{10}",DK:"DK[0-9]{2}[0-9]{14}",DO:"DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}",DZ:"DZ[0-9]{2}[0-9]{20}",EE:"EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}",ES:"ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}",FI:"FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}",FO:"FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}",FR:"FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}",GB:"GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}",GE:"GE[0-9]{2}[A-Z]{2}[0-9]{16}",GI:"GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}",GL:"GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}",GR:"GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}",GT:"GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}",HR:"HR[0-9]{2}[0-9]{7}[0-9]{10}",HU:"HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}",IE:"IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}",IL:"IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}",IR:"IR[0-9]{2}[0-9]{22}",IS:"IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}",IT:"IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}",JO:"JO[0-9]{2}[A-Z]{4}[0-9]{4}[0]{8}[A-Z0-9]{10}",KW:"KW[0-9]{2}[A-Z]{4}[0-9]{22}",KZ:"KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}",LB:"LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}",LI:"LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}",LT:"LT[0-9]{2}[0-9]{5}[0-9]{11}",LU:"LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}",LV:"LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}",MC:"MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}",MD:"MD[0-9]{2}[A-Z0-9]{20}",ME:"ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",MG:"MG[0-9]{2}[0-9]{23}",MK:"MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}",ML:"ML[0-9]{2}[A-Z]{1}[0-9]{23}",MR:"MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}",MT:"MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}",MU:"MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}",MZ:"MZ[0-9]{2}[0-9]{21}",NL:"NL[0-9]{2}[A-Z]{4}[0-9]{10}",NO:"NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}",PK:"PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}",PL:"PL[0-9]{2}[0-9]{8}[0-9]{16}",PS:"PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}",PT:"PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}",QA:"QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}",RO:"RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}",RS:"RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",SA:"SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}",SE:"SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}",SI:"SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}",SK:"SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}",SM:"SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}",SN:"SN[0-9]{2}[A-Z]{1}[0-9]{23}",TN:"TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",TR:"TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}",VG:"VG[0-9]{2}[A-Z]{4}[0-9]{16}"};d=d.replace(/[^a-zA-Z0-9]/g,"").toUpperCase();var f=c.country||d.substr(0,2);if(!e[f])return!1;if(!new RegExp("^"+e[f]+"$").test(d))return!1;d=d.substr(4)+d.substr(0,4),d=d.split("").map(function(a){var b=a.charCodeAt(0);return b>="A".charCodeAt(0)&&b<="Z".charCodeAt(0)?b-"A".charCodeAt(0)+10:a}).join("");for(var g=parseInt(d.substr(0,1),10),h=d.length,i=1;h>i;++i)g=(10*g+parseInt(d.substr(i,1),10))%97;return 1==g}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={html5Attributes:{message:"message",field:"field"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d==e.val()?(a.updateStatus(c.field,a.STATUS_VALID,"identical"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.integer={enableByHtml5:function(a){return"number"==a.attr("type")},validate:function(a,b){var c=b.val();return""==c?!0:/^(?:-?(?:0|[1-9][0-9]*))$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.ip={html5Attributes:{message:"message",ipv4:"ipv4",ipv6:"ipv6"},validate:function(b,c,d){var e=c.val();return""==e?!0:(d=a.extend({},{ipv4:!0,ipv6:!0},d),d.ipv4?/^(?:(?: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(e):d.ipv6?/^\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(str):!1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.isbn={validate:function(a,b){var c=b.val();if(""==c)return!0;c=c.replace(/[^\dX]/gi,"");var d,e=c.split(""),f=0;switch(e.length){case 10:f=0;for(var g=0;9>g;g++)f+=(10-g)*parseInt(e[g]);return d=11-f%11,11==d?d=0:10==d&&(d="X"),d==e[9];case 13:f=0;for(var g=0;12>g;g++)f+=g%2==0?parseInt(e[g]):3*parseInt(e[g]);return d=10-f%10,10==d&&(d="0"),d==e[12];default:return!1}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={html5Attributes:{message:"message",value:"value",inclusive:"inclusive"},enableByHtml5:function(a){var b=a.attr("max");return b?{value:b}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!1?d<=c.value:d0:""!=a.trim(c.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.numeric={validate:function(a,b){var c=b.val();return""==c?!0:!isNaN(parseFloat(c))&&isFinite(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.phone={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=(c.country||"US").toUpperCase();switch(e){case"US":default:return d=d.replace(/\D/g,""),/^(?:(1\-?)|(\+1 ?))?\(?(\d{3})[\)\-\.]?(\d{3})[\-\.]?(\d{4})$/.test(d)&&10==d.length}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.regexp={html5Attributes:{message:"message",regexp:"regexp"},enableByHtml5:function(a){var b=a.attr("pattern");return b?{regexp:b}:!1},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e="string"==typeof c.regexp?new RegExp(c.regexp):c.regexp;return e.test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.remote={html5Attributes:{message:"message",url:"url",name:"name"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=c.attr("data-bv-field"),g=d.data;null==g&&(g={}),"function"==typeof g&&(g=g.call(this,b)),g[d.name||f]=e;var h=new a.Deferred,i=a.ajax({type:"POST",url:d.url,dataType:"json",data:g});return i.then(function(a){h.resolve(c,"remote",a.valid===!0||"true"===a.valid)}),h.fail(function(){i.abort()}),h}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.siren={validate:function(a,b){var c=b.val();if(""==c)return!0;for(var d,e=0,f=c.length,g=0;f>g;g++)d=parseInt(c.charAt(g)),g%2==1&&(d=2*d,d>9&&(d-=9)),e+=d;return e%10==0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.siret={validate:function(a,b){var c=b.val();if(""==c)return!0;for(var d,e=0,f=c.length,g=0;f>g;g++)d=parseInt(c.charAt(g)),g%2==0&&(d=2*d,d>9&&(d-=9)),e+=d;return e%10==0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.step={html5Attributes:{message:"message",base:"baseValue",step:"step"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;if(d=a.extend({},{baseValue:0,step:1},d),e=parseFloat(e),isNaN(e)||!isFinite(e))return!1;var f=function(a,b){var c=Math.pow(10,b);a*=c;var d=a>0|-(0>a),e=a%1===.5*d;return e?(Math.floor(a)+(d>0))/c:Math.round(a)/c},g=function(a,b){if(0==b)return 1;var c=(a+"").split("."),d=(b+"").split("."),e=(1==c.length?0:c[1].length)+(1==d.length?0:d[1].length);return f(a-b*Math.floor(a/b),e)},h=g(e-d.baseValue,d.step);return 0==h||h==d.step}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringCase={html5Attributes:{message:"message","case":"case"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=(c["case"]||"lower").toLowerCase();switch(e){case"upper":return d===d.toUpperCase();case"lower":default:return d===d.toLowerCase()}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringLength={html5Attributes:{message:"message",min:"min",max:"max"},enableByHtml5:function(a){var b=a.attr("maxlength");return b?{max:parseInt(b,10)}:!1},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=a.trim(e).length;return d.min&&fd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={enableByHtml5:function(a){return"url"==a.attr("type")},validate:function(a,b){var c=b.val();if(""==c)return!0;var d=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uuid={html5Attributes:{message:"message",version:"version"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i},f=c.version?c.version+"":"all";return null==e[f]?!0:e[f].test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.vin={validate:function(a,b){var c=b.val();if(""==c)return!0;if(!/^[a-hj-npr-z0-9]{8}[0-9xX][a-hj-npr-z0-9]{8}$/i.test(c))return!1;c=c.toUpperCase();for(var d={A:1,B:2,C:3,D:4,E:5,F:6,G:7,H:8,J:1,K:2,L:3,M:4,N:5,P:7,R:9,S:2,T:3,U:4,V:5,W:6,X:7,Y:8,Z:9,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,0:0},e=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],f=0,g=c.length,h=0;g>h;h++)f+=d[c.charAt(h)+""]*e[h];var i=f%11;return 10==i&&(i="X"),i==c.charAt(8)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.zipCode={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d||!c.country)return!0;switch(c.country=c.country||"US",c.country.toUpperCase()){case"DK":return/^(DK(-|\s)?)?\d{4}$/i.test(d);case"SE":return/^(S-)?\d{3}\s?\d{2}$/i.test(d);case"US":default:return/^\d{4,5}([\-]\d{4})?$/.test(d)}}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.3/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.4.3/css/bootstrapValidator.css new file mode 100644 index 000000000..20b84ba8d --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.3/css/bootstrapValidator.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ + +.bootstrap-validator-form .help-block { + margin-bottom: 0; +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.3/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.4.3/css/bootstrapValidator.min.css new file mode 100644 index 000000000..cc00e2153 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.3/css/bootstrapValidator.min.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.3 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + + +.bootstrap-validator-form .help-block{margin-bottom:0} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.3/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.4.3/js/bootstrapValidator.js new file mode 100644 index 000000000..c6389c065 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.3/js/bootstrapValidator.js @@ -0,0 +1,3672 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.3 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + this.$invalidField = null; // First invalid field + this.$submitButton = null; // The submit button which is clicked to submit form + + // Validating status + this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED'; + this.STATUS_VALIDATING = 'VALIDATING'; + this.STATUS_INVALID = 'INVALID'; + this.STATUS_VALID = 'VALID'; + + // Determine the event that is fired when user change the field value + // Most modern browsers supports input event except IE 7, 8. + // IE 9 supports input event but the event is still not fired if I press the backspace key. + // Get IE version + // https://gist.github.com/padolsey/527683/#comment-7595 + var ieVersion = (function() { + var v = 3, div = document.createElement('div'), a = div.all || []; + while (div.innerHTML = '', a[0]); + return v > 4 ? v : !v; + }()); + + var el = document.createElement('div'); + this._changeEvent = (ieVersion === 9 || !('oninput' in el)) ? 'keyup' : 'input'; + + // The flag to indicate that the form is ready to submit when a remote/callback validator returns + this._submitIfValid = null; + + this._init(); + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bootstrap-validator-form', + + // Default invalid message + message: 'This value is not valid', + + // Indicate fields which won't be validated + // By default, the plugin will not validate the following kind of fields: + // - disabled + // - hidden + // - invisible + // + // The setting consists of jQuery filters. Accept 3 formats: + // - A string. Use a comma to separate filter + // - An array. Each element is a filter + // - An array. Each element can be a callback function + // function($field, validator) { + // $field is jQuery object representing the field element + // validator is the BootstrapValidator instance + // return true or false; + // } + // + // The 3 following settings are equivalent: + // + // 1) ':disabled, :hidden, :not(:visible)' + // 2) [':disabled', ':hidden', ':not(:visible)'] + // 3) [':disabled', ':hidden', function($field) { + // return !$field.is(':visible'); + // }] + excluded: [':disabled', ':hidden', ':not(:visible)'], + + // Shows ok/error/loading icons based on the field validity. + // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation). + // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically. + // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later. + // + // Examples: + // - Use Glyphicons icons: + // feedbackIcons: { + // valid: 'glyphicon glyphicon-ok', + // invalid: 'glyphicon glyphicon-remove', + // validating: 'glyphicon glyphicon-refresh' + // } + // - Use FontAwesome icons: + // feedbackIcons: { + // valid: 'fa fa-check', + // invalid: 'fa fa-times', + // validating: 'fa fa-refresh' + // } + feedbackIcons: { + valid: null, + invalid: null, + validating: null + }, + + // The submit buttons selector + // These buttons will be disabled to prevent the valid form from multiple submissions + submitButtons: 'button[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submission + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating option + // Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + var that = this, + options = { + excluded: this.$form.attr('data-bv-excluded'), + trigger: this.$form.attr('data-bv-trigger'), + message: this.$form.attr('data-bv-message'), + submitButtons: this.$form.attr('data-bv-submitbuttons'), + live: this.$form.attr('data-bv-live'), + 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') + } + }, + validator, + v, // Validator name + enabled, + optionName, + optionValue, + html5AttrName, + html5Attrs; + + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + // Disable the default submission first + .on('submit.bv', function(e) { + e.preventDefault(); + that.validate(); + }) + .on('click', this.options.submitButtons, function() { + that.$submitButton = $(this); + // The user just click the submit button + that._submitIfValid = true; + }) + // Find all fields which have either "name" or "data-bv-field" attribute + .find('[name], [data-bv-field]').each(function() { + var $field = $(this); + // Don't initialize hidden input + if ('hidden' == $field.attr('type')) { + return; + } + + var field = $field.attr('name') || $field.attr('data-bv-field'); + $field.attr('data-bv-field', field); + + options.fields[field] = $.extend({}, { + trigger: $field.attr('data-bv-trigger'), + message: $field.attr('data-bv-message'), + container: $field.attr('data-bv-container'), + selector: $field.attr('data-bv-selector'), + validators: {} + }, options.fields[field]); + + for (v in $.fn.bootstrapValidator.validators) { + validator = $.fn.bootstrapValidator.validators[v]; + enabled = $field.attr('data-bv-' + v.toLowerCase()) + ''; + html5Attrs = ('function' == typeof validator.enableByHtml5) ? validator.enableByHtml5($(this)) : null; + + if ((html5Attrs && enabled != 'false') + || (html5Attrs !== true && ('' == enabled || 'true' == enabled))) + { + // Try to parse the options via attributes + validator.html5Attributes = validator.html5Attributes || { message: 'message' }; + options.fields[field]['validators'][v] = $.extend({}, html5Attrs == true ? {} : html5Attrs, options.fields[field]['validators'][v]); + + for (html5AttrName in validator.html5Attributes) { + optionName = validator.html5Attributes[html5AttrName]; + optionValue = $field.attr('data-bv-' + v.toLowerCase() + '-' + html5AttrName); + if (optionValue) { + if ('true' == optionValue) { + optionValue = true; + } else if ('false' == optionValue) { + optionValue = false; + } + options.fields[field]['validators'][v][optionName] = optionValue; + } + } + } + } + }); + + this.options = $.extend(true, this.options, options); + if ('string' == typeof this.options.excluded) { + this.options.excluded = $.map(this.options.excluded.split(','), function(item) { + // Trim the spaces + return $.trim(item); + }); + } + + for (var field in this.options.fields) { + this._initField(field); + } + + this.setLiveMode(this.options.live); + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + var fields = this.getFieldElements(field); + + // We don't need to validate non-existing fields + if (fields == null) { + delete this.options.fields[field]; + return; + } + for (var validatorName in this.options.fields[field].validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + delete this.options.fields[field].validators[validatorName]; + } + } + + var that = this, + type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent, + total = fields.length, + updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type); + + for (var i = 0; i < total; i++) { + var $field = $(fields[i]), + $parent = $field.parents('.form-group'), + // Allow user to indicate where the error messages are shown + $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field); + + // Set the attribute to indicate the fields which are defined by selector + if (!$field.attr('data-bv-field')) { + $field.attr('data-bv-field', field); + } + + // Whenever the user change the field value, mark it as not validated yet + $field.on(event + '.update.bv', function() { + // Reset the flag + that._submitIfValid = false; + updateAll ? that.updateStatus(field, that.STATUS_NOT_VALIDATED, null) + : that.updateElementStatus($(this), that.STATUS_NOT_VALIDATED, null); + }); + + // Create help block elements for showing the error messages + $field.data('bv.messages', $message); + for (validatorName in this.options.fields[field].validators) { + $field.data('bv.result.' + validatorName, this.STATUS_NOT_VALIDATED); + + if (!updateAll || i == total - 1) { + $('') + .css('display', 'none') + .attr('data-bv-validator', validatorName) + .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message) + .addClass('help-block') + .appendTo($message); + } + } + + // Prepare the feedback icons + // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation) + if (this.options.feedbackIcons + && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid + && (!updateAll || i == total - 1)) + { + $parent.addClass('has-feedback'); + var $icon = $('').css('display', 'none').addClass('form-control-feedback').attr('data-bv-field', field).insertAfter($field); + // The feedback icon does not render correctly if there is no label + // https://github.com/twbs/bootstrap/issues/12873 + if ($parent.find('label').length == 0) { + $icon.css('top', 0); + } + } + } + + if (this.options.fields[field]['enabled'] == null) { + this.options.fields[field]['enabled'] = true; + } + }, + + /** + * Get the element to place the error messages + * + * @param {jQuery} $field The field element + * @returns {jQuery} + */ + _getMessageContainer: function($field) { + var $parent = $field.parent(); + if ($parent.hasClass('form-group')) { + return $parent; + } + + var cssClasses = $parent.attr('class'); + if (!cssClasses) { + return this._getMessageContainer($parent); + } + + cssClasses = cssClasses.split(' '); + var n = cssClasses.length; + for (var i = 0; i < n; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i]) || /^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + return $parent; + } + } + + return this._getMessageContainer($parent); + }, + + /** + * Called when all validations are completed + */ + _submit: function() { + if (!this.isValid()) { + if ('submitted' == this.options.live) { + this.setLiveMode('enabled'); + } + + // Focus to the first invalid field + if (this.$invalidField) { + // Activate the tab containing the invalid field if exists + var $tab = this.$invalidField.parents('.tab-pane'), + tabId; + if ($tab && (tabId = $tab.attr('id'))) { + $('a[href="#' + tabId + '"][data-toggle="tab"]').trigger('click.bs.tab.data-api'); + } + + this.$invalidField.focus(); + } + + return; + } + + // Call the custom submission if enabled + if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + // If you want to submit the form inside your submit handler, please call defaultSubmit() method + this.options.submitHandler.call(this, this, this.$form, this.$submitButton); + } else { + this.disableSubmitButtons(true).defaultSubmit(); + } + }, + + /** + * Check if the field is excluded. + * Returning true means that the field will not be validated + * + * @param {jQuery} $field The field element + * @return {Boolean} + */ + _isExcluded: function($field) { + if (this.options.excluded) { + for (var i in this.options.excluded) { + if (('string' == typeof this.options.excluded[i] && $field.is(this.options.excluded[i])) + || ('function' == typeof this.options.excluded[i] && this.options.excluded[i].call(this, $field, this) == true)) + { + return true; + } + } + } + + return false; + }, + + // --- Public methods --- + + /** + * Retrieve the field elements by given name + * + * @param {String} field The field name + * @returns {null|jQuery[]} + */ + getFieldElements: function(field) { + var fields = this.options.fields[field].selector ? $(this.options.fields[field].selector) : this.$form.find('[name="' + field + '"]'); + return (fields.length == 0) ? null : fields; + }, + + /** + * Set live validating mode + * + * @param {String} mode Live validating mode. Can be 'enabled', 'disabled', 'submitted' + * @returns {BootstrapValidator} + */ + setLiveMode: function(mode) { + this.options.live = mode; + if ('submitted' == mode) { + return this; + } + + var that = this; + for (var field in this.options.fields) { + (function(f) { + var fields = that.getFieldElements(f); + if (fields) { + var type = fields.attr('type'), + total = fields.length, + updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type), + trigger = that.options.fields[field].trigger + || that.options.trigger + || (('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent), + events = $.map(trigger.split(' '), function(item) { + return item + '.live.bv'; + }).join(' '); + + for (var i = 0; i < total; i++) { + ('enabled' == mode) + ? $(fields[i]).on(events, function() { + updateAll ? that.validateField(f) : that.validateFieldElement($(this), false); + }) + : $(fields[i]).off(events); + } + } + })(field); + } + + return this; + }, + + /** + * Disable/enable submit buttons + * + * @param {Boolean} disabled Can be true or false + * @returns {BootstrapValidator} + */ + disableSubmitButtons: function(disabled) { + if (!disabled) { + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + } else if (this.options.live != 'disabled') { + // Don't disable if the live validating mode is disabled + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + } + + return this; + }, + + /** + * Validate the form + * + * @return {BootstrapValidator} + */ + validate: function() { + if (!this.options.fields) { + return this; + } + this.disableSubmitButtons(true); + + for (var field in this.options.fields) { + this.validateField(field); + } + + // Check if whether the submit button is clicked + if (this.$submitButton) { + this._submit(); + } + + return this; + }, + + /** + * Validate given field + * + * @param {String} field The field name + * @returns {BootstrapValidator} + */ + validateField: function(field) { + var fields = this.getFieldElements(field), + type = fields.attr('type'), + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (var i = 0; i < n; i++) { + this.validateFieldElement($(fields[i]), (n == 1)); + } + + return this; + }, + + /** + * Validate field element + * + * @param {jQuery} $field The field element + * @param {Boolean} updateAll If true, update status of all elements which have the same name + * @returns {BootstrapValidator} + */ + validateFieldElement: function($field, updateAll) { + var that = this, + field = $field.attr('data-bv-field'), + validators = this.options.fields[field].validators, + validatorName, + validateResult; + + if (!this.options.fields[field]['enabled'] || this._isExcluded($field)) { + return this; + } + + for (validatorName in validators) { + if ($field.data('bv.dfs.' + validatorName)) { + $field.data('bv.dfs.' + validatorName).reject(); + } + + // Don't validate field if it is already done + var result = $field.data('bv.result.' + validatorName); + if (result == this.STATUS_VALID || result == this.STATUS_INVALID) { + continue; + } + + $field.data('bv.result.' + validatorName, this.STATUS_VALIDATING); + validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]); + + if ('object' == typeof validateResult) { + updateAll ? this.updateStatus(field, this.STATUS_VALIDATING, validatorName) + : this.updateElementStatus($field, this.STATUS_VALIDATING, validatorName); + $field.data('bv.dfs.' + validatorName, validateResult); + + validateResult.done(function($f, v, isValid) { + // v is validator name + $f.removeData('bv.dfs.' + v); + updateAll ? that.updateStatus($f.attr('data-bv-field'), isValid ? that.STATUS_VALID : that.STATUS_INVALID, v) + : that.updateElementStatus($f, isValid ? that.STATUS_VALID : that.STATUS_INVALID, v); + + if (isValid && that._submitIfValid == true) { + // If a remote validator returns true and the form is ready to submit, then do it + that._submit(); + } + }); + } else if ('boolean' == typeof validateResult) { + updateAll ? this.updateStatus(field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName) + : this.updateElementStatus($field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName); + } + } + + return this; + }, + + /** + * Update all validating results of elements which have the same field name + * + * @param {String} field The field name + * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateStatus: function(field, status, validatorName) { + var fields = this.getFieldElements(field), + type = fields.attr('type'), + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (var i = 0; i < n; i++) { + this.updateElementStatus($(fields[i]), status, validatorName); + } + + return this; + }, + + /** + * Update validating result of given element + * + * @param {jQuery} $field The field element + * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateElementStatus: function($field, status, validatorName) { + var that = this, + field = $field.attr('data-bv-field'), + $parent = $field.parents('.form-group'), + $message = $field.data('bv.messages'), + $rowErrors = $parent.find('.help-block[data-bv-validator]'), + $errors = $message.find('.help-block[data-bv-validator]'), + $icon = $parent.find('.form-control-feedback[data-bv-field="' + field + '"]'); + + // Update status + if (validatorName) { + $field.data('bv.result.' + validatorName, status); + } else { + for (var v in this.options.fields[field].validators) { + $field.data('bv.result.' + v, status); + } + } + + // Show/hide error elements and feedback icons + switch (status) { + case this.STATUS_VALIDATING: + this.disableSubmitButtons(true); + $parent.removeClass('has-success').removeClass('has-error'); + // TODO: Show validating message + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(); + } + break; + + case this.STATUS_INVALID: + this.disableSubmitButtons(true); + $parent.removeClass('has-success').addClass('has-error'); + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').show() : $errors.show(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(); + } + break; + + case this.STATUS_VALID: + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + + // If the field is valid (passes all validators) + var validField = ($errors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || ($field.data('bv.result.' + v) != that.STATUS_VALID); + }).length == 0); + this.disableSubmitButtons(validField ? false : true); + if ($icon) { + $icon + .removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid) + .addClass(validField ? this.options.feedbackIcons.valid : this.options.feedbackIcons.invalid) + .show(); + } + + // Check if all fields in the same row are valid + var validRow = ($rowErrors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || ($field.data('bv.result.' + v) != that.STATUS_VALID); + }).length == 0); + $parent.removeClass('has-error has-success').addClass(validRow ? 'has-success' : 'has-error'); + break; + + case this.STATUS_NOT_VALIDATED: + default: + this.disableSubmitButtons(false); + $parent.removeClass('has-success').removeClass('has-error'); + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide(); + } + break; + } + + return this; + }, + + /** + * Check the form validity + * + * @returns {Boolean} + */ + isValid: function() { + var fields, field, $field, + type, status, validatorName, + n, i; + for (field in this.options.fields) { + if (this.options.fields[field] == null || !this.options.fields[field]['enabled']) { + continue; + } + + fields = this.getFieldElements(field); + type = fields.attr('type'); + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (i = 0; i < n; i++) { + $field = $(fields[i]); + if (this._isExcluded($field)) { + continue; + } + + for (validatorName in this.options.fields[field].validators) { + status = $field.data('bv.result.' + validatorName); + if (status == this.STATUS_NOT_VALIDATED || status == this.STATUS_VALIDATING) { + return false; + } + + if (status == this.STATUS_INVALID) { + this.$invalidField = $field; + return false; + } + } + } + } + + return true; + }, + + /** + * Submit the form using default submission. + * It also does not perform any validations when submitting the form + * + * It might be used when you want to submit the form right inside the submitHandler() + */ + defaultSubmit: function() { + this.$form.off('submit.bv').submit(); + }, + + // Useful APIs which aren't used internally + + /** + * Reset the form + * + * @param {Boolean} resetFormData Reset current form data + * @return {BootstrapValidator} + */ + resetForm: function(resetFormData) { + var field, fields, total, type, validator; + for (field in this.options.fields) { + fields = this.getFieldElements(field); + total = fields.length; + + for (var i = 0; i < total; i++) { + for (validator in this.options.fields[field].validators) { + $(fields[i]).removeData('bv.dfs.' + validator); + } + } + + // Mark field as not validated yet + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + if (resetFormData) { + type = fields.attr('type'); + ('radio' == type || 'checkbox' == type) ? fields.removeAttr('checked').removeAttr('selected') : fields.val(''); + } + } + + this.$invalidField = null; + this.$submitButton = null; + + // Enable submit buttons + this.disableSubmitButtons(false); + + return this; + }, + + /** + * Enable/Disable all validators to given field + * + * @param {String} field The field name + * @param {Boolean} enabled Enable/Disable field validators + * @return {BootstrapValidator} + */ + enableFieldValidators: function(field, enabled) { + this.options.fields[field]['enabled'] = enabled; + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + return this; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(option, params) { + return this.each(function() { + var $this = $(this), + data = $this.data('bootstrapValidator'), + options = 'object' == typeof option && option; + if (!data) { + data = new BootstrapValidator(this, options); + $this.data('bootstrapValidator', data); + } + + // Allow to call plugin method + if ('string' == typeof option) { + data[option](params); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; + + // Helper methods, which can be used in validator class + $.fn.bootstrapValidator.helpers = { + /** + * Implement Luhn validation algorithm ((http://en.wikipedia.org/wiki/Luhn)) + * Credit to https://gist.github.com/ShirtlessKirk/2134376 + * + * @param {String} value + * @returns {boolean} + */ + luhn: function(value) { + var length = value.length, + mul = 0, + prodArr = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]], + sum = 0; + + while (length--) { + sum += prodArr[mul][parseInt(value.charAt(length), 10)]; + mul ^= 1; + } + + return (sum % 10 === 0 && sum > 0); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.base64 = { + /** + * Return true if the input value is a base 64 encoded string. + * + * @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; + } + + return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + if ('range' == $field.attr('type')) { + return { + min: $field.attr('min'), + max: $field.attr('max') + }; + } + + return false; + }, + + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = parseFloat(value); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {Boolean|Deferred} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (options.callback && 'function' == typeof options.callback) { + var dfd = new $.Deferred(); + dfd.resolve($field, 'callback', options.callback.call(this, value, validator)); + return dfd; + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.choice = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max' + }, + + /** + * Check if the number of checked boxes are less or more than a given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var numChoices = $field.is('select') + ? validator.getFieldElements($field.attr('data-bv-field')).find('option').filter(':selected').length + : validator.getFieldElements($field.attr('data-bv-field')).filter(':checked').length; + if ((options.min && numChoices < options.min) || (options.max && numChoices > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + value = value.replace(/\D/g, ''); + + if (!$.fn.bootstrapValidator.helpers.luhn(value)) { + return false; + } + + // Validate the card number based on prefix (IIN ranges) and length + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + + var type, i; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (value.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(value.length) != -1) // and length + { + return true; + } + } + } + + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.cvv = { + html5Attributes: { + message: 'message', + ccfield: 'creditCardField' + }, + + /** + * Return true if the input value is a valid CVV number. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - creditCardField: The credit card number field. It can be null + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^[0-9]{3,4}$/.test(value)) { + return false; + } + + if (!options.creditCardField) { + return true; + } + + // Get the credit card number + var creditCard = validator.getFieldElements(options.creditCardField).val(); + if (creditCard == '') { + return true; + } + + // Supported credit card types + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + var type, i, creditCardType = null; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (creditCard.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(creditCard.length) != -1) // and length + { + creditCardType = type; + break; + } + } + } + + return (creditCardType == null) + ? false + : (('AMERICAN_EXPRESS' == creditCardType) ? (value.length == 4) : (value.length == 3)); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.date = { + html5Attributes: { + message: 'message', + format: 'format' + }, + + /** + * Return true if the input value is valid date + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - format: The date format. Default is MM/DD/YYYY + * Support the following formats: + * YYYY/DD/MM + * YYYY/DD/MM h:m A + * YYYY/MM/DD + * YYYY/MM/DD h:m A + * + * YYYY-DD-MM + * YYYY-DD-MM h:m A + * YYYY-MM-DD + * YYYY-MM-DD h:m A + * + * MM/DD/YYYY + * MM/DD/YYYY h:m A + * DD/MM/YYYY + * DD/MM/YYYY h:m A + * + * MM-DD-YYYY + * MM-DD-YYYY h:m A + * DD-MM-YYYY + * DD-MM-YYYY h:m A + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + // Determine the separator + options.format = options.format || 'MM/DD/YYYY'; + var separator = (options.format.indexOf('/') != -1) + ? '/' + : ((options.format.indexOf('-') != -1) ? '-' : null); + if (separator == null) { + return false; + } + + var month, day, year, minutes = null, hours = null, matches; + switch (true) { + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/DD/MM'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-DD-MM'): + year = matches[1]; day = matches[2]; month = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'DD/MM/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'DD-MM-YYYY'): + day = matches[1]; month = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i)) && options.format == 'YYYY/MM/DD'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i)) && options.format == 'YYYY-MM-DD'): + year = matches[1]; month = matches[2]; day = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i)) && options.format == 'MM/DD/YYYY'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i)) && options.format == 'MM-DD-YYYY'): + month = matches[1]; day = matches[2]; year = matches[3]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/DD/MM h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-DD-MM h:m A'): + year = matches[1]; day = matches[2]; month = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD/MM/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'DD-MM-YYYY h:m A'): + day = matches[1]; month = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY/MM/DD h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'YYYY-MM-DD h:m A'): + year = matches[1]; month = matches[2]; day = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + case (separator == '/' && (matches = value.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM/DD/YYYY h:m A'): + case (separator == '-' && (matches = value.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i)) && options.format == 'MM-DD-YYYY h:m A'): + month = matches[1]; day = matches[2]; year = matches[3]; hours = matches[4]; minutes = matches[5]; + break; + + default: + return false; + } + + // Validate hours and minutes + if (hours && minutes) { + hours = parseInt(hours, 10); + minutes = parseInt(minutes, 10); + if (hours < 1 || hours > 12 || minutes < 0 || minutes > 59) { + return false; + } + } + + // Validate day, month, and year + day = parseInt(day, 10); + month = parseInt(month, 10); + year = parseInt(year, 10); + + if (year < 1000 || year > 9999 || month == 0 || month > 12) { + return false; + } + + var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + // Update the number of days in Feb of leap year + if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) { + numDays[1] = 29; + } + + // Check the day + return (day > 0 && day <= numDays[month - 1]); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.different = { + html5Attributes: { + message: 'message', + field: 'field' + }, + + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value != compareWith.val()) { + validator.updateStatus(options.field, validator.STATUS_VALID, 'different'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^\d+$/.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + enableByHtml5: function($field) { + return ('email' == $field.attr('type')); + }, + + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.file = { + html5Attributes: { + extension: 'extension', + maxsize: 'maxSize', + message: 'message', + type: 'type' + }, + + /** + * Validate upload file. Use HTML 5 API if the browser supports + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - extension: The allowed extensions, separated by a comma + * - maxSize: The maximum size in bytes + * - message: The invalid message + * - type: The allowed MIME type, separated by a comma + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var ext, + extensions = options.extension ? options.extension.split(',') : null, + types = options.type ? options.type.split(',') : null, + html5 = (window.File && window.FileList && window.FileReader); + + if (html5) { + // Get FileList instance + var files = $field.get(0).files, + total = files.length; + for (var i = 0; i < total; i++) { + // Check file size + if (options.maxSize && files[i].size > parseInt(options.maxSize)) { + return false; + } + + // Check file extension + ext = files[i].name.substr(files[i].name.lastIndexOf('.') + 1); + if (extensions && extensions.indexOf(ext) == -1) { + return false; + } + + // Check file type + if (types && types.indexOf(files[i].type) == -1) { + return false; + } + } + } else { + // Check file extension + ext = value.substr(value.lastIndexOf('.') + 1); + if (extensions && extensions.indexOf(ext) == -1) { + return false; + } + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + html5Attributes: { + message: 'message', + value: 'value', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + var min = $field.attr('min'); + if (min) { + return { + value: min + }; + } + + return false; + }, + + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hex = { + /** + * Return true if and only if the input value is a valid hexadecimal number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^[0-9a-fA-F]+$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + enableByHtml5: function($field) { + return ('color' == $field.attr('type')); + }, + + /** + * Return true if the input value is a valid hex color + * + * @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; + } + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.iban = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Validate an International Bank Account Number (IBAN) + * To test it, take the sample IBAN from + * http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html + * + * @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 + * - country: The ISO 3166-1 country code + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // See + // http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf + // http://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country + var ibanRegex = { + '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 + }; + value = value.replace(/[^a-zA-Z0-9]/g, '').toUpperCase(); + var country = options.country || value.substr(0, 2); + if (!ibanRegex[country]) { + return false; + } + if (!(new RegExp('^' + ibanRegex[country] + '$')).test(value)) { + return false; + } + + value = value.substr(4) + value.substr(0, 4); + value = value.split('').map(function(n) { + var code = n.charCodeAt(0); + return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) + // Replace A, B, C, ..., Z with 10, 11, ..., 35 + ? (code - 'A'.charCodeAt(0) + 10) + : n; + }).join(''); + + var temp = parseInt(value.substr(0, 1), 10), + length = value.length; + for (var i = 1; i < length; ++i) { + temp = (temp * 10 + parseInt(value.substr(i, 1), 10)) % 97; + } + return (temp == 1); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + html5Attributes: { + message: 'message', + field: 'field' + }, + + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value == compareWith.val()) { + validator.updateStatus(options.field, validator.STATUS_VALID, 'identical'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.integer = { + enableByHtml5: function($field) { + return ('number' == $field.attr('type')); + }, + + /** + * Return true if the input value is an integer + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + return /^(?:-?(?:0|[1-9][0-9]*))$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.ip = { + html5Attributes: { + message: 'message', + ipv4: 'ipv4', + ipv6: 'ipv6' + }, + + /** + * Return true if the input value is a IP address. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - ipv4: Enable IPv4 validator, default to true + * - ipv6: Enable IPv6 validator, default to true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + options = $.extend({}, { ipv4: true, ipv6: true }, options); + + if (options.ipv4) { + return /^(?:(?: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); + } else if (options.ipv6) { + return /^\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(str); + } + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.isbn = { + /** + * Return true if the input value is a valid ISBN 10 or ISBN 13 number + * Examples: + * - Valid: + * ISBN 10: 99921-58-10-7, 9971-5-0210-0, 960-425-059-0, 80-902734-1-6, 85-359-0277-5, 1-84356-028-3, 0-684-84328-5, 0-8044-2957-X, 0-85131-041-9, 0-943396-04-2, 0-9752298-0-X + * ISBN 13: 978-0-306-40615-7 + * - Invalid: + * ISBN 10: 99921-58-10-6 + * ISBN 13: 978-0-306-40615-6 + * + * @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; + } + + // http://en.wikipedia.org/wiki/International_Standard_Book_Number#Overview + // Groups are separated by a hyphen or a space + var type; + switch (true) { + case /^\d{9}[\dX]$/.test(value): + case (value.length == 13 && /^(\d+)-(\d+)-(\d+)-([\dX])$/.test(value)): + case (value.length == 13 && /^(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(value)): + type = 'ISBN10'; + break; + case /^(978|979)\d{9}[\dX]$/.test(value): + case (value.length == 17 && /^(978|979)-(\d+)-(\d+)-(\d+)-([\dX])$/.test(value)): + case (value.length == 17 && /^(978|979)\s(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(value)): + type = 'ISBN13'; + break; + default: + return false; + } + + // Replace all special characters except digits and X + value = value.replace(/[^0-9X]/gi, ''); + var chars = value.split(''), + length = chars.length, + sum = 0, + checksum; + + switch (type) { + case 'ISBN10': + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += ((10 - i) * parseInt(chars[i])); + } + checksum = 11 - (sum % 11); + if (checksum == 11) { + checksum = 0; + } else if (checksum == 10) { + checksum = 'X'; + } + return (checksum + '' == chars[length - 1]); + + case 'ISBN13': + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += ((i % 2 == 0) ? parseInt(chars[i]) : (parseInt(chars[i]) * 3)); + } + checksum = 10 - (sum % 10); + if (checksum == 10) { + checksum = '0'; + } + return (checksum + '' == chars[length - 1]); + + default: + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + html5Attributes: { + message: 'message', + value: 'value', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + var max = $field.attr('max'); + if (max) { + return { + value: max + }; + } + + return false; + }, + + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === false) ? (value <= options.value) : (value < options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.mac = { + /** + * Return true if the input value is a MAC address. + * + * @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; + } + + return /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + enableByHtml5: function($field) { + var required = $field.attr('required') + ''; + return ('required' == required || 'true' == required); + }, + + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + if ('radio' == type || 'checkbox' == type) { + return validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length > 0; + } + + return $.trim($field.val()) != ''; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.numeric = { + /** + * Validate decimal number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return !isNaN(parseFloat(value)) && isFinite(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.phone = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Return true if the input value contains a valid US phone number only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166 country code + * Currently it only supports United State (US) country + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var country = (options.country || 'US').toUpperCase(); + switch (country) { + case 'US': + default: + // Make sure US phone numbers have 10 digits + // May start with 1, +1, or 1-; should discard + // Area code may be delimited with (), & sections may be delimited with . or - + // Test: http://regexr.com/38mqi + value = value.replace(/\D/g, ''); + return (/^(?:(1\-?)|(\+1 ?))?\(?(\d{3})[\)\-\.]?(\d{3})[\-\.]?(\d{4})$/).test(value) && (value.length == 10); + } + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + html5Attributes: { + message: 'message', + regexp: 'regexp' + }, + + enableByHtml5: function($field) { + var pattern = $field.attr('pattern'); + if (pattern) { + return { + regexp: pattern + }; + } + + return false; + }, + + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var regexp = ('string' == typeof options.regexp) ? new RegExp(options.regexp) : options.regexp; + return regexp.test(value); + } + }; +}(window.jQuery)); +;(function ($) { + $.fn.bootstrapValidator.validators.remote = { + html5Attributes: { + message: 'message', + url: 'url', + name: 'name' + }, + + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - name [optional]: Override the field name for the request. + * - message: The invalid message + * @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; + if (data == null) { + data = {}; + } + // Support dynamic data + if ('function' == typeof data) { + data = data.call(this, validator); + } + data[options.name || name] = value; + + var dfd = new $.Deferred(); + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }); + xhr.then(function(response) { + dfd.resolve($field, 'remote', response.valid === true || response.valid === 'true'); + }); + + dfd.fail(function() { + xhr.abort(); + }); + + return dfd; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.siren = { + /** + * Check if a string is a siren number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^\d{9}$/.test(value)) { + return false; + } + return $.fn.bootstrapValidator.helpers.luhn(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.siret = { + /** + * Check if a string is a siret number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var sum = 0, + length = value.length, + tmp; + for (var i = 0; i < length; i++) { + tmp = parseInt(value.charAt(i), 10); + if ((i % 2) == 0) { + tmp = tmp * 2; + if (tmp > 9) { + tmp -= 9; + } + } + sum += tmp; + } + return (sum % 10 == 0); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.step = { + html5Attributes: { + message: 'message', + base: 'baseValue', + step: 'step' + }, + + /** + * Return true if the input value is valid step one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - baseValue: The base value + * - step: The step + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options = $.extend({}, { baseValue: 0, step: 1 }, options); + value = parseFloat(value); + if (isNaN(value) || !isFinite(value)) { + return false; + } + + var round = function(x, precision) { + var m = Math.pow(10, precision); + x = x * m; + var sign = (x > 0) | -(x < 0), + isHalf = (x % 1 === 0.5 * sign); + if (isHalf) { + return (Math.floor(x) + (sign > 0)) / m; + } else { + return Math.round(x) / m; + } + }, + floatMod = function(x, y) { + if (y == 0.0) { + return 1.0; + } + var dotX = (x + '').split('.'), + dotY = (y + '').split('.'), + precision = ((dotX.length == 1) ? 0 : dotX[1].length) + ((dotY.length == 1) ? 0 : dotY[1].length); + return round(x - y * Math.floor(x / y), precision); + }; + + var mod = floatMod(value - options.baseValue, options.step); + return (mod == 0.0 || mod == options.step); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringCase = { + html5Attributes: { + message: 'message', + 'case': 'case' + }, + + /** + * Check if a string is a lower or upper case one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - case: Can be 'lower' (default) or 'upper' + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var stringCase = (options['case'] || 'lower').toLowerCase(); + switch (stringCase) { + case 'upper': + return value === value.toUpperCase(); + case 'lower': + default: + return value === value.toLowerCase(); + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max' + }, + + enableByHtml5: function($field) { + var maxLength = $field.attr('maxlength'); + if (maxLength) { + return { + max: parseInt(maxLength, 10) + }; + } + + return false; + }, + + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var length = $.trim(value).length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + enableByHtml5: function($field) { + return ('url' == $field.attr('type')); + }, + + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uuid = { + html5Attributes: { + message: 'message', + version: 'version' + }, + + /** + * Return true if and only if the input value is a valid UUID string + * + * @see http://en.wikipedia.org/wiki/Universally_unique_identifier + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - version: Can be 3, 4, 5, null + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // See the format at http://en.wikipedia.org/wiki/Universally_unique_identifier#Variants_and_versions + var patterns = { + '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, + '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i + }, + version = options.version ? (options.version + '') : 'all'; + return (null == patterns[version]) ? true : patterns[version].test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.vat = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Validate an European VAT number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166-1 country code + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var country = options.country || value.substr(0, 2), + method = ['_', country.toLowerCase()].join(''); + if (this[method] && 'function' == typeof this[method]) { + return this[method](value); + } + + return true; + }, + + // VAT validators + + /** + * Validate Austrian VAT number + * Example: + * - Valid: ATU13585627 + * - Invalid: ATU13585626 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _at: function(value) { + if (!/^ATU[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(3); + var sum = 0, + weight = [1, 2, 1, 2, 1, 2, 1], + temp = 0; + + for (var i = 0; i < 7; i++) { + temp = parseInt(value.charAt(i)) * weight[i]; + if (temp > 9) { + temp = Math.floor(temp / 10) + temp % 10; + } + sum += temp; + } + + sum = 10 - (sum + 4) % 10; + if (sum == 10) { + sum = 0; + } + + return (sum == value.substr(7, 1)); + }, + + /** + * Validate Belgian VAT number + * Example: + * - Valid: BE0428759497 + * - Invalid: BE431150351 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _be: function(value) { + if (!/^BE[0]{0,1}[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + if (value.length == 9) { + value = '0' + value; + } + + if (value.substr(1, 1) == 0) { + return false; + } + + var sum = parseInt(value.substr(0, 8), 10) + parseInt(value.substr(8, 2), 10); + return (sum % 97 == 0); + }, + + /** + * Validate Bulgarian VAT number + * Example: + * - Valid: BG175074752, + * BG7523169263, BG8032056031, + * BG7542011030, + * BG7111042925 + * - Invalid: BG175074753, BG7552A10004, BG7111042922 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _bg: function(value) { + if (!/^BG[0-9]{9,10}$/.test(value)) { + return false; + } + + value = value.substr(2); + + var total = 0, sum = 0, weight = [], i = 0; + + // Legal entities + if (value.length == 9) { + for (i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * (i + 1); + } + sum = sum % 11; + if (sum == 10) { + sum = 0; + for (i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * (i + 3); + } + } + sum = sum % 10; + return (sum == value.substr(8)); + } + // Physical persons, foreigners and others + else if (value.length == 10) { + // Validate Bulgarian national identification numbers + var egn = function(value) { + // Check the birth date + var year = parseInt(value.substr(0, 2), 10) + 1900, + month = parseInt(value.substr(2, 2), 10), + day = parseInt(value.substr(4, 2), 10); + if (month > 40) { + year += 100; + month -= 40; + } else if (month > 20) { + year -= 100; + month -= 20; + } + + try { + var d = new Date(year, month, day); + } catch (ex) { + return false; + } + + var sum = 0, + weight = [2, 4, 8, 5, 10, 9, 7, 3, 6]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = (sum % 11) % 10; + return (sum == value.substr(9, 1)); + }, + // Validate Bulgarian personal number of a foreigner + pnf = function(value) { + var sum = 0, + weight = [21, 19, 17, 13, 11, 9, 7, 3, 1]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 10; + return (sum == value.substr(9, 1)); + }, + // Finally, consider it as a VAT number + vat = function(value) { + var sum = 0, + weight = [4, 3, 2, 7, 6, 5, 4, 3, 2]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = 11 - sum % 11; + if (sum == 10) { + return false; + } + if (sum == 11) { + sum = 0; + } + return (sum == value.substr(9, 1)); + }; + return (egn(value) || pnf(value) || vat(value)); + } + + return false; + }, + + /** + * Validate Swiss VAT number + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ch: function(value) { + if (!/^CHE[0-9]{9}(MWST)?$/.test(value)) { + return false; + } + + value = value.substr(3); + var sum = 0, + weight = [5, 4, 3, 2, 7, 6, 5, 4]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i), 10) * weight[i]; + } + + sum = 11 - sum % 11; + if (sum == 10) { + return false; + } + if (sum == 11) { + sum = 0; + } + + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Cypriot VAT number + * Examples: + * - Valid: CY10259033P + * - Invalid: CY10259033Z + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _cy: function(value) { + if (!/^CY[0-5|9]{1}[0-9]{7}[A-Z]{1}$/.test(value)) { + return false; + } + + value = value.substr(2); + + // Do not allow to start with "12" + if (value.substr(0, 2) == '12') { + return false; + } + + // Extract the next digit and multiply by the counter. + var sum = 0, + translation = { + '0': 1, '1': 0, '2': 5, '3': 7, '4': 9, + '5': 13, '6': 15, '7': 17, '8': 19, '9': 21 + }; + for (var i = 0; i < 8; i++) { + var temp = parseInt(value.charAt(i), 10); + if (i % 2 == 0) { + temp = translation[temp + '']; + } + sum += temp; + } + + sum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[sum % 26]; + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Czech Republic VAT number + * Can be: + * i) Legal entities (8 digit numbers) + * ii) Individuals with a RC (the 9 or 10 digit Czech birth number) + * iii) Individuals without a RC (9 digit numbers beginning with 6) + * + * Examples: + * - Valid: i) CZ25123891; ii) CZ7103192745, CZ991231123; iii) CZ640903926 + * - Invalid: i) CZ25123890; ii) CZ1103492745, CZ590312123 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _cz: function(value) { + if (!/^CZ[0-9]{8,10}$/.test(value)) { + return false; + } + + value = value.substr(2); + + var sum = 0, + i = 0; + if (value.length == 8) { + // Do not allow to start with '9' + if (value.charAt(0) + '' == '9') { + return false; + } + + sum = 0; + for (i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i), 10) * (8 - i); + } + sum = 11 - sum % 11; + if (sum == 10) { + sum = 0; + } + if (sum == 11) { + sum = 1; + } + + return (sum == value.substr(7, 1)); + } else if (value.length == 9 && (value.charAt(0) + '' == '6')) { + sum = 0; + // Skip the first (which is 6) + for (i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i + 1), 10) * (8 - i); + } + sum = 11 - sum % 11; + if (sum == 10) { + sum = 0; + } + if (sum == 11) { + sum = 1; + } + sum = [8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 10][sum - 1]; + return (sum == value.substr(8, 1)); + } else if (value.length == 9 || value.length == 10) { + // Validate Czech birth number (Rodné číslo), which is also national identifier + var year = 1900 + parseInt(value.substr(0, 2)), + month = parseInt(value.substr(2, 2)) % 50 % 20, + day = parseInt(value.substr(4, 2)); + if (value.length == 9) { + if (year >= 1980) { + year -= 100; + } + if (year > 1953) { + return false; + } + } else if (year < 1954) { + year += 100; + } + + try { + var d = new Date(year, month, day); + } catch (ex) { + return false; + } + + // Check that the birth date is not in the future + if (value.length == 10) { + var check = parseInt(value.substr(0, 9), 10) % 11; + if (year < 1985) { + check = check % 10; + } + return (check == value.substr(9, 1)); + } + + return true; + } + + return false; + }, + + /** + * Validate German VAT number + * Examples: + * - Valid: DE136695976 + * - Invalid: DE136695978 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _de: function(value) { + if (!/^DE[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + var product = 10, + sum = 0; + for (var i = 0; i < 8; i++) { + sum = (parseInt(value.charAt(i), 10) + product) % 10; + if (sum == 0) { + sum = 10; + } + product = (sum * 2) % 11; + } + + var checkDigit = (11 - product == 10) ? 0 : (11 - product); + return (checkDigit == value.substr(8, 1)); + }, + + /** + * Validate Danish VAT number + * Example: + * - Valid: DK13585628 + * - Invalid: DK13585627 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _dk: function(value) { + if (!/^DK[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [2, 7, 6, 5, 4, 3, 2, 1]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i), 10) * weight[i]; + } + + return (sum % 11 == 0); + }, + + /** + * Validate Estonian VAT number + * Examples: + * - Valid: EE100931558, EE100594102 + * - Invalid: EE100594103 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ee: function(value) { + if (!/^EE[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [3, 7, 1, 3, 7, 1, 3, 7, 1]; + + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 10 == 0); + }, + + /** + * Validate Spanish VAT number (NIF - Número de Identificación Fiscal) + * Can be: + * i) DNI (Documento nacional de identidad), for Spaniards + * ii) NIE (Número de Identificación de Extranjeros), for foreigners + * iii) CIF (Certificado de Identificación Fiscal), for legal entities and others + * + * Examples: + * - Valid: i) ES54362315K; ii) ESX2482300W, ESX5253868R; iii) ESM1234567L, ESJ99216582, ESB58378431, ESB64717838 + * - Invalid: i) ES54362315Z; ii) ESX2482300A; iii) ESJ99216583 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _es: function(value) { + if (!/^ES[0-9A-Z][0-9]{7}[0-9A-Z]$/.test(value)) { + return false; + } + + value = value.substr(2); + var dni = function(value) { + var check = parseInt(value.substr(0, 8), 10); + check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; + return (check == value.substr(8, 1)); + }, + nie = function(value) { + var check = ['XYZ'.indexOf(value.charAt(0)), value.substr(1)].join(''); + check = parseInt(check, 10); + check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; + return (check == value.substr(8, 1)); + }, + cif = function(value) { + var first = value.charAt(0), check; + if ('KLM'.indexOf(first) != -1) { + // K: Spanish younger than 14 year old + // L: Spanish living outside Spain without DNI + // M: Granted the tax to foreigners who have no NIE + check = parseInt(value.substr(1, 8), 10); + check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; + return (check == value.substr(8, 1)); + } else if ('ABCDEFGHJNPQRSUVW'.indexOf(first) != -1) { + var sum = 0, + weight = [2, 1, 2, 1, 2, 1, 2], + temp = 0; + + for (var i = 0; i < 7; i++) { + temp = parseInt(value.charAt(i + 1)) * weight[i]; + if (temp > 9) { + temp = Math.floor(temp / 10) + temp % 10; + } + sum += temp; + } + sum = 10 - sum % 10; + return (sum == value.substr(8, 1) || 'JABCDEFGHI'[sum] == value.substr(8, 1)); + } + + return false; + }; + + var first = value.charAt(0); + if (/^[0-9]$/.test(first)) { + return dni(value); + } else if (/^[XYZ]$/.test(first)) { + return nie(value); + } else { + return cif(value); + } + }, + + /** + * Validate Finnish VAT number + * Examples: + * - Valid: FI20774740 + * - Invalid: FI20774741 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _fi: function(value) { + if (!/^FI[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [7, 9, 10, 5, 8, 4, 2, 1]; + + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 11 == 0); + }, + + /** + * Validate French VAT number (TVA - taxe sur la valeur ajoutée) + * It's constructed by a SIREN number, prefixed by two characters. + * + * Examples: + * - Valid: FR40303265045, FR23334175221, FRK7399859412, FR4Z123456782 + * - Invalid: FR84323140391 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _fr: function(value) { + if (!/^FR[0-9A-Z]{2}[0-9]{9}$/.test(value)) { + return false; + } + + value = 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 + return value.substr(0, 2) == (parseInt(value.substr(2) + '12', 10) % 97); + } else { + // The first characters cann't be O and I + var alphabet = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ', + check; + // First one is digit + if (/^[0-9]{1}$/.test(value.charAt(0))) { + check = alphabet.indexOf(value.charAt(0)) * 24 + alphabet.indexOf(value.charAt(1)) - 10; + } else { + check = alphabet.indexOf(value.charAt(0)) * 34 + alphabet.indexOf(value.charAt(1)) - 100; + } + return ((parseInt(value.substr(2), 10) + 1 + Math.floor(check / 11)) % 11) == (check % 11); + } + }, + + /** + * Validate United Kingdom VAT number + * Example: + * - Valid: GB980780684 + * - Invalid: GB802311781 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _gb: function(value) { + if (!/^GB[0-9]{9}$/.test(value) // Standard + && !/^GB[0-9]{12}$/.test(value) // Branches + && !/^GBGD[0-9]{3}$/.test(value) // Government department + && !/^GBHA[0-9]{3}$/.test(value) // Health authority + && !/^GB(GD|HA)8888[0-9]{5}$/.test(value)) + { + return false; + } + + value = value.substr(2); + var length = value.length; + if (length == 5) { + var firstTwo = value.substr(0, 2), + lastThree = parseInt(value.substr(2)); + return ('GD' == firstTwo && lastThree < 500) || ('HA' == firstTwo && lastThree >= 500); + } else if (length == 11 && ('GD8888' == value.substr(0, 6) || 'HA8888' == value.substr(0, 6))) { + if (('GD' == value.substr(0, 2) && parseInt(value.substr(6, 3)) >= 500) + || ('HA' == value.substr(0, 2) && parseInt(value.substr(6, 3)) < 500)) + { + return false; + } + return (parseInt(value.substr(6, 3)) % 97 == parseInt(value.substr(9, 2))); + } else if (length == 9 || length == 12) { + var sum = 0, + weight = [8, 7, 6, 5, 4, 3, 2, 10, 1]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 97; + + if (parseInt(value.substr(0, 3)) >= 100) { + return (sum == 0 || sum == 42 || sum == 55); + } else { + return (sum == 0); + } + } + + return true; + }, + + /** + * Validate Greek VAT number + * Examples: + * - Valid: GR023456780, EL094259216 + * - Invalid: EL123456781 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _gr: function(value) { + if (!/^GR[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + if (value.length == 8) { + value = '0' + value; + } + + var sum = 0, + weight = [256, 128, 64, 32, 16, 8, 4, 2]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = (sum % 11) % 10; + + return (sum == value.substr(8, 1)); + }, + + // EL is traditionally prefix of Greek VAT numbers + _el: function(value) { + if (!/^EL[0-9]{9}$/.test(value)) { + return false; + } + + value = 'GR' + value.substr(2); + return this._gr(value); + }, + + /** + * Validate Hungarian VAT number + * Examples: + * - Valid: HU12892312 + * - Invalid: HU12892313 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _hu: function(value) { + if (!/^HU[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [9, 7, 3, 1, 9, 7, 3, 1]; + + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 10 == 0); + }, + + /** + * Validate Croatian VAT number + * Examples: + * - Valid: HR33392005961 + * - Invalid: HR33392005962 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _hr: function(value) { + if (!/^HR[0-9]{11}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 10, + temp = 0; + + for (var i = 0; i < 10; i++) { + temp = (parseInt(value.charAt(i), 10) + sum) % 10; + if (temp == 0) { + temp = 10; + } + sum = (temp * 2) % 11; + } + sum += parseInt(value.substr(10, 1), 10); + return (sum % 10 == 1); + }, + + /** + * Validate Irish VAT number + * Examples: + * - Valid: IE6433435F, IE6433435OA, IE8D79739I + * - Invalid: IE8D79738J + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ie: function(value) { + if (!/^IE[0-9]{1}[0-9A-Z\*\+]{1}[0-9]{5}[A-Z]{1,2}$/.test(value)) { + return false; + } + + value = value.substr(2); + var getCheckDigit = function(value) { + while (value.length < 7) { + value = '0' + value; + } + var alphabet = 'WABCDEFGHIJKLMNOPQRSTUV', + sum = 0; + for (var i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i)) * (8 - i); + } + sum += 9 * alphabet.indexOf(value.substr(7)); + return alphabet[sum % 23]; + }; + + // The first 7 characters are digits + if (/^[0-9]+$/.test(value.substr(0, 7))) { + // New system + return value.charAt(7) == getCheckDigit(value.substr(0, 7) + value.substr(8) + ''); + } else if ('ABCDEFGHIJKLMNOPQRSTUVWXYZ+*'.indexOf(value.charAt(1)) != -1) { + // Old system + return value.charAt(7) == getCheckDigit(value.substr(2, 5) + value.substr(0, 1) + ''); + } + + return true; + }, + + /** + * 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 + * + * Examples: + * - Valid: IT00743110157 + * - Invalid: IT00743110158 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _it: function(value) { + if (!/^IT[0-9]{11}$/.test(value)) { + return false; + } + + value = value.substr(2); + if (parseInt(value.substr(0, 7)) == 0) { + return false; + } + + var lastThree = parseInt(value.substr(7, 3)); + if ((lastThree < 1) || (lastThree > 201) && lastThree != 999 && lastThree != 888) { + return false; + } + + return $.fn.bootstrapValidator.helpers.luhn(value); + }, + + /** + * Validate Lithuanian VAT number + * It can be: + * - 9 digits, for legal entities + * - 12 digits, for temporarily registered taxpayers + * + * Examples: + * - Valid: LT119511515, LT100001919017, LT100004801610 + * - Invalid: LT100001919018 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _lt: function(value) { + if (!/^LT([0-9]{7}1[0-9]{1}|[0-9]{10}1[0-9]{1})$/.test(value)) { + return false; + } + + value = value.substr(2); + var length = value.length, + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * (1 + i % 9); + } + var check = sum % 11; + if (check == 10) { + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * (1 + (i + 2) % 9); + } + } + check = check % 11 % 10; + return (check == value.charAt(length - 1)); + }, + + /** + * Validate Luxembourg VAT number + * Examples: + * - Valid: LU15027442 + * - Invalid: LU15027443 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _lu: function(value) { + if (!/^LU[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + return (value.substr(0, 6) % 89 == value.substr(6, 2)); + }, + + /** + * Validate Latvian VAT number + * Examples: + * - Valid: LV40003521600, LV16117519997 + * - Invalid: LV40003521601, LV16137519997 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _lv: function(value) { + if (!/^LV[0-9]{11}$/.test(value)) { + return false; + } + + value = value.substr(2); + var first = parseInt(value.charAt(0)), + sum = 0, + weight = [], + i = 0, + length = value.length; + if (first > 3) { + // Legal entity + sum = 0; + weight = [9, 1, 4, 8, 3, 10, 2, 5, 7, 6, 1]; + for (i = 0; i < length; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 11; + return (sum == 3); + } else { + // Check birth date + var day = parseInt(value.substr(0, 2)), + month = parseInt(value.substr(2, 2)), + year = parseInt(value.substr(4, 2)); + year = year + 1800 + parseInt(value.charAt(6)) * 100; + + try { + var d = new Date(year, month, day); + } catch (ex) { + return false; + } + + // Check personal code + sum = 0; + weight = [10, 5, 8, 4, 2, 1, 6, 3, 7, 9]; + for (i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = (sum + 1) % 11 % 10; + return (sum == value.charAt(length - 1)); + } + + return true; + }, + + /** + * Validate Maltese VAT number + * Examples: + * - Valid: MT11679112 + * - Invalid: MT11679113 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _mt: function(value) { + if (!/^MT[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [3, 4, 6, 7, 8, 9, 10, 1]; + + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 37 == 0); + }, + + /** + * Validate Dutch VAT number + * Examples: + * - Valid: NL004495445B01 + * - Invalid: NL123456789B90 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _nl: function(value) { + if (!/^NL[0-9]{9}B[0-9]{2}$/.test(value)) { + return false; + } + value = value.substr(2); + var sum = 0, + weight = [9, 8, 7, 6, 5, 4, 3, 2]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + sum = sum % 11; + if (sum > 9) { + sum = 0; + } + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Norwegian VAT number + * + * @see http://www.brreg.no/english/coordination/number.html + * @param {String} value VAT number + * @returns {Boolean} + */ + _no: function(value) { + if (!/^NO[0-9]{9}$/.test(value)) { + return false; + } + value = value.substr(2); + var sum = 0, + weight = [3, 2, 7, 6, 5, 4, 3, 2]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + sum = 11 - sum % 11; + if (sum == 11) { + sum = 0; + } + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Polish VAT number + * Examples: + * - Valid: PL8567346215 + * - Invalid: PL8567346216 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _pl: function(value) { + if (!/^PL[0-9]{10}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [6, 5, 7, 2, 3, 4, 5, 6, 7, -1]; + + for (var i = 0; i < 10; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 11 == 0); + }, + + /** + * Validate Portuguese VAT number + * Examples: + * - Valid: PT501964843 + * - Invalid: PT501964842 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _pt: function(value) { + if (!/^PT[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [9, 8, 7, 6, 5, 4, 3, 2]; + + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = 11 - sum % 11; + if (sum > 9) { + sum = 0; + } + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Romanian VAT number + * Examples: + * - Valid: RO18547290 + * - Invalid: RO18547291 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ro: function(value) { + if (!/^RO[1-9][0-9]{1,9}$/.test(value)) { + return false; + } + value = value.substr(2); + + var length = value.length, + weight = [7, 5, 3, 2, 1, 7, 5, 3, 2].slice(10 - length), + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + sum = (10 * sum) % 11 % 10; + return (sum == value.substr(length - 1, 1)); + }, + + /** + * Validate Russian VAT number (Taxpayer Identification Number - INN) + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ru: function(value) { + if (!/^RU([0-9]{9}|[0-9]{12})$/.test(value)) { + return false; + } + + value = value.substr(2); + if (value.length == 10) { + var sum = 0, + weight = [2, 4, 10, 3, 5, 9, 4, 6, 8, 0]; + for (var i = 0; i < 10; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 11; + if (sum > 9) { + sum = sum % 10; + } + + return (sum == value.substr(9, 1)); + } else if (value.length == 12) { + var sum1 = 0, + weight1 = [7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0], + sum2 = 0, + weight2 = [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0]; + + for (var i = 0; i < 11; i++) { + sum1 += parseInt(value.charAt(i)) * weight1[i]; + sum2 += parseInt(value.charAt(i)) * weight2[i]; + } + sum1 = sum1 % 11; + if (sum1 > 9) { + sum1 = sum1 % 10; + } + sum2 = sum2 % 11; + if (sum2 > 9) { + sum2 = sum2 % 10; + } + + return (sum1 == value.substr(10, 1) && sum2 == value.substr(11, 1)); + } + + return false; + }, + + /** + * Validate Serbian VAT number + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _rs: function(value) { + if (!/^RS[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 10, + temp = 0; + for (var i = 0; i < 8; i++) { + temp = (parseInt(value.charAt(i)) + sum) % 10; + if (temp == 0) { + temp = 10; + } + sum = (2 * temp) % 11; + } + + return ((sum + parseInt(value.substr(8, 1))) % 10 == 1); + }, + + /** + * Validate Swedish VAT number + * Examples: + * - Valid: SE123456789701 + * - Invalid: SE123456789101 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _se: function(value) { + if (!/^SE[0-9]{10}01$/.test(value)) { + return false; + } + + value = value.substr(2, 10); + return $.fn.bootstrapValidator.helpers.luhn(value); + }, + + /** + * Validate Slovenian VAT number + * Examples: + * - Valid: SI50223054 + * - Invalid: SI50223055 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _si: function(value) { + if (!/^SI[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [8, 7, 6, 5, 4, 3, 2]; + + for (var i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = 11 - sum % 11; + if (sum == 10) { + sum = 0; + } + return (sum == value.substr(7, 1)); + }, + + /** + * Validate Slovak VAT number + * Examples: + * - Valid: SK2022749619 + * - Invalid: SK2022749618 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _sk: function(value) { + if (!/^SK[1-9][0-9][(2-4)|(6-9)][0-9]{7}$/.test(value)) { + return false; + } + + value = value.substr(2); + return (value % 11 == 0); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.vin = { + /** + * Validate an US VIN (Vehicle Identification Number) + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Don't accept I, O, Q characters + if (!/^[a-hj-npr-z0-9]{8}[0-9xX][a-hj-npr-z0-9]{8}$/i.test(value)) { + return false; + } + + value = value.toUpperCase(); + var chars = { + A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8, + J: 1, K: 2, L: 3, M: 4, N: 5, P: 7, R: 9, + S: 2, T: 3, U: 4, V: 5, W: 6, X: 7, Y: 8, Z: 9, + '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '0': 0 + }, + weights = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2], + sum = 0, + length = value.length; + for (var i = 0; i < length; i++) { + sum += chars[value.charAt(i) + ''] * weights[i]; + } + + var reminder = sum % 11; + if (reminder == 10) { + reminder = 'X'; + } + + return reminder == value.charAt(8); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.zipCode = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Return true if and only if the input value is a valid country zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166 country code + * + * Currently it supports the following countries: + * - US (United State) + * - CA (Canada) + * - DK (Denmark) + * - SE (Sweden) + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '' || !options.country) { + return true; + } + + var country = (options.country || 'US').toUpperCase(); + switch (country) { + case 'CA': + return /(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}\s?[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}/i.test(value); + case 'DK': + return /^(DK(-|\s)?)?\d{4}$/i.test(value); + case 'SE': + return /^(S-)?\d{3}\s?\d{2}$/i.test(value); + case 'US': + default: + return /^\d{4,5}([\-]\d{4})?$/.test(value); + } + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.3/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.4.3/js/bootstrapValidator.min.js new file mode 100644 index 000000000..fe1bfa875 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.3/js/bootstrapValidator.min.js @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.3 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),this.$invalidField=null,this.$submitButton=null,this.STATUS_NOT_VALIDATED="NOT_VALIDATED",this.STATUS_VALIDATING="VALIDATING",this.STATUS_INVALID="INVALID",this.STATUS_VALID="VALID";var e=function(){for(var a=3,b=document.createElement("div"),c=b.all||[];b.innerHTML="",c[0];);return a>4?a:!a}(),f=document.createElement("div");this._changeEvent=9!==e&&"oninput"in f?"input":"keyup",this._submitIfValid=null,this._init()};b.DEFAULT_OPTIONS={elementClass:"bootstrap-validator-form",message:"This value is not valid",excluded:[":disabled",":hidden",":not(:visible)"],feedbackIcons:{valid:null,invalid:null,validating:null},submitButtons:'button[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){var b,c,d,e,f,g,h,i=this,j={excluded:this.$form.attr("data-bv-excluded"),trigger:this.$form.attr("data-bv-trigger"),message:this.$form.attr("data-bv-message"),submitButtons:this.$form.attr("data-bv-submitbuttons"),live:this.$form.attr("data-bv-live"),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")}};this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit.bv",function(a){a.preventDefault(),i.validate()}).on("click",this.options.submitButtons,function(){i.$submitButton=a(this),i._submitIfValid=!0}).find("[name], [data-bv-field]").each(function(){var i=a(this);if("hidden"!=i.attr("type")){var k=i.attr("name")||i.attr("data-bv-field");i.attr("data-bv-field",k),j.fields[k]=a.extend({},{trigger:i.attr("data-bv-trigger"),message:i.attr("data-bv-message"),container:i.attr("data-bv-container"),selector:i.attr("data-bv-selector"),validators:{}},j.fields[k]);for(c in a.fn.bootstrapValidator.validators)if(b=a.fn.bootstrapValidator.validators[c],d=i.attr("data-bv-"+c.toLowerCase())+"",h="function"==typeof b.enableByHtml5?b.enableByHtml5(a(this)):null,h&&"false"!=d||h!==!0&&(""==d||"true"==d)){b.html5Attributes=b.html5Attributes||{message:"message"},j.fields[k].validators[c]=a.extend({},1==h?{}:h,j.fields[k].validators[c]);for(g in b.html5Attributes)e=b.html5Attributes[g],f=i.attr("data-bv-"+c.toLowerCase()+"-"+g),f&&("true"==f?f=!0:"false"==f&&(f=!1),j.fields[k].validators[c][e]=f)}}}),this.options=a.extend(!0,this.options,j),"string"==typeof this.options.excluded&&(this.options.excluded=a.map(this.options.excluded.split(","),function(b){return a.trim(b)}));for(var k in this.options.fields)this._initField(k);this.setLiveMode(this.options.live)},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){var c=this.getFieldElements(b);if(null==c)return void delete this.options.fields[b];for(var d in this.options.fields[b].validators)a.fn.bootstrapValidator.validators[d]||delete this.options.fields[b].validators[d];for(var e=this,f=c.attr("type"),g="radio"==f||"checkbox"==f||"file"==f||"SELECT"==c[0].tagName?"change":e._changeEvent,h=c.length,i=1==h||"radio"==f||"checkbox"==f,j=0;h>j;j++){var k=a(c[j]),l=k.parents(".form-group"),m=this.options.fields[b].container?l.find(this.options.fields[b].container):this._getMessageContainer(k);k.attr("data-bv-field")||k.attr("data-bv-field",b),k.on(g+".update.bv",function(){e._submitIfValid=!1,i?e.updateStatus(b,e.STATUS_NOT_VALIDATED,null):e.updateElementStatus(a(this),e.STATUS_NOT_VALIDATED,null)}),k.data("bv.messages",m);for(d in this.options.fields[b].validators)k.data("bv.result."+d,this.STATUS_NOT_VALIDATED),i&&j!=h-1||a("").css("display","none").attr("data-bv-validator",d).html(this.options.fields[b].validators[d].message||this.options.fields[b].message||this.options.message).addClass("help-block").appendTo(m);if(this.options.feedbackIcons&&this.options.feedbackIcons.validating&&this.options.feedbackIcons.invalid&&this.options.feedbackIcons.valid&&(!i||j==h-1)){l.addClass("has-feedback");var n=a("").css("display","none").addClass("form-control-feedback").attr("data-bv-field",b).insertAfter(k);0==l.find("label").length&&n.css("top",0)}}null==this.options.fields[b].enabled&&(this.options.fields[b].enabled=!0)}},_getMessageContainer:function(a){var b=a.parent();if(b.hasClass("form-group"))return b;var c=b.attr("class");if(!c)return this._getMessageContainer(b);c=c.split(" ");for(var d=c.length,e=0;d>e;e++)if(/^col-(xs|sm|md|lg)-\d+$/.test(c[e])||/^col-(xs|sm|md|lg)-offset-\d+$/.test(c[e]))return b;return this._getMessageContainer(b)},_submit:function(){if(this.isValid())this.options.submitHandler&&"function"==typeof this.options.submitHandler?this.options.submitHandler.call(this,this,this.$form,this.$submitButton):this.disableSubmitButtons(!0).defaultSubmit();else if("submitted"==this.options.live&&this.setLiveMode("enabled"),this.$invalidField){var b,c=this.$invalidField.parents(".tab-pane");c&&(b=c.attr("id"))&&a('a[href="#'+b+'"][data-toggle="tab"]').trigger("click.bs.tab.data-api"),this.$invalidField.focus()}},_isExcluded:function(a){if(this.options.excluded)for(var b in this.options.excluded)if("string"==typeof this.options.excluded[b]&&a.is(this.options.excluded[b])||"function"==typeof this.options.excluded[b]&&1==this.options.excluded[b].call(this,a,this))return!0;return!1},getFieldElements:function(b){var c=this.options.fields[b].selector?a(this.options.fields[b].selector):this.$form.find('[name="'+b+'"]');return 0==c.length?null:c},setLiveMode:function(b){if(this.options.live=b,"submitted"==b)return this;var c=this;for(var d in this.options.fields)!function(e){var f=c.getFieldElements(e);if(f)for(var g=f.attr("type"),h=f.length,i=1==h||"radio"==g||"checkbox"==g,j=c.options.fields[d].trigger||c.options.trigger||("radio"==g||"checkbox"==g||"file"==g||"SELECT"==f[0].tagName?"change":c._changeEvent),k=a.map(j.split(" "),function(a){return a+".live.bv"}).join(" "),l=0;h>l;l++)"enabled"==b?a(f[l]).on(k,function(){i?c.validateField(e):c.validateFieldElement(a(this),!1)}):a(f[l]).off(k)}(d);return this},disableSubmitButtons:function(a){return a?"disabled"!=this.options.live&&this.$form.find(this.options.submitButtons).attr("disabled","disabled"):this.$form.find(this.options.submitButtons).removeAttr("disabled"),this},validate:function(){if(!this.options.fields)return this;this.disableSubmitButtons(!0);for(var a in this.options.fields)this.validateField(a);return this.$submitButton&&this._submit(),this},validateField:function(b){for(var c=this.getFieldElements(b),d=c.attr("type"),e="radio"==d||"checkbox"==d?1:c.length,f=0;e>f;f++)this.validateFieldElement(a(c[f]),1==e);return this},validateFieldElement:function(b,c){var d,e,f=this,g=b.attr("data-bv-field"),h=this.options.fields[g].validators;if(!this.options.fields[g].enabled||this._isExcluded(b))return this;for(d in h){b.data("bv.dfs."+d)&&b.data("bv.dfs."+d).reject();var i=b.data("bv.result."+d);i!=this.STATUS_VALID&&i!=this.STATUS_INVALID&&(b.data("bv.result."+d,this.STATUS_VALIDATING),e=a.fn.bootstrapValidator.validators[d].validate(this,b,h[d]),"object"==typeof e?(c?this.updateStatus(g,this.STATUS_VALIDATING,d):this.updateElementStatus(b,this.STATUS_VALIDATING,d),b.data("bv.dfs."+d,e),e.done(function(a,b,d){a.removeData("bv.dfs."+b),c?f.updateStatus(a.attr("data-bv-field"),d?f.STATUS_VALID:f.STATUS_INVALID,b):f.updateElementStatus(a,d?f.STATUS_VALID:f.STATUS_INVALID,b),d&&1==f._submitIfValid&&f._submit()})):"boolean"==typeof e&&(c?this.updateStatus(g,e?this.STATUS_VALID:this.STATUS_INVALID,d):this.updateElementStatus(b,e?this.STATUS_VALID:this.STATUS_INVALID,d)))}return this},updateStatus:function(b,c,d){for(var e=this.getFieldElements(b),f=e.attr("type"),g="radio"==f||"checkbox"==f?1:e.length,h=0;g>h;h++)this.updateElementStatus(a(e[h]),c,d);return this},updateElementStatus:function(b,c,d){var e=this,f=b.attr("data-bv-field"),g=b.parents(".form-group"),h=b.data("bv.messages"),i=g.find(".help-block[data-bv-validator]"),j=h.find(".help-block[data-bv-validator]"),k=g.find('.form-control-feedback[data-bv-field="'+f+'"]');if(d)b.data("bv.result."+d,c);else for(var l in this.options.fields[f].validators)b.data("bv.result."+l,c);switch(c){case this.STATUS_VALIDATING:this.disableSubmitButtons(!0),g.removeClass("has-success").removeClass("has-error"),d?j.filter('.help-block[data-bv-validator="'+d+'"]').hide():j.hide(),k&&k.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show();break;case this.STATUS_INVALID:this.disableSubmitButtons(!0),g.removeClass("has-success").addClass("has-error"),d?j.filter('[data-bv-validator="'+d+'"]').show():j.show(),k&&k.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show();break;case this.STATUS_VALID:d?j.filter('[data-bv-validator="'+d+'"]').hide():j.hide();var m=0==j.filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||b.data("bv.result."+d)!=e.STATUS_VALID}).length;this.disableSubmitButtons(m?!1:!0),k&&k.removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid).addClass(m?this.options.feedbackIcons.valid:this.options.feedbackIcons.invalid).show();var n=0==i.filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||b.data("bv.result."+d)!=e.STATUS_VALID}).length;g.removeClass("has-error has-success").addClass(n?"has-success":"has-error");break;case this.STATUS_NOT_VALIDATED:default:this.disableSubmitButtons(!1),g.removeClass("has-success").removeClass("has-error"),d?j.filter('.help-block[data-bv-validator="'+d+'"]').hide():j.hide(),k&&k.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide()}return this},isValid:function(){var b,c,d,e,f,g,h,i;for(c in this.options.fields)if(null!=this.options.fields[c]&&this.options.fields[c].enabled)for(b=this.getFieldElements(c),e=b.attr("type"),h="radio"==e||"checkbox"==e?1:b.length,i=0;h>i;i++)if(d=a(b[i]),!this._isExcluded(d))for(g in this.options.fields[c].validators){if(f=d.data("bv.result."+g),f==this.STATUS_NOT_VALIDATED||f==this.STATUS_VALIDATING)return!1;if(f==this.STATUS_INVALID)return this.$invalidField=d,!1}return!0},defaultSubmit:function(){this.$form.off("submit.bv").submit()},resetForm:function(b){var c,d,e,f,g;for(c in this.options.fields){d=this.getFieldElements(c),e=d.length;for(var h=0;e>h;h++)for(g in this.options.fields[c].validators)a(d[h]).removeData("bv.dfs."+g);this.updateStatus(c,this.STATUS_NOT_VALIDATED,null),b&&(f=d.attr("type"),"radio"==f||"checkbox"==f?d.removeAttr("checked").removeAttr("selected"):d.val(""))}return this.$invalidField=null,this.$submitButton=null,this.disableSubmitButtons(!1),this},enableFieldValidators:function(a,b){return this.options.fields[a].enabled=b,this.updateStatus(a,this.STATUS_NOT_VALIDATED,null),this}},a.fn.bootstrapValidator=function(c,d){return this.each(function(){var e=a(this),f=e.data("bootstrapValidator"),g="object"==typeof c&&c;f||(f=new b(this,g),e.data("bootstrapValidator",f)),"string"==typeof c&&f[c](d)})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b,a.fn.bootstrapValidator.helpers={luhn:function(a){for(var b=a.length,c=0,d=[[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8,1,3,5,7,9]],e=0;b--;)e+=d[c][parseInt(a.charAt(b),10)],c^=1;return e%10===0&&e>0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.base64={validate:function(a,b){var c=b.val();return""==c?!0:/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={html5Attributes:{message:"message",min:"min",max:"max",inclusive:"inclusive"},enableByHtml5:function(a){return"range"==a.attr("type")?{min:a.attr("min"),max:a.attr("max")}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(b,c,d){var e=c.val();if(d.callback&&"function"==typeof d.callback){var f=new a.Deferred;return f.resolve(c,"callback",d.callback.call(this,e,b)),f}return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.choice={html5Attributes:{message:"message",min:"min",max:"max"},validate:function(a,b,c){var d=b.is("select")?a.getFieldElements(b.attr("data-bv-field")).find("option").filter(":selected").length:a.getFieldElements(b.attr("data-bv-field")).filter(":checked").length;return c.min&&dc.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(b,c){var d=c.val();if(""==d)return!0;if(/[^0-9-\s]+/.test(d))return!1;if(d=d.replace(/\D/g,""),!a.fn.bootstrapValidator.helpers.luhn(d))return!1;var e,f,g={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["3528","3529","353","354","355","356","357","358"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}};for(e in g)for(f in g[e].prefix)if(d.substr(0,g[e].prefix[f].length)==g[e].prefix[f]&&-1!=g[e].length.indexOf(d.length))return!0;return!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.cvv={html5Attributes:{message:"message",ccfield:"creditCardField"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;if(!/^[0-9]{3,4}$/.test(d))return!1;if(!c.creditCardField)return!0;var e=a.getFieldElements(c.creditCardField).val();if(""==e)return!0;var f,g,h={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["3528","3529","353","354","355","356","357","358"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}},i=null;for(f in h)for(g in h[f].prefix)if(e.substr(0,h[f].prefix[g].length)==h[f].prefix[g]&&-1!=h[f].length.indexOf(e.length)){i=f;break}return null==i?!1:"AMERICAN_EXPRESS"==i?4==d.length:3==d.length}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.date={html5Attributes:{message:"message",format:"format"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;c.format=c.format||"MM/DD/YYYY";var e=-1!=c.format.indexOf("/")?"/":-1!=c.format.indexOf("-")?"-":null;if(null==e)return!1;var f,g,h,i,j=null,k=null;switch(!0){case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/DD/MM"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-DD-MM"==c.format:h=i[1],g=i[2],f=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"DD/MM/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"DD-MM-YYYY"==c.format:g=i[1],f=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})$/i))&&"YYYY/MM/DD"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})$/i))&&"YYYY-MM-DD"==c.format:h=i[1],f=i[2],g=i[3];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})$/i))&&"MM/DD/YYYY"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})$/i))&&"MM-DD-YYYY"==c.format:f=i[1],g=i[2],h=i[3];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/DD/MM h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-DD-MM h:m A"==c.format:h=i[1],g=i[2],f=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD/MM/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"DD-MM-YYYY h:m A"==c.format:g=i[1],f=i[2],h=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{4})\/(\d{1,2})\/(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY/MM/DD h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{4})-(\d{1,2})-(\d{1,2})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"YYYY-MM-DD h:m A"==c.format:h=i[1],f=i[2],g=i[3],k=i[4],j=i[5];break;case"/"==e&&(i=d.match(/^(\d{1,2})\/(\d{1,2})\/(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM/DD/YYYY h:m A"==c.format:case"-"==e&&(i=d.match(/^(\d{1,2})-(\d{1,2})-(\d{4})\s+(\d{1,2}):(\d{1,2})\s+(AM|PM)$/i))&&"MM-DD-YYYY h:m A"==c.format:f=i[1],g=i[2],h=i[3],k=i[4],j=i[5];break;default:return!1}if(k&&j&&(k=parseInt(k,10),j=parseInt(j,10),1>k||k>12||0>j||j>59))return!1;if(g=parseInt(g,10),f=parseInt(f,10),h=parseInt(h,10),1e3>h||h>9999||0==f||f>12)return!1;var l=[31,28,31,30,31,30,31,31,30,31,30,31];return(h%400==0||h%100!=0&&h%4==0)&&(l[1]=29),g>0&&g<=l[f-1]}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={html5Attributes:{message:"message",field:"field"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d!=e.val()?(a.updateStatus(c.field,a.STATUS_VALID,"different"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){var c=b.val();return""==c?!0:/^\d+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={enableByHtml5:function(a){return"email"==a.attr("type")},validate:function(a,b){var c=b.val();if(""==c)return!0;var d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.file={html5Attributes:{extension:"extension",maxsize:"maxSize",message:"message",type:"type"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e,f=c.extension?c.extension.split(","):null,g=c.type?c.type.split(","):null,h=window.File&&window.FileList&&window.FileReader;if(h)for(var i=b.get(0).files,j=i.length,k=0;j>k;k++){if(c.maxSize&&i[k].size>parseInt(c.maxSize))return!1;if(e=i[k].name.substr(i[k].name.lastIndexOf(".")+1),f&&-1==f.indexOf(e))return!1;if(g&&-1==g.indexOf(i[k].type))return!1}else if(e=d.substr(d.lastIndexOf(".")+1),f&&-1==f.indexOf(e))return!1;return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={html5Attributes:{message:"message",value:"value",inclusive:"inclusive"},enableByHtml5:function(a){var b=a.attr("min");return b?{value:b}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.value:d>=c.value)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hex={validate:function(a,b){var c=b.val();return""==c?!0:/^[0-9a-fA-F]+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={enableByHtml5:function(a){return"color"==a.attr("type")},validate:function(a,b){var c=b.val();return""==c?!0:/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.iban={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e={AD:"AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}",AE:"AE[0-9]{2}[0-9]{3}[0-9]{16}",AL:"AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}",AO:"AO[0-9]{2}[0-9]{21}",AT:"AT[0-9]{2}[0-9]{5}[0-9]{11}",AZ:"AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}",BA:"BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}",BE:"BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}",BF:"BF[0-9]{2}[0-9]{23}",BG:"BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}",BH:"BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}",BI:"BI[0-9]{2}[0-9]{12}",BJ:"BJ[0-9]{2}[A-Z]{1}[0-9]{23}",BR:"BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]",CH:"CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}",CI:"CI[0-9]{2}[A-Z]{1}[0-9]{23}",CM:"CM[0-9]{2}[0-9]{23}",CR:"CR[0-9]{2}[0-9]{3}[0-9]{14}",CV:"CV[0-9]{2}[0-9]{21}",CY:"CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}",CZ:"CZ[0-9]{2}[0-9]{20}",DE:"DE[0-9]{2}[0-9]{8}[0-9]{10}",DK:"DK[0-9]{2}[0-9]{14}",DO:"DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}",DZ:"DZ[0-9]{2}[0-9]{20}",EE:"EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}",ES:"ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}",FI:"FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}",FO:"FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}",FR:"FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}",GB:"GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}",GE:"GE[0-9]{2}[A-Z]{2}[0-9]{16}",GI:"GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}",GL:"GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}",GR:"GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}",GT:"GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}",HR:"HR[0-9]{2}[0-9]{7}[0-9]{10}",HU:"HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}",IE:"IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}",IL:"IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}",IR:"IR[0-9]{2}[0-9]{22}",IS:"IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}",IT:"IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}",JO:"JO[0-9]{2}[A-Z]{4}[0-9]{4}[0]{8}[A-Z0-9]{10}",KW:"KW[0-9]{2}[A-Z]{4}[0-9]{22}",KZ:"KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}",LB:"LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}",LI:"LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}",LT:"LT[0-9]{2}[0-9]{5}[0-9]{11}",LU:"LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}",LV:"LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}",MC:"MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}",MD:"MD[0-9]{2}[A-Z0-9]{20}",ME:"ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",MG:"MG[0-9]{2}[0-9]{23}",MK:"MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}",ML:"ML[0-9]{2}[A-Z]{1}[0-9]{23}",MR:"MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}",MT:"MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}",MU:"MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}",MZ:"MZ[0-9]{2}[0-9]{21}",NL:"NL[0-9]{2}[A-Z]{4}[0-9]{10}",NO:"NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}",PK:"PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}",PL:"PL[0-9]{2}[0-9]{8}[0-9]{16}",PS:"PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}",PT:"PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}",QA:"QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}",RO:"RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}",RS:"RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",SA:"SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}",SE:"SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}",SI:"SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}",SK:"SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}",SM:"SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}",SN:"SN[0-9]{2}[A-Z]{1}[0-9]{23}",TN:"TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",TR:"TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}",VG:"VG[0-9]{2}[A-Z]{4}[0-9]{16}"};d=d.replace(/[^a-zA-Z0-9]/g,"").toUpperCase();var f=c.country||d.substr(0,2);if(!e[f])return!1;if(!new RegExp("^"+e[f]+"$").test(d))return!1;d=d.substr(4)+d.substr(0,4),d=d.split("").map(function(a){var b=a.charCodeAt(0);return b>="A".charCodeAt(0)&&b<="Z".charCodeAt(0)?b-"A".charCodeAt(0)+10:a}).join("");for(var g=parseInt(d.substr(0,1),10),h=d.length,i=1;h>i;++i)g=(10*g+parseInt(d.substr(i,1),10))%97;return 1==g}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={html5Attributes:{message:"message",field:"field"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d==e.val()?(a.updateStatus(c.field,a.STATUS_VALID,"identical"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.integer={enableByHtml5:function(a){return"number"==a.attr("type")},validate:function(a,b){var c=b.val();return""==c?!0:/^(?:-?(?:0|[1-9][0-9]*))$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.ip={html5Attributes:{message:"message",ipv4:"ipv4",ipv6:"ipv6"},validate:function(b,c,d){var e=c.val();return""==e?!0:(d=a.extend({},{ipv4:!0,ipv6:!0},d),d.ipv4?/^(?:(?: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(e):d.ipv6?/^\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(str):!1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.isbn={validate:function(a,b){var c=b.val();if(""==c)return!0;var d;switch(!0){case/^\d{9}[\dX]$/.test(c):case 13==c.length&&/^(\d+)-(\d+)-(\d+)-([\dX])$/.test(c):case 13==c.length&&/^(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(c):d="ISBN10";break;case/^(978|979)\d{9}[\dX]$/.test(c):case 17==c.length&&/^(978|979)-(\d+)-(\d+)-(\d+)-([\dX])$/.test(c):case 17==c.length&&/^(978|979)\s(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(c):d="ISBN13";break;default:return!1}c=c.replace(/[^0-9X]/gi,"");var e,f=c.split(""),g=f.length,h=0;switch(d){case"ISBN10":h=0;for(var i=0;g-1>i;i++)h+=(10-i)*parseInt(f[i]);return e=11-h%11,11==e?e=0:10==e&&(e="X"),e+""==f[g-1];case"ISBN13":h=0;for(var i=0;g-1>i;i++)h+=i%2==0?parseInt(f[i]):3*parseInt(f[i]);return e=10-h%10,10==e&&(e="0"),e+""==f[g-1];default:return!1}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={html5Attributes:{message:"message",value:"value",inclusive:"inclusive"},enableByHtml5:function(a){var b=a.attr("max");return b?{value:b}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!1?d<=c.value:d0:""!=a.trim(c.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.numeric={validate:function(a,b){var c=b.val();return""==c?!0:!isNaN(parseFloat(c))&&isFinite(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.phone={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=(c.country||"US").toUpperCase();switch(e){case"US":default:return d=d.replace(/\D/g,""),/^(?:(1\-?)|(\+1 ?))?\(?(\d{3})[\)\-\.]?(\d{3})[\-\.]?(\d{4})$/.test(d)&&10==d.length}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.regexp={html5Attributes:{message:"message",regexp:"regexp"},enableByHtml5:function(a){var b=a.attr("pattern");return b?{regexp:b}:!1},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e="string"==typeof c.regexp?new RegExp(c.regexp):c.regexp;return e.test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.remote={html5Attributes:{message:"message",url:"url",name:"name"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=c.attr("data-bv-field"),g=d.data;null==g&&(g={}),"function"==typeof g&&(g=g.call(this,b)),g[d.name||f]=e;var h=new a.Deferred,i=a.ajax({type:"POST",url:d.url,dataType:"json",data:g});return i.then(function(a){h.resolve(c,"remote",a.valid===!0||"true"===a.valid)}),h.fail(function(){i.abort()}),h}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.siren={validate:function(b,c){var d=c.val();return""==d?!0:/^\d{9}$/.test(d)?a.fn.bootstrapValidator.helpers.luhn(d):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.siret={validate:function(a,b){var c=b.val();if(""==c)return!0;for(var d,e=0,f=c.length,g=0;f>g;g++)d=parseInt(c.charAt(g),10),g%2==0&&(d=2*d,d>9&&(d-=9)),e+=d;return e%10==0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.step={html5Attributes:{message:"message",base:"baseValue",step:"step"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;if(d=a.extend({},{baseValue:0,step:1},d),e=parseFloat(e),isNaN(e)||!isFinite(e))return!1;var f=function(a,b){var c=Math.pow(10,b);a*=c;var d=a>0|-(0>a),e=a%1===.5*d;return e?(Math.floor(a)+(d>0))/c:Math.round(a)/c},g=function(a,b){if(0==b)return 1;var c=(a+"").split("."),d=(b+"").split("."),e=(1==c.length?0:c[1].length)+(1==d.length?0:d[1].length);return f(a-b*Math.floor(a/b),e)},h=g(e-d.baseValue,d.step);return 0==h||h==d.step}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringCase={html5Attributes:{message:"message","case":"case"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=(c["case"]||"lower").toLowerCase();switch(e){case"upper":return d===d.toUpperCase();case"lower":default:return d===d.toLowerCase()}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringLength={html5Attributes:{message:"message",min:"min",max:"max"},enableByHtml5:function(a){var b=a.attr("maxlength");return b?{max:parseInt(b,10)}:!1},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=a.trim(e).length;return d.min&&fd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={enableByHtml5:function(a){return"url"==a.attr("type")},validate:function(a,b){var c=b.val();if(""==c)return!0;var d=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uuid={html5Attributes:{message:"message",version:"version"},validate:function(a,b,c){var d=b.val(); +if(""==d)return!0;var e={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i},f=c.version?c.version+"":"all";return null==e[f]?!0:e[f].test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.vat={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=c.country||d.substr(0,2),f=["_",e.toLowerCase()].join("");return this[f]&&"function"==typeof this[f]?this[f](d):!0},_at:function(a){if(!/^ATU[0-9]{8}$/.test(a))return!1;a=a.substr(3);for(var b=0,c=[1,2,1,2,1,2,1],d=0,e=0;7>e;e++)d=parseInt(a.charAt(e))*c[e],d>9&&(d=Math.floor(d/10)+d%10),b+=d;return b=10-(b+4)%10,10==b&&(b=0),b==a.substr(7,1)},_be:function(a){if(!/^BE[0]{0,1}[0-9]{9}$/.test(a))return!1;if(a=a.substr(2),9==a.length&&(a="0"+a),0==a.substr(1,1))return!1;var b=parseInt(a.substr(0,8),10)+parseInt(a.substr(8,2),10);return b%97==0},_bg:function(a){if(!/^BG[0-9]{9,10}$/.test(a))return!1;a=a.substr(2);var b=0,c=0;if(9==a.length){for(c=0;8>c;c++)b+=parseInt(a.charAt(c))*(c+1);if(b%=11,10==b)for(b=0,c=0;8>c;c++)b+=parseInt(a.charAt(c))*(c+3);return b%=10,b==a.substr(8)}if(10==a.length){var d=function(a){var b=parseInt(a.substr(0,2),10)+1900,c=parseInt(a.substr(2,2),10),d=parseInt(a.substr(4,2),10);c>40?(b+=100,c-=40):c>20&&(b-=100,c-=20);try{{new Date(b,c,d)}}catch(e){return!1}for(var f=0,g=[2,4,8,5,10,9,7,3,6],h=0;9>h;h++)f+=parseInt(a.charAt(h))*g[h];return f=f%11%10,f==a.substr(9,1)},e=function(a){for(var b=0,c=[21,19,17,13,11,9,7,3,1],d=0;9>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%=10,b==a.substr(9,1)},f=function(a){for(var b=0,c=[4,3,2,7,6,5,4,3,2],d=0;9>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,10==b?!1:(11==b&&(b=0),b==a.substr(9,1))};return d(a)||e(a)||f(a)}return!1},_ch:function(a){if(!/^CHE[0-9]{9}(MWST)?$/.test(a))return!1;a=a.substr(3);for(var b=0,c=[5,4,3,2,7,6,5,4],d=0;8>d;d++)b+=parseInt(a.charAt(d),10)*c[d];return b=11-b%11,10==b?!1:(11==b&&(b=0),b==a.substr(8,1))},_cy:function(a){if(!/^CY[0-5|9]{1}[0-9]{7}[A-Z]{1}$/.test(a))return!1;if(a=a.substr(2),"12"==a.substr(0,2))return!1;for(var b=0,c={0:1,1:0,2:5,3:7,4:9,5:13,6:15,7:17,8:19,9:21},d=0;8>d;d++){var e=parseInt(a.charAt(d),10);d%2==0&&(e=c[e+""]),b+=e}return b="ABCDEFGHIJKLMNOPQRSTUVWXYZ"[b%26],b==a.substr(8,1)},_cz:function(a){if(!/^CZ[0-9]{8,10}$/.test(a))return!1;a=a.substr(2);var b=0,c=0;if(8==a.length){if(a.charAt(0)+""=="9")return!1;for(b=0,c=0;7>c;c++)b+=parseInt(a.charAt(c),10)*(8-c);return b=11-b%11,10==b&&(b=0),11==b&&(b=1),b==a.substr(7,1)}if(9==a.length&&a.charAt(0)+""=="6"){for(b=0,c=0;7>c;c++)b+=parseInt(a.charAt(c+1),10)*(8-c);return b=11-b%11,10==b&&(b=0),11==b&&(b=1),b=[8,7,6,5,4,3,2,1,0,9,10][b-1],b==a.substr(8,1)}if(9==a.length||10==a.length){var d=1900+parseInt(a.substr(0,2)),e=parseInt(a.substr(2,2))%50%20,f=parseInt(a.substr(4,2));if(9==a.length){if(d>=1980&&(d-=100),d>1953)return!1}else 1954>d&&(d+=100);try{{new Date(d,e,f)}}catch(g){return!1}if(10==a.length){var h=parseInt(a.substr(0,9),10)%11;return 1985>d&&(h%=10),h==a.substr(9,1)}return!0}return!1},_de:function(a){if(!/^DE[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=10,c=0,d=0;8>d;d++)c=(parseInt(a.charAt(d),10)+b)%10,0==c&&(c=10),b=2*c%11;var e=11-b==10?0:11-b;return e==a.substr(8,1)},_dk:function(a){if(!/^DK[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[2,7,6,5,4,3,2,1],d=0;8>d;d++)b+=parseInt(a.charAt(d),10)*c[d];return b%11==0},_ee:function(a){if(!/^EE[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[3,7,1,3,7,1,3,7,1],d=0;9>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%10==0},_es:function(a){if(!/^ES[0-9A-Z][0-9]{7}[0-9A-Z]$/.test(a))return!1;a=a.substr(2);var b=function(a){var b=parseInt(a.substr(0,8),10);return b="TRWAGMYFPDXBNJZSQVHLCKE"[b%23],b==a.substr(8,1)},c=function(a){var b=["XYZ".indexOf(a.charAt(0)),a.substr(1)].join("");return b=parseInt(b,10),b="TRWAGMYFPDXBNJZSQVHLCKE"[b%23],b==a.substr(8,1)},d=function(a){var b,c=a.charAt(0);if(-1!="KLM".indexOf(c))return b=parseInt(a.substr(1,8),10),b="TRWAGMYFPDXBNJZSQVHLCKE"[b%23],b==a.substr(8,1);if(-1!="ABCDEFGHJNPQRSUVW".indexOf(c)){for(var d=0,e=[2,1,2,1,2,1,2],f=0,g=0;7>g;g++)f=parseInt(a.charAt(g+1))*e[g],f>9&&(f=Math.floor(f/10)+f%10),d+=f;return d=10-d%10,d==a.substr(8,1)||"JABCDEFGHI"[d]==a.substr(8,1)}return!1},e=a.charAt(0);return/^[0-9]$/.test(e)?b(a):/^[XYZ]$/.test(e)?c(a):d(a)},_fi:function(a){if(!/^FI[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[7,9,10,5,8,4,2,1],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%11==0},_fr:function(b){if(!/^FR[0-9A-Z]{2}[0-9]{9}$/.test(b))return!1;if(b=b.substr(2),!a.fn.bootstrapValidator.helpers.luhn(b.substr(2)))return!1;if(/^[0-9]{2}$/.test(b.substr(0,2)))return b.substr(0,2)==parseInt(b.substr(2)+"12",10)%97;var c,d="0123456789ABCDEFGHJKLMNPQRSTUVWXYZ";return c=/^[0-9]{1}$/.test(b.charAt(0))?24*d.indexOf(b.charAt(0))+d.indexOf(b.charAt(1))-10:34*d.indexOf(b.charAt(0))+d.indexOf(b.charAt(1))-100,(parseInt(b.substr(2),10)+1+Math.floor(c/11))%11==c%11},_gb:function(a){if(!(/^GB[0-9]{9}$/.test(a)||/^GB[0-9]{12}$/.test(a)||/^GBGD[0-9]{3}$/.test(a)||/^GBHA[0-9]{3}$/.test(a)||/^GB(GD|HA)8888[0-9]{5}$/.test(a)))return!1;a=a.substr(2);var b=a.length;if(5==b){var c=a.substr(0,2),d=parseInt(a.substr(2));return"GD"==c&&500>d||"HA"==c&&d>=500}if(11==b&&("GD8888"==a.substr(0,6)||"HA8888"==a.substr(0,6)))return"GD"==a.substr(0,2)&&parseInt(a.substr(6,3))>=500||"HA"==a.substr(0,2)&&parseInt(a.substr(6,3))<500?!1:parseInt(a.substr(6,3))%97==parseInt(a.substr(9,2));if(9==b||12==b){for(var e=0,f=[8,7,6,5,4,3,2,10,1],g=0;9>g;g++)e+=parseInt(a.charAt(g))*f[g];return e%=97,parseInt(a.substr(0,3))>=100?0==e||42==e||55==e:0==e}return!0},_gr:function(a){if(!/^GR[0-9]{9}$/.test(a))return!1;a=a.substr(2),8==a.length&&(a="0"+a);for(var b=0,c=[256,128,64,32,16,8,4,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=b%11%10,b==a.substr(8,1)},_el:function(a){return/^EL[0-9]{9}$/.test(a)?(a="GR"+a.substr(2),this._gr(a)):!1},_hu:function(a){if(!/^HU[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[9,7,3,1,9,7,3,1],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%10==0},_hr:function(a){if(!/^HR[0-9]{11}$/.test(a))return!1;a=a.substr(2);for(var b=10,c=0,d=0;10>d;d++)c=(parseInt(a.charAt(d),10)+b)%10,0==c&&(c=10),b=2*c%11;return b+=parseInt(a.substr(10,1),10),b%10==1},_ie:function(a){if(!/^IE[0-9]{1}[0-9A-Z\*\+]{1}[0-9]{5}[A-Z]{1,2}$/.test(a))return!1;a=a.substr(2);var b=function(a){for(;a.length<7;)a="0"+a;for(var b="WABCDEFGHIJKLMNOPQRSTUV",c=0,d=0;7>d;d++)c+=parseInt(a.charAt(d))*(8-d);return c+=9*b.indexOf(a.substr(7)),b[c%23]};return/^[0-9]+$/.test(a.substr(0,7))?a.charAt(7)==b(a.substr(0,7)+a.substr(8)+""):-1!="ABCDEFGHIJKLMNOPQRSTUVWXYZ+*".indexOf(a.charAt(1))?a.charAt(7)==b(a.substr(2,5)+a.substr(0,1)+""):!0},_it:function(b){if(!/^IT[0-9]{11}$/.test(b))return!1;if(b=b.substr(2),0==parseInt(b.substr(0,7)))return!1;var c=parseInt(b.substr(7,3));return 1>c||c>201&&999!=c&&888!=c?!1:a.fn.bootstrapValidator.helpers.luhn(b)},_lt:function(a){if(!/^LT([0-9]{7}1[0-9]{1}|[0-9]{10}1[0-9]{1})$/.test(a))return!1;a=a.substr(2);for(var b=a.length,c=0,d=0;b-1>d;d++)c+=parseInt(a.charAt(d))*(1+d%9);var e=c%11;if(10==e){c=0;for(var d=0;b-1>d;d++)c+=parseInt(a.charAt(d))*(1+(d+2)%9)}return e=e%11%10,e==a.charAt(b-1)},_lu:function(a){return/^LU[0-9]{8}$/.test(a)?(a=a.substr(2),a.substr(0,6)%89==a.substr(6,2)):!1},_lv:function(a){if(!/^LV[0-9]{11}$/.test(a))return!1;a=a.substr(2);var b=parseInt(a.charAt(0)),c=0,d=[],e=0,f=a.length;if(b>3){for(c=0,d=[9,1,4,8,3,10,2,5,7,6,1],e=0;f>e;e++)c+=parseInt(a.charAt(e))*d[e];return c%=11,3==c}var g=parseInt(a.substr(0,2)),h=parseInt(a.substr(2,2)),i=parseInt(a.substr(4,2));i=i+1800+100*parseInt(a.charAt(6));try{{new Date(i,h,g)}}catch(j){return!1}for(c=0,d=[10,5,8,4,2,1,6,3,7,9],e=0;f-1>e;e++)c+=parseInt(a.charAt(e))*d[e];return c=(c+1)%11%10,c==a.charAt(f-1)},_mt:function(a){if(!/^MT[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[3,4,6,7,8,9,10,1],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%37==0},_nl:function(a){if(!/^NL[0-9]{9}B[0-9]{2}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[9,8,7,6,5,4,3,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%=11,b>9&&(b=0),b==a.substr(8,1)},_no:function(a){if(!/^NO[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[3,2,7,6,5,4,3,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,11==b&&(b=0),b==a.substr(8,1)},_pl:function(a){if(!/^PL[0-9]{10}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[6,5,7,2,3,4,5,6,7,-1],d=0;10>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%11==0},_pt:function(a){if(!/^PT[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[9,8,7,6,5,4,3,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,b>9&&(b=0),b==a.substr(8,1)},_ro:function(a){if(!/^RO[1-9][0-9]{1,9}$/.test(a))return!1;a=a.substr(2);for(var b=a.length,c=[7,5,3,2,1,7,5,3,2].slice(10-b),d=0,e=0;b-1>e;e++)d+=parseInt(a.charAt(e))*c[e];return d=10*d%11%10,d==a.substr(b-1,1)},_ru:function(a){if(!/^RU([0-9]{9}|[0-9]{12})$/.test(a))return!1;if(a=a.substr(2),10==a.length){for(var b=0,c=[2,4,10,3,5,9,4,6,8,0],d=0;10>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%=11,b>9&&(b%=10),b==a.substr(9,1)}if(12==a.length){for(var e=0,f=[7,2,4,10,3,5,9,4,6,8,0],g=0,h=[3,7,2,4,10,3,5,9,4,6,8,0],d=0;11>d;d++)e+=parseInt(a.charAt(d))*f[d],g+=parseInt(a.charAt(d))*h[d];return e%=11,e>9&&(e%=10),g%=11,g>9&&(g%=10),e==a.substr(10,1)&&g==a.substr(11,1)}return!1},_rs:function(a){if(!/^RS[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=10,c=0,d=0;8>d;d++)c=(parseInt(a.charAt(d))+b)%10,0==c&&(c=10),b=2*c%11;return(b+parseInt(a.substr(8,1)))%10==1},_se:function(b){return/^SE[0-9]{10}01$/.test(b)?(b=b.substr(2,10),a.fn.bootstrapValidator.helpers.luhn(b)):!1},_si:function(a){if(!/^SI[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[8,7,6,5,4,3,2],d=0;7>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,10==b&&(b=0),b==a.substr(7,1)},_sk:function(a){return/^SK[1-9][0-9][(2-4)|(6-9)][0-9]{7}$/.test(a)?(a=a.substr(2),a%11==0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.vin={validate:function(a,b){var c=b.val();if(""==c)return!0;if(!/^[a-hj-npr-z0-9]{8}[0-9xX][a-hj-npr-z0-9]{8}$/i.test(c))return!1;c=c.toUpperCase();for(var d={A:1,B:2,C:3,D:4,E:5,F:6,G:7,H:8,J:1,K:2,L:3,M:4,N:5,P:7,R:9,S:2,T:3,U:4,V:5,W:6,X:7,Y:8,Z:9,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,0:0},e=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],f=0,g=c.length,h=0;g>h;h++)f+=d[c.charAt(h)+""]*e[h];var i=f%11;return 10==i&&(i="X"),i==c.charAt(8)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.zipCode={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d||!c.country)return!0;var e=(c.country||"US").toUpperCase();switch(e){case"CA":return/(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}\s?[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}/i.test(d);case"DK":return/^(DK(-|\s)?)?\d{4}$/i.test(d);case"SE":return/^(S-)?\d{3}\s?\d{2}$/i.test(d);case"US":default:return/^\d{4,5}([\-]\d{4})?$/.test(d)}}}}(window.jQuery); \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.4/css/bootstrapValidator.css b/ajax/libs/jquery.bootstrapvalidator/0.4.4/css/bootstrapValidator.css new file mode 100644 index 000000000..b23db97b8 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.4/css/bootstrapValidator.css @@ -0,0 +1,19 @@ +/** + * BootstrapValidator (https://github.com/nghuuphuoc/bootstrapvalidator) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @author http://twitter.com/nghuuphuoc + * @copyright (c) 2014 Nguyen Huu Phuoc + * @license MIT + */ + +.bv-form .help-block { + margin-bottom: 0; +} +.nav-tabs li.bv-tab-success > a { + color: #3c763d; +} +.nav-tabs li.bv-tab-error > a { + color: #a94442; +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.4/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.4.4/css/bootstrapValidator.min.css new file mode 100644 index 000000000..70c1136cf --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.4/css/bootstrapValidator.min.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.4 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + + +.bv-form .help-block{margin-bottom:0}.nav-tabs li.bv-tab-success>a{color:#3c763d}.nav-tabs li.bv-tab-error>a{color:#a94442} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.4/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.4.4/js/bootstrapValidator.js new file mode 100644 index 000000000..b917647cb --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.4/js/bootstrapValidator.js @@ -0,0 +1,3952 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.4 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + this.$invalidField = null; // First invalid field + this.$submitButton = null; // The submit button which is clicked to submit form + + // Validating status + this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED'; + this.STATUS_VALIDATING = 'VALIDATING'; + this.STATUS_INVALID = 'INVALID'; + this.STATUS_VALID = 'VALID'; + + // Determine the event that is fired when user change the field value + // Most modern browsers supports input event except IE 7, 8. + // IE 9 supports input event but the event is still not fired if I press the backspace key. + // Get IE version + // https://gist.github.com/padolsey/527683/#comment-7595 + var ieVersion = (function() { + var v = 3, div = document.createElement('div'), a = div.all || []; + while (div.innerHTML = '', a[0]); + return v > 4 ? v : !v; + }()); + + var el = document.createElement('div'); + this._changeEvent = (ieVersion === 9 || !('oninput' in el)) ? 'keyup' : 'input'; + + // The flag to indicate that the form is ready to submit when a remote/callback validator returns + this._submitIfValid = null; + + this._init(); + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bv-form', + + // Default invalid message + message: 'This value is not valid', + + // Indicate fields which won't be validated + // By default, the plugin will not validate the following kind of fields: + // - disabled + // - hidden + // - invisible + // + // The setting consists of jQuery filters. Accept 3 formats: + // - A string. Use a comma to separate filter + // - An array. Each element is a filter + // - An array. Each element can be a callback function + // function($field, validator) { + // $field is jQuery object representing the field element + // validator is the BootstrapValidator instance + // return true or false; + // } + // + // The 3 following settings are equivalent: + // + // 1) ':disabled, :hidden, :not(:visible)' + // 2) [':disabled', ':hidden', ':not(:visible)'] + // 3) [':disabled', ':hidden', function($field) { + // return !$field.is(':visible'); + // }] + excluded: [':disabled', ':hidden', ':not(:visible)'], + + // Shows ok/error/loading icons based on the field validity. + // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation). + // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically. + // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later. + // + // Examples: + // - Use Glyphicons icons: + // feedbackIcons: { + // valid: 'glyphicon glyphicon-ok', + // invalid: 'glyphicon glyphicon-remove', + // validating: 'glyphicon glyphicon-refresh' + // } + // - Use FontAwesome icons: + // feedbackIcons: { + // valid: 'fa fa-check', + // invalid: 'fa fa-times', + // validating: 'fa fa-refresh' + // } + feedbackIcons: { + valid: null, + invalid: null, + validating: null + }, + + // The submit buttons selector + // These buttons will be disabled to prevent the valid form from multiple submissions + submitButtons: 'button[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submission + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating option + // Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + var that = this, + options = { + excluded: this.$form.attr('data-bv-excluded'), + trigger: this.$form.attr('data-bv-trigger'), + message: this.$form.attr('data-bv-message'), + submitButtons: this.$form.attr('data-bv-submitbuttons'), + live: this.$form.attr('data-bv-live'), + 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') + } + }, + validator, + v, // Validator name + enabled, + optionName, + optionValue, + html5AttrName, + html5Attrs; + + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + // Disable the default submission first + .on('submit.bv', function(e) { + e.preventDefault(); + that.validate(); + }) + .on('click', this.options.submitButtons, function() { + that.$submitButton = $(this); + // The user just click the submit button + that._submitIfValid = true; + }) + // Find all fields which have either "name" or "data-bv-field" attribute + .find('[name], [data-bv-field]').each(function() { + var $field = $(this); + // Don't initialize hidden input + if ('hidden' == $field.attr('type')) { + return; + } + + var field = $field.attr('name') || $field.attr('data-bv-field'); + $field.attr('data-bv-field', field); + + options.fields[field] = $.extend({}, { + trigger: $field.attr('data-bv-trigger'), + message: $field.attr('data-bv-message'), + container: $field.attr('data-bv-container'), + selector: $field.attr('data-bv-selector'), + validators: {} + }, options.fields[field]); + + for (v in $.fn.bootstrapValidator.validators) { + validator = $.fn.bootstrapValidator.validators[v]; + enabled = $field.attr('data-bv-' + v.toLowerCase()) + ''; + html5Attrs = ('function' == typeof validator.enableByHtml5) ? validator.enableByHtml5($(this)) : null; + + if ((html5Attrs && enabled != 'false') + || (html5Attrs !== true && ('' == enabled || 'true' == enabled))) + { + // Try to parse the options via attributes + validator.html5Attributes = validator.html5Attributes || { message: 'message' }; + options.fields[field]['validators'][v] = $.extend({}, html5Attrs == true ? {} : html5Attrs, options.fields[field]['validators'][v]); + + for (html5AttrName in validator.html5Attributes) { + optionName = validator.html5Attributes[html5AttrName]; + optionValue = $field.attr('data-bv-' + v.toLowerCase() + '-' + html5AttrName); + if (optionValue) { + if ('true' == optionValue) { + optionValue = true; + } else if ('false' == optionValue) { + optionValue = false; + } + options.fields[field]['validators'][v][optionName] = optionValue; + } + } + } + } + }); + + this.options = $.extend(true, this.options, options); + if ('string' == typeof this.options.excluded) { + this.options.excluded = $.map(this.options.excluded.split(','), function(item) { + // Trim the spaces + return $.trim(item); + }); + } + + for (var field in this.options.fields) { + this._initField(field); + } + + this.setLiveMode(this.options.live); + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + var fields = this.getFieldElements(field); + + // We don't need to validate non-existing fields + if (fields == null) { + delete this.options.fields[field]; + return; + } + for (var validatorName in this.options.fields[field].validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + delete this.options.fields[field].validators[validatorName]; + } + } + + var that = this, + type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent, + total = fields.length, + updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type); + + for (var i = 0; i < total; i++) { + var $field = $(fields[i]), + $parent = $field.parents('.form-group'), + // Allow user to indicate where the error messages are shown + $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field); + + // Set the attribute to indicate the fields which are defined by selector + if (this.options.fields[field].selector) { + $field.attr('data-bv-field', field); + } + + // Whenever the user change the field value, mark it as not validated yet + $field.on(event + '.update.bv', function() { + // Reset the flag + that._submitIfValid = false; + updateAll ? that.updateStatus(field, that.STATUS_NOT_VALIDATED, null) + : that.updateElementStatus($(this), that.STATUS_NOT_VALIDATED, null); + }); + + // Create help block elements for showing the error messages + $field.data('bv.messages', $message); + for (validatorName in this.options.fields[field].validators) { + $field.data('bv.result.' + validatorName, this.STATUS_NOT_VALIDATED); + + if (!updateAll || i == total - 1) { + $('') + .css('display', 'none') + .attr('data-bv-validator', validatorName) + .attr('data-bv-validator-for', field) + .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message) + .addClass('help-block') + .appendTo($message); + } + } + + // Prepare the feedback icons + // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation) + if (this.options.feedbackIcons + && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid + && (!updateAll || i == total - 1)) + { + $parent.addClass('has-feedback'); + var $icon = $('').css('display', 'none').addClass('form-control-feedback').attr('data-bv-field', field).insertAfter($field); + // The feedback icon does not render correctly if there is no label + // https://github.com/twbs/bootstrap/issues/12873 + if ($parent.find('label').length == 0) { + $icon.css('top', 0); + } + } + } + + if (this.options.fields[field]['enabled'] == null) { + this.options.fields[field]['enabled'] = true; + } + }, + + /** + * Get the element to place the error messages + * + * @param {jQuery} $field The field element + * @returns {jQuery} + */ + _getMessageContainer: function($field) { + var $parent = $field.parent(); + if ($parent.hasClass('form-group')) { + return $parent; + } + + var cssClasses = $parent.attr('class'); + if (!cssClasses) { + return this._getMessageContainer($parent); + } + + cssClasses = cssClasses.split(' '); + var n = cssClasses.length; + for (var i = 0; i < n; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i]) || /^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + return $parent; + } + } + + return this._getMessageContainer($parent); + }, + + /** + * Called when all validations are completed + */ + _submit: function() { + if (!this.isValid()) { + if ('submitted' == this.options.live) { + this.setLiveMode('enabled'); + } + + // Focus to the first invalid field + if (this.$invalidField) { + // Activate the tab containing the invalid field if exists + var $tab = this.$invalidField.parents('.tab-pane'), + tabId; + if ($tab && (tabId = $tab.attr('id'))) { + $('a[href="#' + tabId + '"][data-toggle="tab"]').trigger('click.bs.tab.data-api'); + } + + this.$invalidField.focus(); + } + + return; + } + + // Call the custom submission if enabled + if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + // If you want to submit the form inside your submit handler, please call defaultSubmit() method + this.options.submitHandler.call(this, this, this.$form, this.$submitButton); + } else { + this.disableSubmitButtons(true).defaultSubmit(); + } + }, + + /** + * Check if the field is excluded. + * Returning true means that the field will not be validated + * + * @param {jQuery} $field The field element + * @return {Boolean} + */ + _isExcluded: function($field) { + if (this.options.excluded) { + for (var i in this.options.excluded) { + if (('string' == typeof this.options.excluded[i] && $field.is(this.options.excluded[i])) + || ('function' == typeof this.options.excluded[i] && this.options.excluded[i].call(this, $field, this) == true)) + { + return true; + } + } + } + + return false; + }, + + // --- Public methods --- + + /** + * Retrieve the field elements by given name + * + * @param {String} field The field name + * @returns {null|jQuery[]} + */ + getFieldElements: function(field) { + var fields = this.options.fields[field].selector ? $(this.options.fields[field].selector) : this.$form.find('[name="' + field + '"]'); + return (fields.length == 0) ? null : fields; + }, + + /** + * Set live validating mode + * + * @param {String} mode Live validating mode. Can be 'enabled', 'disabled', 'submitted' + * @returns {BootstrapValidator} + */ + setLiveMode: function(mode) { + this.options.live = mode; + if ('submitted' == mode) { + return this; + } + + var that = this; + for (var field in this.options.fields) { + (function(f) { + var fields = that.getFieldElements(f); + if (fields) { + var type = fields.attr('type'), + total = fields.length, + updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type), + trigger = that.options.fields[field].trigger + || that.options.trigger + || (('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent), + events = $.map(trigger.split(' '), function(item) { + return item + '.live.bv'; + }).join(' '); + + for (var i = 0; i < total; i++) { + ('enabled' == mode) + ? $(fields[i]).on(events, function() { + updateAll ? that.validateField(f) : that.validateFieldElement($(this), false); + }) + : $(fields[i]).off(events); + } + } + })(field); + } + + return this; + }, + + /** + * Disable/enable submit buttons + * + * @param {Boolean} disabled Can be true or false + * @returns {BootstrapValidator} + */ + disableSubmitButtons: function(disabled) { + if (!disabled) { + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + } else if (this.options.live != 'disabled') { + // Don't disable if the live validating mode is disabled + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + } + + return this; + }, + + /** + * Validate the form + * + * @return {BootstrapValidator} + */ + validate: function() { + if (!this.options.fields) { + return this; + } + this.disableSubmitButtons(true); + + for (var field in this.options.fields) { + this.validateField(field); + } + + // Check if whether the submit button is clicked + if (this.$submitButton) { + this._submit(); + } + + return this; + }, + + /** + * Validate given field + * + * @param {String} field The field name + * @returns {BootstrapValidator} + */ + validateField: function(field) { + var fields = this.getFieldElements(field), + type = fields.attr('type'), + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (var i = 0; i < n; i++) { + this.validateFieldElement($(fields[i]), (n == 1)); + } + + return this; + }, + + /** + * Validate field element + * + * @param {jQuery} $field The field element + * @param {Boolean} updateAll If true, update status of all elements which have the same name + * @returns {BootstrapValidator} + */ + validateFieldElement: function($field, updateAll) { + var that = this, + field = $field.attr('data-bv-field'), + validators = this.options.fields[field].validators, + validatorName, + validateResult; + + if (!this.options.fields[field]['enabled'] || this._isExcluded($field)) { + return this; + } + + for (validatorName in validators) { + if ($field.data('bv.dfs.' + validatorName)) { + $field.data('bv.dfs.' + validatorName).reject(); + } + + // Don't validate field if it is already done + var result = $field.data('bv.result.' + validatorName); + if (result == this.STATUS_VALID || result == this.STATUS_INVALID) { + continue; + } + + $field.data('bv.result.' + validatorName, this.STATUS_VALIDATING); + validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]); + + if ('object' == typeof validateResult) { + updateAll ? this.updateStatus(field, this.STATUS_VALIDATING, validatorName) + : this.updateElementStatus($field, this.STATUS_VALIDATING, validatorName); + $field.data('bv.dfs.' + validatorName, validateResult); + + validateResult.done(function($f, v, isValid) { + // v is validator name + $f.removeData('bv.dfs.' + v); + updateAll ? that.updateStatus($f.attr('data-bv-field'), isValid ? that.STATUS_VALID : that.STATUS_INVALID, v) + : that.updateElementStatus($f, isValid ? that.STATUS_VALID : that.STATUS_INVALID, v); + + if (isValid && that._submitIfValid == true) { + // If a remote validator returns true and the form is ready to submit, then do it + that._submit(); + } + }); + } else if ('boolean' == typeof validateResult) { + updateAll ? this.updateStatus(field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName) + : this.updateElementStatus($field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName); + } + } + + return this; + }, + + /** + * Update all validating results of elements which have the same field name + * + * @param {String} field The field name + * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateStatus: function(field, status, validatorName) { + var fields = this.getFieldElements(field), + type = fields.attr('type'), + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (var i = 0; i < n; i++) { + this.updateElementStatus($(fields[i]), status, validatorName); + } + + return this; + }, + + /** + * Update validating result of given element + * + * @param {jQuery} $field The field element + * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators + * @return {BootstrapValidator} + */ + updateElementStatus: function($field, status, validatorName) { + var that = this, + field = $field.attr('data-bv-field'), + $parent = $field.parents('.form-group'), + $message = $field.data('bv.messages'), + $errors = $message.find('.help-block[data-bv-validator]'), + $icon = $parent.find('.form-control-feedback[data-bv-field="' + field + '"]'); + + // Update status + if (validatorName) { + $field.data('bv.result.' + validatorName, status); + } else { + for (var v in this.options.fields[field].validators) { + $field.data('bv.result.' + v, status); + } + } + + // Determine the tab containing the element + var $tabPane = $field.parents('.tab-pane'), + tabId, + $tab; + if ($tabPane && (tabId = $tabPane.attr('id'))) { + $tab = $('a[href="#' + tabId + '"][data-toggle="tab"]').parent(); + } + + // Show/hide error elements and feedback icons + switch (status) { + case this.STATUS_VALIDATING: + this.disableSubmitButtons(true); + $parent.removeClass('has-success').removeClass('has-error'); + // TODO: Show validating message + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(); + } + if ($tab) { + $tab.removeClass('bv-tab-success').removeClass('bv-tab-error'); + } + break; + + case this.STATUS_INVALID: + this.disableSubmitButtons(true); + $parent.removeClass('has-success').addClass('has-error'); + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').show() : $errors.show(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(); + } + if ($tab) { + $tab.removeClass('bv-tab-success').addClass('bv-tab-error'); + } + break; + + case this.STATUS_VALID: + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + + // If the field is valid (passes all validators) + var validField = ($errors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || ($field.data('bv.result.' + v) != that.STATUS_VALID); + }).length == 0); + this.disableSubmitButtons(validField ? false : true); + if ($icon) { + $icon + .removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid) + .addClass(validField ? this.options.feedbackIcons.valid : this.options.feedbackIcons.invalid) + .show(); + } + + // Check if all elements in given container are valid + var isValidContainer = function($container) { + return $container + .find('.help-block[data-bv-validator]') + .filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || ($field.data('bv.result.' + v) && $field.data('bv.result.' + v) != that.STATUS_VALID); + }) + .length == 0; + }; + $parent.removeClass('has-error has-success').addClass(isValidContainer($parent) ? 'has-success' : 'has-error'); + if ($tab) { + $tab.removeClass('bv-tab-success').removeClass('bv-tab-error').addClass(isValidContainer($tabPane) ? 'bv-tab-success' : 'bv-tab-error'); + } + break; + + case this.STATUS_NOT_VALIDATED: + default: + this.disableSubmitButtons(false); + $parent.removeClass('has-success').removeClass('has-error'); + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide(); + } + if ($tab) { + $tab.removeClass('bv-tab-success').removeClass('bv-tab-error'); + } + break; + } + + return this; + }, + + /** + * Check the form validity + * + * @returns {Boolean} + */ + isValid: function() { + var fields, field, $field, + type, status, validatorName, + n, i; + for (field in this.options.fields) { + if (this.options.fields[field] == null || !this.options.fields[field]['enabled']) { + continue; + } + + fields = this.getFieldElements(field); + type = fields.attr('type'); + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (i = 0; i < n; i++) { + $field = $(fields[i]); + if (this._isExcluded($field)) { + continue; + } + + for (validatorName in this.options.fields[field].validators) { + status = $field.data('bv.result.' + validatorName); + if (status == this.STATUS_NOT_VALIDATED || status == this.STATUS_VALIDATING) { + return false; + } + + if (status == this.STATUS_INVALID) { + this.$invalidField = $field; + return false; + } + } + } + } + + return true; + }, + + /** + * Submit the form using default submission. + * It also does not perform any validations when submitting the form + * + * It might be used when you want to submit the form right inside the submitHandler() + */ + defaultSubmit: function() { + this.$form.off('submit.bv').submit(); + }, + + // Useful APIs which aren't used internally + + /** + * Reset the form + * + * @param {Boolean} resetFormData Reset current form data + * @return {BootstrapValidator} + */ + resetForm: function(resetFormData) { + var field, fields, total, type, validator; + for (field in this.options.fields) { + fields = this.getFieldElements(field); + total = fields.length; + + for (var i = 0; i < total; i++) { + for (validator in this.options.fields[field].validators) { + $(fields[i]).removeData('bv.dfs.' + validator); + } + } + + // Mark field as not validated yet + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + if (resetFormData) { + type = fields.attr('type'); + ('radio' == type || 'checkbox' == type) ? fields.removeAttr('checked').removeAttr('selected') : fields.val(''); + } + } + + this.$invalidField = null; + this.$submitButton = null; + + // Enable submit buttons + this.disableSubmitButtons(false); + + return this; + }, + + /** + * Enable/Disable all validators to given field + * + * @param {String} field The field name + * @param {Boolean} enabled Enable/Disable field validators + * @return {BootstrapValidator} + */ + enableFieldValidators: function(field, enabled) { + this.options.fields[field]['enabled'] = enabled; + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + return this; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(option, params) { + return this.each(function() { + var $this = $(this), + data = $this.data('bootstrapValidator'), + options = 'object' == typeof option && option; + if (!data) { + data = new BootstrapValidator(this, options); + $this.data('bootstrapValidator', data); + } + + // Allow to call plugin method + if ('string' == typeof option) { + data[option](params); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; + + // Helper methods, which can be used in validator class + $.fn.bootstrapValidator.helpers = { + /** + * Implement Luhn validation algorithm ((http://en.wikipedia.org/wiki/Luhn)) + * Credit to https://gist.github.com/ShirtlessKirk/2134376 + * + * @param {String} value + * @returns {Boolean} + */ + luhn: function(value) { + var length = value.length, + mul = 0, + prodArr = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]], + sum = 0; + + while (length--) { + sum += prodArr[mul][parseInt(value.charAt(length), 10)]; + mul ^= 1; + } + + return (sum % 10 === 0 && sum > 0); + }, + + /** + * Implement modulus 11, 10 (ISO 7064) algorithm + * + * @param {String} value + * @returns {Boolean} + */ + mod_11_10: function(value) { + var check = 5, + length = value.length; + for (var i = 0; i < length; i++) { + check = (((check || 10) * 2) % 11 + parseInt(value.charAt(i), 10)) % 10; + } + return (check == 1); + }, + + /** + * Implements Mod 37, 36 (ISO 7064) algorithm + * Usages: + * mod_37_36('A12425GABC1234002M') + * mod_37_36('002006673085', '0123456789') + * + * @param {String} value + * @param {String} alphabet + * @returns {Boolean} + */ + mod_37_36: function(value, alphabet) { + alphabet = alphabet || '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + var modulus = alphabet.length, + length = value.length, + check = Math.floor(modulus / 2); + for (var i = 0; i < length; i++) { + check = (((check || modulus) * 2) % (modulus + 1) + alphabet.indexOf(value.charAt(i))) % modulus; + } + return (check == 1); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.base64 = { + /** + * Return true if the input value is a base 64 encoded string. + * + * @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; + } + + return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + if ('range' == $field.attr('type')) { + return { + min: $field.attr('min'), + max: $field.attr('max') + }; + } + + return false; + }, + + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = parseFloat(value); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {Boolean|Deferred} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (options.callback && 'function' == typeof options.callback) { + var dfd = new $.Deferred(); + dfd.resolve($field, 'callback', options.callback.call(this, value, validator)); + return dfd; + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.choice = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max' + }, + + /** + * Check if the number of checked boxes are less or more than a given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var numChoices = $field.is('select') + ? validator.getFieldElements($field.attr('data-bv-field')).find('option').filter(':selected').length + : validator.getFieldElements($field.attr('data-bv-field')).filter(':checked').length; + if ((options.min && numChoices < options.min) || (options.max && numChoices > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + value = value.replace(/\D/g, ''); + + if (!$.fn.bootstrapValidator.helpers.luhn(value)) { + return false; + } + + // Validate the card number based on prefix (IIN ranges) and length + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['6304', '6706', '6771', '6709'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + + var type, i; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (value.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(value.length) != -1) // and length + { + return true; + } + } + } + + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.cvv = { + html5Attributes: { + message: 'message', + ccfield: 'creditCardField' + }, + + /** + * Return true if the input value is a valid CVV number. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - creditCardField: The credit card number field. It can be null + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^[0-9]{3,4}$/.test(value)) { + return false; + } + + if (!options.creditCardField) { + return true; + } + + // Get the credit card number + var creditCard = validator.getFieldElements(options.creditCardField).val(); + if (creditCard == '') { + return true; + } + + // Supported credit card types + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['6304', '6706', '6771', '6709'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + var type, i, creditCardType = null; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (creditCard.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(creditCard.length) != -1) // and length + { + creditCardType = type; + break; + } + } + } + + return (creditCardType == null) + ? false + : (('AMERICAN_EXPRESS' == creditCardType) ? (value.length == 4) : (value.length == 3)); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.date = { + html5Attributes: { + message: 'message', + format: 'format' + }, + + /** + * Return true if the input value is valid date + * + * @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 + * - format: The date format. Default is MM/DD/YYYY + * The format can be: + * + * i) date: Consist of DD, MM, YYYY parts which are separated by / + * ii) date and time: + * The time can consist of h, m, s parts which are separated by : + * ii) date, time and A (indicating AM or PM) + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options.format = options.format || 'MM/DD/YYYY'; + + 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(' '), + date = sections[0], + time = (sections.length > 1) ? sections[1] : null; + + if (formats.length != sections.length) { + return false; + } + + // Determine the separator + var separator = (date.indexOf('/') != -1) ? '/' : ((date.indexOf('-') != -1) ? '-' : null); + if (separator == null) { + return false; + } + + // Determine the date + date = date.split(separator); + dateFormat = dateFormat.split(separator); + var year = date[dateFormat.indexOf('YYYY')], + month = date[dateFormat.indexOf('MM')], + day = date[dateFormat.indexOf('DD')]; + + // Determine the time + var minutes = null, hours = null, seconds = null; + if (timeFormat) { + timeFormat = timeFormat.split(':'), + time = time.split(':'); + + if (timeFormat.length != time.length) { + return false; + } + + hours = time.length > 0 ? time[0] : null; + minutes = time.length > 1 ? time[1] : null; + seconds = time.length > 2 ? time[2] : null; + + // Validate seconds + if (seconds) { + seconds = parseInt(seconds, 10); + if (seconds < 0 || seconds > 60) { + return false; + } + } + + // Validate hours + if (hours) { + hours = parseInt(hours, 10); + if (hours < 0 || hours >= 24 || (amOrPm && hours > 12)) { + return false; + } + } + + // Validate minutes + if (minutes) { + minutes = parseInt(minutes, 10); + if (minutes < 0 || minutes > 59) { + return false; + } + } + } + + // Validate day, month, and year + day = parseInt(day, 10); + month = parseInt(month, 10); + year = parseInt(year, 10); + + if (year < 1000 || year > 9999 || month == 0 || month > 12) { + return false; + } + + var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + // Update the number of days in Feb of leap year + if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) { + numDays[1] = 29; + } + + // Check the day + return (day > 0 && day <= numDays[month - 1]); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.different = { + html5Attributes: { + message: 'message', + field: 'field' + }, + + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value != compareWith.val()) { + validator.updateStatus(options.field, validator.STATUS_VALID, 'different'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^\d+$/.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.ean = { + /** + * Validate EAN (International Article Number) + * Examples: + * - Valid: 73513537, 9780471117094, 4006381333931 + * - Invalid: 73513536 + * + * @see http://en.wikipedia.org/wiki/European_Article_Number + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^(\d{8}|\d{12}|\d{13})$/.test(value)) { + return false; + } + + var length = value.length, + sum = 0, + weight = (length == 8) ? [3, 1] : [1, 3]; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * weight[i % 2]; + } + sum = 10 - sum % 10; + return (sum == value.charAt(length - 1)); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + enableByHtml5: function($field) { + return ('email' == $field.attr('type')); + }, + + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.file = { + html5Attributes: { + extension: 'extension', + maxsize: 'maxSize', + message: 'message', + type: 'type' + }, + + /** + * Validate upload file. Use HTML 5 API if the browser supports + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - extension: The allowed extensions, separated by a comma + * - maxSize: The maximum size in bytes + * - message: The invalid message + * - type: The allowed MIME type, separated by a comma + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var ext, + extensions = options.extension ? options.extension.split(',') : null, + types = options.type ? options.type.split(',') : null, + html5 = (window.File && window.FileList && window.FileReader); + + if (html5) { + // Get FileList instance + var files = $field.get(0).files, + total = files.length; + for (var i = 0; i < total; i++) { + // Check file size + if (options.maxSize && files[i].size > parseInt(options.maxSize)) { + return false; + } + + // Check file extension + ext = files[i].name.substr(files[i].name.lastIndexOf('.') + 1); + if (extensions && extensions.indexOf(ext) == -1) { + return false; + } + + // Check file type + if (types && types.indexOf(files[i].type) == -1) { + return false; + } + } + } else { + // Check file extension + ext = value.substr(value.lastIndexOf('.') + 1); + if (extensions && extensions.indexOf(ext) == -1) { + return false; + } + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + html5Attributes: { + message: 'message', + value: 'value', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + var min = $field.attr('min'); + if (min) { + return { + value: min + }; + } + + return false; + }, + + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.grid = { + /** + * Validate GRId (Global Release Identifier) + * Examples: + * - Valid: A12425GABC1234002M, A1-2425G-ABC1234002-M, A1 2425G ABC1234002 M, Grid:A1-2425G-ABC1234002-M + * - Invalid: A1-2425G-ABC1234002-Q + * + * @see http://en.wikipedia.org/wiki/Global_Release_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; + } + + value = value.toUpperCase(); + if (!/^[GRID:]*([0-9A-Z]{2})[-\s]*([0-9A-Z]{5})[-\s]*([0-9A-Z]{10})[-\s]*([0-9A-Z]{1})$/g.test(value)) { + return false; + } + value = value.replace(/\s/g, '').replace(/-/g, ''); + if ('GRID:' == value.substr(0, 5)) { + value = value.substr(5); + } + return $.fn.bootstrapValidator.helpers.mod_37_36(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hex = { + /** + * Return true if and only if the input value is a valid hexadecimal number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^[0-9a-fA-F]+$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + enableByHtml5: function($field) { + return ('color' == $field.attr('type')); + }, + + /** + * Return true if the input value is a valid hex color + * + * @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; + } + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.iban = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Validate an International Bank Account Number (IBAN) + * To test it, take the sample IBAN from + * http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html + * + * @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 + * - country: The ISO 3166-1 country code + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // See + // http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf + // http://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country + var ibanRegex = { + '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 + }; + value = value.replace(/[^a-zA-Z0-9]/g, '').toUpperCase(); + var country = options.country || value.substr(0, 2); + if (!ibanRegex[country]) { + return false; + } + if (!(new RegExp('^' + ibanRegex[country] + '$')).test(value)) { + return false; + } + + value = value.substr(4) + value.substr(0, 4); + value = value.split('').map(function(n) { + var code = n.charCodeAt(0); + return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) + // Replace A, B, C, ..., Z with 10, 11, ..., 35 + ? (code - 'A'.charCodeAt(0) + 10) + : n; + }).join(''); + + var temp = parseInt(value.substr(0, 1), 10), + length = value.length; + for (var i = 1; i < length; ++i) { + temp = (temp * 10 + parseInt(value.substr(i, 1), 10)) % 97; + } + return (temp == 1); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + html5Attributes: { + message: 'message', + field: 'field' + }, + + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value == compareWith.val()) { + validator.updateStatus(options.field, validator.STATUS_VALID, 'identical'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.imei = { + /** + * Validate IMEI (International Mobile Station Equipment Identity) + * Examples: + * - Valid: 35-209900-176148-1, 35-209900-176148-23, 3568680000414120, 490154203237518 + * - Invalid: 490154203237517 + * + * @see http://en.wikipedia.org/wiki/International_Mobile_Station_Equipment_Identity + * @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) { + case /^\d{15}$/.test(value): + case /^\d{2}-\d{6}-\d{6}-\d{1}$/.test(value): + case /^\d{2}\s\d{6}\s\d{6}\s\d{1}$/.test(value): + value = value.replace(/[^0-9]/g, ''); + return $.fn.bootstrapValidator.helpers.luhn(value); + break; + + case /^\d{14}$/.test(value): + case /^\d{16}$/.test(value): + case /^\d{2}-\d{6}-\d{6}(|-\d{2})$/.test(value): + case /^\d{2}\s\d{6}\s\d{6}(|\s\d{2})$/.test(value): + return true; + + default: + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.integer = { + enableByHtml5: function($field) { + return ('number' == $field.attr('type')); + }, + + /** + * Return true if the input value is an integer + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + return /^(?:-?(?:0|[1-9][0-9]*))$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.ip = { + html5Attributes: { + message: 'message', + ipv4: 'ipv4', + ipv6: 'ipv6' + }, + + /** + * Return true if the input value is a IP address. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - ipv4: Enable IPv4 validator, default to true + * - ipv6: Enable IPv6 validator, default to true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + options = $.extend({}, { ipv4: true, ipv6: true }, options); + + if (options.ipv4) { + return /^(?:(?: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); + } else if (options.ipv6) { + return /^\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(str); + } + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.isbn = { + /** + * Return true if the input value is a valid ISBN 10 or ISBN 13 number + * Examples: + * - Valid: + * ISBN 10: 99921-58-10-7, 9971-5-0210-0, 960-425-059-0, 80-902734-1-6, 85-359-0277-5, 1-84356-028-3, 0-684-84328-5, 0-8044-2957-X, 0-85131-041-9, 0-943396-04-2, 0-9752298-0-X + * ISBN 13: 978-0-306-40615-7 + * - Invalid: + * ISBN 10: 99921-58-10-6 + * ISBN 13: 978-0-306-40615-6 + * + * @see http://en.wikipedia.org/wiki/International_Standard_Book_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; + } + + // http://en.wikipedia.org/wiki/International_Standard_Book_Number#Overview + // Groups are separated by a hyphen or a space + var type; + switch (true) { + case /^\d{9}[\dX]$/.test(value): + case (value.length == 13 && /^(\d+)-(\d+)-(\d+)-([\dX])$/.test(value)): + case (value.length == 13 && /^(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(value)): + type = 'ISBN10'; + break; + case /^(978|979)\d{9}[\dX]$/.test(value): + case (value.length == 17 && /^(978|979)-(\d+)-(\d+)-(\d+)-([\dX])$/.test(value)): + case (value.length == 17 && /^(978|979)\s(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(value)): + type = 'ISBN13'; + break; + default: + return false; + } + + // Replace all special characters except digits and X + value = value.replace(/[^0-9X]/gi, ''); + var chars = value.split(''), + length = chars.length, + sum = 0, + checksum; + + switch (type) { + case 'ISBN10': + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += ((10 - i) * parseInt(chars[i])); + } + checksum = 11 - (sum % 11); + if (checksum == 11) { + checksum = 0; + } else if (checksum == 10) { + checksum = 'X'; + } + return (checksum + '' == chars[length - 1]); + + case 'ISBN13': + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += ((i % 2 == 0) ? parseInt(chars[i]) : (parseInt(chars[i]) * 3)); + } + checksum = 10 - (sum % 10); + if (checksum == 10) { + checksum = '0'; + } + return (checksum + '' == chars[length - 1]); + + default: + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.ismn = { + /** + * Validate ISMN (International Standard Music Number) + * Examples: + * - Valid: M230671187, 979-0-0601-1561-5, 979 0 3452 4680 5, 9790060115615 + * - Invalid: 9790060115614 + * + * @see http://en.wikipedia.org/wiki/International_Standard_Music_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; + } + + // Groups are separated by a hyphen or a space + var type; + switch (true) { + case /^M\d{9}$/.test(value): + case /^M-\d{4}-\d{4}-\d{1}$/.test(value): + case /^M\s\d{4}\s\d{4}\s\d{1}$/.test(value): + type = 'ISMN10'; + break; + case /^9790\d{9}$/.test(value): + case /^979-0-\d{4}-\d{4}-\d{1}$/.test(value): + case /^979\s0\s\d{4}\s\d{4}\s\d{1}$/.test(value): + type = 'ISMN13'; + break; + default: + return false; + } + + if ('ISMN10' == type) { + value = '9790' + value.substr(1); + } + + // Replace all special characters except digits + value = value.replace(/[^0-9]/gi, ''); + var length = value.length, + sum = 0, + weight = [1, 3]; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * weight[i % 2]; + } + sum = 10 - sum % 10; + return (sum == value.charAt(length - 1)); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.issn = { + /** + * Validate ISSN (International Standard Serial Number) + * Examples: + * - Valid: 0378-5955, 0024-9319, 0032-1478 + * - Invalid: 0032-147X + * + * @see http://en.wikipedia.org/wiki/International_Standard_Serial_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; + } + + // Groups are separated by a hyphen or a space + if (!/^\d{4}\-\d{3}[\dX]$/.test(value)) { + return false; + } + + // Replace all special characters except digits and X + value = value.replace(/[^0-9X]/gi, ''); + var chars = value.split(''), + length = chars.length, + sum = 0; + + if (chars[7] == 'X') { + chars[7] = 10; + } + for (var i = 0; i < length; i++) { + sum += ((8 - i) * parseInt(chars[i])); + } + return (sum % 11 == 0); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + html5Attributes: { + message: 'message', + value: 'value', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + var max = $field.attr('max'); + if (max) { + return { + value: max + }; + } + + return false; + }, + + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === false) ? (value <= options.value) : (value < options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.mac = { + /** + * Return true if the input value is a MAC address. + * + * @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; + } + + return /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + enableByHtml5: function($field) { + var required = $field.attr('required') + ''; + return ('required' == required || 'true' == required); + }, + + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + if ('radio' == type || 'checkbox' == type) { + return validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length > 0; + } + + return $.trim($field.val()) != ''; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.numeric = { + /** + * Validate decimal number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return !isNaN(parseFloat(value)) && isFinite(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.phone = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Return true if the input value contains a valid US phone number only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166 country code + * Currently it only supports United State (US) country + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var country = (options.country || 'US').toUpperCase(); + switch (country) { + case 'US': + default: + // Make sure US phone numbers have 10 digits + // May start with 1, +1, or 1-; should discard + // Area code may be delimited with (), & sections may be delimited with . or - + // Test: http://regexr.com/38mqi + value = value.replace(/\D/g, ''); + return (/^(?:(1\-?)|(\+1 ?))?\(?(\d{3})[\)\-\.]?(\d{3})[\-\.]?(\d{4})$/).test(value) && (value.length == 10); + } + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + html5Attributes: { + message: 'message', + regexp: 'regexp' + }, + + enableByHtml5: function($field) { + var pattern = $field.attr('pattern'); + if (pattern) { + return { + regexp: pattern + }; + } + + return false; + }, + + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var regexp = ('string' == typeof options.regexp) ? new RegExp(options.regexp) : options.regexp; + return regexp.test(value); + } + }; +}(window.jQuery)); +;(function ($) { + $.fn.bootstrapValidator.validators.remote = { + html5Attributes: { + message: 'message', + url: 'url', + name: 'name' + }, + + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - name [optional]: Override the field name for the request. + * - message: The invalid message + * @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; + if (data == null) { + data = {}; + } + // Support dynamic data + if ('function' == typeof data) { + data = data.call(this, validator); + } + data[options.name || name] = value; + + var dfd = new $.Deferred(); + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }); + xhr.then(function(response) { + dfd.resolve($field, 'remote', response.valid === true || response.valid === 'true'); + }); + + dfd.fail(function() { + xhr.abort(); + }); + + return dfd; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.siren = { + /** + * Check if a string is a siren number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^\d{9}$/.test(value)) { + return false; + } + return $.fn.bootstrapValidator.helpers.luhn(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.siret = { + /** + * Check if a string is a siret number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var sum = 0, + length = value.length, + tmp; + for (var i = 0; i < length; i++) { + tmp = parseInt(value.charAt(i), 10); + if ((i % 2) == 0) { + tmp = tmp * 2; + if (tmp > 9) { + tmp -= 9; + } + } + sum += tmp; + } + return (sum % 10 == 0); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.step = { + html5Attributes: { + message: 'message', + base: 'baseValue', + step: 'step' + }, + + /** + * Return true if the input value is valid step one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - baseValue: The base value + * - step: The step + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options = $.extend({}, { baseValue: 0, step: 1 }, options); + value = parseFloat(value); + if (isNaN(value) || !isFinite(value)) { + return false; + } + + var round = function(x, precision) { + var m = Math.pow(10, precision); + x = x * m; + var sign = (x > 0) | -(x < 0), + isHalf = (x % 1 === 0.5 * sign); + if (isHalf) { + return (Math.floor(x) + (sign > 0)) / m; + } else { + return Math.round(x) / m; + } + }, + floatMod = function(x, y) { + if (y == 0.0) { + return 1.0; + } + var dotX = (x + '').split('.'), + dotY = (y + '').split('.'), + precision = ((dotX.length == 1) ? 0 : dotX[1].length) + ((dotY.length == 1) ? 0 : dotY[1].length); + return round(x - y * Math.floor(x / y), precision); + }; + + var mod = floatMod(value - options.baseValue, options.step); + return (mod == 0.0 || mod == options.step); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringCase = { + html5Attributes: { + message: 'message', + 'case': 'case' + }, + + /** + * Check if a string is a lower or upper case one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - case: Can be 'lower' (default) or 'upper' + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var stringCase = (options['case'] || 'lower').toLowerCase(); + switch (stringCase) { + case 'upper': + return value === value.toUpperCase(); + case 'lower': + default: + return value === value.toLowerCase(); + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max' + }, + + enableByHtml5: function($field) { + var maxLength = $field.attr('maxlength'); + if (maxLength) { + return { + max: parseInt(maxLength, 10) + }; + } + + return false; + }, + + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var length = $.trim(value).length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + enableByHtml5: function($field) { + return ('url' == $field.attr('type')); + }, + + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uuid = { + html5Attributes: { + message: 'message', + version: 'version' + }, + + /** + * Return true if and only if the input value is a valid UUID string + * + * @see http://en.wikipedia.org/wiki/Universally_unique_identifier + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - version: Can be 3, 4, 5, null + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // See the format at http://en.wikipedia.org/wiki/Universally_unique_identifier#Variants_and_versions + var patterns = { + '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, + '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i + }, + version = options.version ? (options.version + '') : 'all'; + return (null == patterns[version]) ? true : patterns[version].test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.vat = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Validate an European VAT number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166-1 country code + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var country = options.country || value.substr(0, 2), + method = ['_', country.toLowerCase()].join(''); + if (this[method] && 'function' == typeof this[method]) { + return this[method](value); + } + + return true; + }, + + // VAT validators + + /** + * Validate Austrian VAT number + * Example: + * - Valid: ATU13585627 + * - Invalid: ATU13585626 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _at: function(value) { + if (!/^ATU[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(3); + var sum = 0, + weight = [1, 2, 1, 2, 1, 2, 1], + temp = 0; + + for (var i = 0; i < 7; i++) { + temp = parseInt(value.charAt(i)) * weight[i]; + if (temp > 9) { + temp = Math.floor(temp / 10) + temp % 10; + } + sum += temp; + } + + sum = 10 - (sum + 4) % 10; + if (sum == 10) { + sum = 0; + } + + return (sum == value.substr(7, 1)); + }, + + /** + * Validate Belgian VAT number + * Example: + * - Valid: BE0428759497 + * - Invalid: BE431150351 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _be: function(value) { + if (!/^BE[0]{0,1}[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + if (value.length == 9) { + value = '0' + value; + } + + if (value.substr(1, 1) == 0) { + return false; + } + + var sum = parseInt(value.substr(0, 8), 10) + parseInt(value.substr(8, 2), 10); + return (sum % 97 == 0); + }, + + /** + * Validate Bulgarian VAT number + * Example: + * - Valid: BG175074752, + * BG7523169263, BG8032056031, + * BG7542011030, + * BG7111042925 + * - Invalid: BG175074753, BG7552A10004, BG7111042922 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _bg: function(value) { + if (!/^BG[0-9]{9,10}$/.test(value)) { + return false; + } + + value = value.substr(2); + + var total = 0, sum = 0, weight = [], i = 0; + + // Legal entities + if (value.length == 9) { + for (i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * (i + 1); + } + sum = sum % 11; + if (sum == 10) { + sum = 0; + for (i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * (i + 3); + } + } + sum = sum % 10; + return (sum == value.substr(8)); + } + // Physical persons, foreigners and others + else if (value.length == 10) { + // Validate Bulgarian national identification numbers + var egn = function(value) { + // Check the birth date + var year = parseInt(value.substr(0, 2), 10) + 1900, + month = parseInt(value.substr(2, 2), 10), + day = parseInt(value.substr(4, 2), 10); + if (month > 40) { + year += 100; + month -= 40; + } else if (month > 20) { + year -= 100; + month -= 20; + } + + try { + var d = new Date(year, month, day); + } catch (ex) { + return false; + } + + var sum = 0, + weight = [2, 4, 8, 5, 10, 9, 7, 3, 6]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = (sum % 11) % 10; + return (sum == value.substr(9, 1)); + }, + // Validate Bulgarian personal number of a foreigner + pnf = function(value) { + var sum = 0, + weight = [21, 19, 17, 13, 11, 9, 7, 3, 1]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 10; + return (sum == value.substr(9, 1)); + }, + // Finally, consider it as a VAT number + vat = function(value) { + var sum = 0, + weight = [4, 3, 2, 7, 6, 5, 4, 3, 2]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = 11 - sum % 11; + if (sum == 10) { + return false; + } + if (sum == 11) { + sum = 0; + } + return (sum == value.substr(9, 1)); + }; + return (egn(value) || pnf(value) || vat(value)); + } + + return false; + }, + + /** + * Validate Swiss VAT number + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ch: function(value) { + if (!/^CHE[0-9]{9}(MWST)?$/.test(value)) { + return false; + } + + value = value.substr(3); + var sum = 0, + weight = [5, 4, 3, 2, 7, 6, 5, 4]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i), 10) * weight[i]; + } + + sum = 11 - sum % 11; + if (sum == 10) { + return false; + } + if (sum == 11) { + sum = 0; + } + + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Cypriot VAT number + * Examples: + * - Valid: CY10259033P + * - Invalid: CY10259033Z + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _cy: function(value) { + if (!/^CY[0-5|9]{1}[0-9]{7}[A-Z]{1}$/.test(value)) { + return false; + } + + value = value.substr(2); + + // Do not allow to start with "12" + if (value.substr(0, 2) == '12') { + return false; + } + + // Extract the next digit and multiply by the counter. + var sum = 0, + translation = { + '0': 1, '1': 0, '2': 5, '3': 7, '4': 9, + '5': 13, '6': 15, '7': 17, '8': 19, '9': 21 + }; + for (var i = 0; i < 8; i++) { + var temp = parseInt(value.charAt(i), 10); + if (i % 2 == 0) { + temp = translation[temp + '']; + } + sum += temp; + } + + sum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[sum % 26]; + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Czech Republic VAT number + * Can be: + * i) Legal entities (8 digit numbers) + * ii) Individuals with a RC (the 9 or 10 digit Czech birth number) + * iii) Individuals without a RC (9 digit numbers beginning with 6) + * + * Examples: + * - Valid: i) CZ25123891; ii) CZ7103192745, CZ991231123; iii) CZ640903926 + * - Invalid: i) CZ25123890; ii) CZ1103492745, CZ590312123 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _cz: function(value) { + if (!/^CZ[0-9]{8,10}$/.test(value)) { + return false; + } + + value = value.substr(2); + + var sum = 0, + i = 0; + if (value.length == 8) { + // Do not allow to start with '9' + if (value.charAt(0) + '' == '9') { + return false; + } + + sum = 0; + for (i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i), 10) * (8 - i); + } + sum = 11 - sum % 11; + if (sum == 10) { + sum = 0; + } + if (sum == 11) { + sum = 1; + } + + return (sum == value.substr(7, 1)); + } else if (value.length == 9 && (value.charAt(0) + '' == '6')) { + sum = 0; + // Skip the first (which is 6) + for (i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i + 1), 10) * (8 - i); + } + sum = 11 - sum % 11; + if (sum == 10) { + sum = 0; + } + if (sum == 11) { + sum = 1; + } + sum = [8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 10][sum - 1]; + return (sum == value.substr(8, 1)); + } else if (value.length == 9 || value.length == 10) { + // Validate Czech birth number (Rodné číslo), which is also national identifier + var year = 1900 + parseInt(value.substr(0, 2)), + month = parseInt(value.substr(2, 2)) % 50 % 20, + day = parseInt(value.substr(4, 2)); + if (value.length == 9) { + if (year >= 1980) { + year -= 100; + } + if (year > 1953) { + return false; + } + } else if (year < 1954) { + year += 100; + } + + try { + var d = new Date(year, month, day); + } catch (ex) { + return false; + } + + // Check that the birth date is not in the future + if (value.length == 10) { + var check = parseInt(value.substr(0, 9), 10) % 11; + if (year < 1985) { + check = check % 10; + } + return (check == value.substr(9, 1)); + } + + return true; + } + + return false; + }, + + /** + * Validate German VAT number + * Examples: + * - Valid: DE136695976 + * - Invalid: DE136695978 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _de: function(value) { + if (!/^DE[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + return $.fn.bootstrapValidator.helpers.mod_11_10(value); + }, + + /** + * Validate Danish VAT number + * Example: + * - Valid: DK13585628 + * - Invalid: DK13585627 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _dk: function(value) { + if (!/^DK[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [2, 7, 6, 5, 4, 3, 2, 1]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i), 10) * weight[i]; + } + + return (sum % 11 == 0); + }, + + /** + * Validate Estonian VAT number + * Examples: + * - Valid: EE100931558, EE100594102 + * - Invalid: EE100594103 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ee: function(value) { + if (!/^EE[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [3, 7, 1, 3, 7, 1, 3, 7, 1]; + + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 10 == 0); + }, + + /** + * Validate Spanish VAT number (NIF - Número de Identificación Fiscal) + * Can be: + * i) DNI (Documento nacional de identidad), for Spaniards + * ii) NIE (Número de Identificación de Extranjeros), for foreigners + * iii) CIF (Certificado de Identificación Fiscal), for legal entities and others + * + * Examples: + * - Valid: i) ES54362315K; ii) ESX2482300W, ESX5253868R; iii) ESM1234567L, ESJ99216582, ESB58378431, ESB64717838 + * - Invalid: i) ES54362315Z; ii) ESX2482300A; iii) ESJ99216583 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _es: function(value) { + if (!/^ES[0-9A-Z][0-9]{7}[0-9A-Z]$/.test(value)) { + return false; + } + + value = value.substr(2); + var dni = function(value) { + var check = parseInt(value.substr(0, 8), 10); + check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; + return (check == value.substr(8, 1)); + }, + nie = function(value) { + var check = ['XYZ'.indexOf(value.charAt(0)), value.substr(1)].join(''); + check = parseInt(check, 10); + check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; + return (check == value.substr(8, 1)); + }, + cif = function(value) { + var first = value.charAt(0), check; + if ('KLM'.indexOf(first) != -1) { + // K: Spanish younger than 14 year old + // L: Spanish living outside Spain without DNI + // M: Granted the tax to foreigners who have no NIE + check = parseInt(value.substr(1, 8), 10); + check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; + return (check == value.substr(8, 1)); + } else if ('ABCDEFGHJNPQRSUVW'.indexOf(first) != -1) { + var sum = 0, + weight = [2, 1, 2, 1, 2, 1, 2], + temp = 0; + + for (var i = 0; i < 7; i++) { + temp = parseInt(value.charAt(i + 1)) * weight[i]; + if (temp > 9) { + temp = Math.floor(temp / 10) + temp % 10; + } + sum += temp; + } + sum = 10 - sum % 10; + return (sum == value.substr(8, 1) || 'JABCDEFGHI'[sum] == value.substr(8, 1)); + } + + return false; + }; + + var first = value.charAt(0); + if (/^[0-9]$/.test(first)) { + return dni(value); + } else if (/^[XYZ]$/.test(first)) { + return nie(value); + } else { + return cif(value); + } + }, + + /** + * Validate Finnish VAT number + * Examples: + * - Valid: FI20774740 + * - Invalid: FI20774741 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _fi: function(value) { + if (!/^FI[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [7, 9, 10, 5, 8, 4, 2, 1]; + + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 11 == 0); + }, + + /** + * Validate French VAT number (TVA - taxe sur la valeur ajoutée) + * It's constructed by a SIREN number, prefixed by two characters. + * + * Examples: + * - Valid: FR40303265045, FR23334175221, FRK7399859412, FR4Z123456782 + * - Invalid: FR84323140391 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _fr: function(value) { + if (!/^FR[0-9A-Z]{2}[0-9]{9}$/.test(value)) { + return false; + } + + value = 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 + return value.substr(0, 2) == (parseInt(value.substr(2) + '12', 10) % 97); + } else { + // The first characters cann't be O and I + var alphabet = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ', + check; + // First one is digit + if (/^[0-9]{1}$/.test(value.charAt(0))) { + check = alphabet.indexOf(value.charAt(0)) * 24 + alphabet.indexOf(value.charAt(1)) - 10; + } else { + check = alphabet.indexOf(value.charAt(0)) * 34 + alphabet.indexOf(value.charAt(1)) - 100; + } + return ((parseInt(value.substr(2), 10) + 1 + Math.floor(check / 11)) % 11) == (check % 11); + } + }, + + /** + * Validate United Kingdom VAT number + * Example: + * - Valid: GB980780684 + * - Invalid: GB802311781 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _gb: function(value) { + if (!/^GB[0-9]{9}$/.test(value) // Standard + && !/^GB[0-9]{12}$/.test(value) // Branches + && !/^GBGD[0-9]{3}$/.test(value) // Government department + && !/^GBHA[0-9]{3}$/.test(value) // Health authority + && !/^GB(GD|HA)8888[0-9]{5}$/.test(value)) + { + return false; + } + + value = value.substr(2); + var length = value.length; + if (length == 5) { + var firstTwo = value.substr(0, 2), + lastThree = parseInt(value.substr(2)); + return ('GD' == firstTwo && lastThree < 500) || ('HA' == firstTwo && lastThree >= 500); + } else if (length == 11 && ('GD8888' == value.substr(0, 6) || 'HA8888' == value.substr(0, 6))) { + if (('GD' == value.substr(0, 2) && parseInt(value.substr(6, 3)) >= 500) + || ('HA' == value.substr(0, 2) && parseInt(value.substr(6, 3)) < 500)) + { + return false; + } + return (parseInt(value.substr(6, 3)) % 97 == parseInt(value.substr(9, 2))); + } else if (length == 9 || length == 12) { + var sum = 0, + weight = [8, 7, 6, 5, 4, 3, 2, 10, 1]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 97; + + if (parseInt(value.substr(0, 3)) >= 100) { + return (sum == 0 || sum == 42 || sum == 55); + } else { + return (sum == 0); + } + } + + return true; + }, + + /** + * Validate Greek VAT number + * Examples: + * - Valid: GR023456780, EL094259216 + * - Invalid: EL123456781 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _gr: function(value) { + if (!/^GR[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + if (value.length == 8) { + value = '0' + value; + } + + var sum = 0, + weight = [256, 128, 64, 32, 16, 8, 4, 2]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = (sum % 11) % 10; + + return (sum == value.substr(8, 1)); + }, + + // EL is traditionally prefix of Greek VAT numbers + _el: function(value) { + if (!/^EL[0-9]{9}$/.test(value)) { + return false; + } + + value = 'GR' + value.substr(2); + return this._gr(value); + }, + + /** + * Validate Hungarian VAT number + * Examples: + * - Valid: HU12892312 + * - Invalid: HU12892313 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _hu: function(value) { + if (!/^HU[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [9, 7, 3, 1, 9, 7, 3, 1]; + + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 10 == 0); + }, + + /** + * Validate Croatian VAT number + * Examples: + * - Valid: HR33392005961 + * - Invalid: HR33392005962 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _hr: function(value) { + if (!/^HR[0-9]{11}$/.test(value)) { + return false; + } + + value = value.substr(2); + return $.fn.bootstrapValidator.helpers.mod_11_10(value); + }, + + /** + * Validate Irish VAT number + * Examples: + * - Valid: IE6433435F, IE6433435OA, IE8D79739I + * - Invalid: IE8D79738J + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ie: function(value) { + if (!/^IE[0-9]{1}[0-9A-Z\*\+]{1}[0-9]{5}[A-Z]{1,2}$/.test(value)) { + return false; + } + + value = value.substr(2); + var getCheckDigit = function(value) { + while (value.length < 7) { + value = '0' + value; + } + var alphabet = 'WABCDEFGHIJKLMNOPQRSTUV', + sum = 0; + for (var i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i)) * (8 - i); + } + sum += 9 * alphabet.indexOf(value.substr(7)); + return alphabet[sum % 23]; + }; + + // The first 7 characters are digits + if (/^[0-9]+$/.test(value.substr(0, 7))) { + // New system + return value.charAt(7) == getCheckDigit(value.substr(0, 7) + value.substr(8) + ''); + } else if ('ABCDEFGHIJKLMNOPQRSTUVWXYZ+*'.indexOf(value.charAt(1)) != -1) { + // Old system + return value.charAt(7) == getCheckDigit(value.substr(2, 5) + value.substr(0, 1) + ''); + } + + return true; + }, + + /** + * 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 + * + * Examples: + * - Valid: IT00743110157 + * - Invalid: IT00743110158 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _it: function(value) { + if (!/^IT[0-9]{11}$/.test(value)) { + return false; + } + + value = value.substr(2); + if (parseInt(value.substr(0, 7)) == 0) { + return false; + } + + var lastThree = parseInt(value.substr(7, 3)); + if ((lastThree < 1) || (lastThree > 201) && lastThree != 999 && lastThree != 888) { + return false; + } + + return $.fn.bootstrapValidator.helpers.luhn(value); + }, + + /** + * Validate Lithuanian VAT number + * It can be: + * - 9 digits, for legal entities + * - 12 digits, for temporarily registered taxpayers + * + * Examples: + * - Valid: LT119511515, LT100001919017, LT100004801610 + * - Invalid: LT100001919018 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _lt: function(value) { + if (!/^LT([0-9]{7}1[0-9]{1}|[0-9]{10}1[0-9]{1})$/.test(value)) { + return false; + } + + value = value.substr(2); + var length = value.length, + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * (1 + i % 9); + } + var check = sum % 11; + if (check == 10) { + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * (1 + (i + 2) % 9); + } + } + check = check % 11 % 10; + return (check == value.charAt(length - 1)); + }, + + /** + * Validate Luxembourg VAT number + * Examples: + * - Valid: LU15027442 + * - Invalid: LU15027443 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _lu: function(value) { + if (!/^LU[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + return (value.substr(0, 6) % 89 == value.substr(6, 2)); + }, + + /** + * Validate Latvian VAT number + * Examples: + * - Valid: LV40003521600, LV16117519997 + * - Invalid: LV40003521601, LV16137519997 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _lv: function(value) { + if (!/^LV[0-9]{11}$/.test(value)) { + return false; + } + + value = value.substr(2); + var first = parseInt(value.charAt(0)), + sum = 0, + weight = [], + i = 0, + length = value.length; + if (first > 3) { + // Legal entity + sum = 0; + weight = [9, 1, 4, 8, 3, 10, 2, 5, 7, 6, 1]; + for (i = 0; i < length; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 11; + return (sum == 3); + } else { + // Check birth date + var day = parseInt(value.substr(0, 2)), + month = parseInt(value.substr(2, 2)), + year = parseInt(value.substr(4, 2)); + year = year + 1800 + parseInt(value.charAt(6)) * 100; + + try { + var d = new Date(year, month, day); + } catch (ex) { + return false; + } + + // Check personal code + sum = 0; + weight = [10, 5, 8, 4, 2, 1, 6, 3, 7, 9]; + for (i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = (sum + 1) % 11 % 10; + return (sum == value.charAt(length - 1)); + } + + return true; + }, + + /** + * Validate Maltese VAT number + * Examples: + * - Valid: MT11679112 + * - Invalid: MT11679113 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _mt: function(value) { + if (!/^MT[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [3, 4, 6, 7, 8, 9, 10, 1]; + + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 37 == 0); + }, + + /** + * Validate Dutch VAT number + * Examples: + * - Valid: NL004495445B01 + * - Invalid: NL123456789B90 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _nl: function(value) { + if (!/^NL[0-9]{9}B[0-9]{2}$/.test(value)) { + return false; + } + value = value.substr(2); + var sum = 0, + weight = [9, 8, 7, 6, 5, 4, 3, 2]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + sum = sum % 11; + if (sum > 9) { + sum = 0; + } + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Norwegian VAT number + * + * @see http://www.brreg.no/english/coordination/number.html + * @param {String} value VAT number + * @returns {Boolean} + */ + _no: function(value) { + if (!/^NO[0-9]{9}$/.test(value)) { + return false; + } + value = value.substr(2); + var sum = 0, + weight = [3, 2, 7, 6, 5, 4, 3, 2]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + sum = 11 - sum % 11; + if (sum == 11) { + sum = 0; + } + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Polish VAT number + * Examples: + * - Valid: PL8567346215 + * - Invalid: PL8567346216 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _pl: function(value) { + if (!/^PL[0-9]{10}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [6, 5, 7, 2, 3, 4, 5, 6, 7, -1]; + + for (var i = 0; i < 10; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 11 == 0); + }, + + /** + * Validate Portuguese VAT number + * Examples: + * - Valid: PT501964843 + * - Invalid: PT501964842 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _pt: function(value) { + if (!/^PT[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [9, 8, 7, 6, 5, 4, 3, 2]; + + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = 11 - sum % 11; + if (sum > 9) { + sum = 0; + } + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Romanian VAT number + * Examples: + * - Valid: RO18547290 + * - Invalid: RO18547291 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ro: function(value) { + if (!/^RO[1-9][0-9]{1,9}$/.test(value)) { + return false; + } + value = value.substr(2); + + var length = value.length, + weight = [7, 5, 3, 2, 1, 7, 5, 3, 2].slice(10 - length), + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + sum = (10 * sum) % 11 % 10; + return (sum == value.substr(length - 1, 1)); + }, + + /** + * Validate Russian VAT number (Taxpayer Identification Number - INN) + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ru: function(value) { + if (!/^RU([0-9]{9}|[0-9]{12})$/.test(value)) { + return false; + } + + value = value.substr(2); + if (value.length == 10) { + var sum = 0, + weight = [2, 4, 10, 3, 5, 9, 4, 6, 8, 0]; + for (var i = 0; i < 10; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 11; + if (sum > 9) { + sum = sum % 10; + } + + return (sum == value.substr(9, 1)); + } else if (value.length == 12) { + var sum1 = 0, + weight1 = [7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0], + sum2 = 0, + weight2 = [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0]; + + for (var i = 0; i < 11; i++) { + sum1 += parseInt(value.charAt(i)) * weight1[i]; + sum2 += parseInt(value.charAt(i)) * weight2[i]; + } + sum1 = sum1 % 11; + if (sum1 > 9) { + sum1 = sum1 % 10; + } + sum2 = sum2 % 11; + if (sum2 > 9) { + sum2 = sum2 % 10; + } + + return (sum1 == value.substr(10, 1) && sum2 == value.substr(11, 1)); + } + + return false; + }, + + /** + * Validate Serbian VAT number + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _rs: function(value) { + if (!/^RS[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 10, + temp = 0; + for (var i = 0; i < 8; i++) { + temp = (parseInt(value.charAt(i)) + sum) % 10; + if (temp == 0) { + temp = 10; + } + sum = (2 * temp) % 11; + } + + return ((sum + parseInt(value.substr(8, 1))) % 10 == 1); + }, + + /** + * Validate Swedish VAT number + * Examples: + * - Valid: SE123456789701 + * - Invalid: SE123456789101 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _se: function(value) { + if (!/^SE[0-9]{10}01$/.test(value)) { + return false; + } + + value = value.substr(2, 10); + return $.fn.bootstrapValidator.helpers.luhn(value); + }, + + /** + * Validate Slovenian VAT number + * Examples: + * - Valid: SI50223054 + * - Invalid: SI50223055 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _si: function(value) { + if (!/^SI[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [8, 7, 6, 5, 4, 3, 2]; + + for (var i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = 11 - sum % 11; + if (sum == 10) { + sum = 0; + } + return (sum == value.substr(7, 1)); + }, + + /** + * Validate Slovak VAT number + * Examples: + * - Valid: SK2022749619 + * - Invalid: SK2022749618 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _sk: function(value) { + if (!/^SK[1-9][0-9][(2-4)|(6-9)][0-9]{7}$/.test(value)) { + return false; + } + + value = value.substr(2); + return (value % 11 == 0); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.vin = { + /** + * Validate an US VIN (Vehicle Identification Number) + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Don't accept I, O, Q characters + if (!/^[a-hj-npr-z0-9]{8}[0-9xX][a-hj-npr-z0-9]{8}$/i.test(value)) { + return false; + } + + value = value.toUpperCase(); + var chars = { + A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8, + J: 1, K: 2, L: 3, M: 4, N: 5, P: 7, R: 9, + S: 2, T: 3, U: 4, V: 5, W: 6, X: 7, Y: 8, Z: 9, + '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '0': 0 + }, + weights = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2], + sum = 0, + length = value.length; + for (var i = 0; i < length; i++) { + sum += chars[value.charAt(i) + ''] * weights[i]; + } + + var reminder = sum % 11; + if (reminder == 10) { + reminder = 'X'; + } + + return reminder == value.charAt(8); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.zipCode = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Return true if and only if the input value is a valid country zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166 country code + * + * Currently it supports the following countries: + * - US (United State) + * - CA (Canada) + * - DK (Denmark) + * - GB (United Kingdom) + * - SE (Sweden) + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '' || !options.country) { + return true; + } + + var country = (options.country || 'US').toUpperCase(); + switch (country) { + case 'CA': + return /(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}\s?[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}/i.test(value); + case 'DK': + return /^(DK(-|\s)?)?\d{4}$/i.test(value); + case 'GB': + return this._gb(value); + case 'SE': + return /^(S-)?\d{3}\s?\d{2}$/i.test(value); + case 'US': + default: + return /^\d{4,5}([\-]\d{4})?$/.test(value); + } + }, + + /** + * Validate United Kingdom postcode + * Examples: + * - Standard: EC1A 1BB, W1A 1HQ, M1 1AA, B33 8TH, CR2 6XH, DN55 1PT + * - Special cases: + * AI-2640, ASCN 1ZZ, GIR 0AA + * + * @see http://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom + * @param {String} value The postcode + * @returns {Boolean} + */ + _gb: function(value) { + var firstChar = '[ABCDEFGHIJKLMNOPRSTUWYZ]', // Does not accept QVX + secondChar = '[ABCDEFGHKLMNOPQRSTUVWXY]', // Does not accept IJZ + thirdChar = '[ABCDEFGHJKPMNRSTUVWXY]', + fouthChar = '[ABEHMNPRVWXY]', + fifthChar = '[ABDEFGHJLNPQRSTUWXYZ]', + regexps = [ + // AN NAA, ANN NAA, AAN NAA, AANN NAA format + new RegExp('^(' + firstChar + '{1}' + secondChar + '?[0-9]{1,2})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'), + // ANA NAA + new RegExp('^(' + firstChar + '{1}[0-9]{1}' + thirdChar + '{1})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'), + // AANA NAA + new RegExp('^(' + firstChar + '{1}' + secondChar + '{1}?[0-9]{1}' + fouthChar + '{1})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'), + + new RegExp('^(BF1)(\\s*)([0-6]{1}[ABDEFGHJLNPQRST]{1}[ABDEFGHJLNPQRSTUWZYZ]{1})$', 'i'), // BFPO postcodes + /^(GIR)(\s*)(0AA)$/i, // Special postcode GIR 0AA + /^(BFPO)(\s*)([0-9]{1,4})$/i, // Standard BFPO numbers + /^(BFPO)(\s*)(c\/o\s*[0-9]{1,3})$/i, // c/o BFPO numbers + /^([A-Z]{4})(\s*)(1ZZ)$/i, // Overseas Territories + /^(AI-2640)$/i // Anguilla + ]; + for (var i = 0; i < regexps.length; i++) { + if (regexps[i].test(value)) { + return true; + } + } + + return false; + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.4/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.4.4/js/bootstrapValidator.min.js new file mode 100644 index 000000000..08e290644 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.4/js/bootstrapValidator.min.js @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * A jQuery plugin to validate form fields. Use with Bootstrap 3 + * + * @version v0.4.4 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),this.$invalidField=null,this.$submitButton=null,this.STATUS_NOT_VALIDATED="NOT_VALIDATED",this.STATUS_VALIDATING="VALIDATING",this.STATUS_INVALID="INVALID",this.STATUS_VALID="VALID";var e=function(){for(var a=3,b=document.createElement("div"),c=b.all||[];b.innerHTML="",c[0];);return a>4?a:!a}(),f=document.createElement("div");this._changeEvent=9!==e&&"oninput"in f?"input":"keyup",this._submitIfValid=null,this._init()};b.DEFAULT_OPTIONS={elementClass:"bv-form",message:"This value is not valid",excluded:[":disabled",":hidden",":not(:visible)"],feedbackIcons:{valid:null,invalid:null,validating:null},submitButtons:'button[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){var b,c,d,e,f,g,h,i=this,j={excluded:this.$form.attr("data-bv-excluded"),trigger:this.$form.attr("data-bv-trigger"),message:this.$form.attr("data-bv-message"),submitButtons:this.$form.attr("data-bv-submitbuttons"),live:this.$form.attr("data-bv-live"),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")}};this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit.bv",function(a){a.preventDefault(),i.validate()}).on("click",this.options.submitButtons,function(){i.$submitButton=a(this),i._submitIfValid=!0}).find("[name], [data-bv-field]").each(function(){var i=a(this);if("hidden"!=i.attr("type")){var k=i.attr("name")||i.attr("data-bv-field");i.attr("data-bv-field",k),j.fields[k]=a.extend({},{trigger:i.attr("data-bv-trigger"),message:i.attr("data-bv-message"),container:i.attr("data-bv-container"),selector:i.attr("data-bv-selector"),validators:{}},j.fields[k]);for(c in a.fn.bootstrapValidator.validators)if(b=a.fn.bootstrapValidator.validators[c],d=i.attr("data-bv-"+c.toLowerCase())+"",h="function"==typeof b.enableByHtml5?b.enableByHtml5(a(this)):null,h&&"false"!=d||h!==!0&&(""==d||"true"==d)){b.html5Attributes=b.html5Attributes||{message:"message"},j.fields[k].validators[c]=a.extend({},1==h?{}:h,j.fields[k].validators[c]);for(g in b.html5Attributes)e=b.html5Attributes[g],f=i.attr("data-bv-"+c.toLowerCase()+"-"+g),f&&("true"==f?f=!0:"false"==f&&(f=!1),j.fields[k].validators[c][e]=f)}}}),this.options=a.extend(!0,this.options,j),"string"==typeof this.options.excluded&&(this.options.excluded=a.map(this.options.excluded.split(","),function(b){return a.trim(b)}));for(var k in this.options.fields)this._initField(k);this.setLiveMode(this.options.live)},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){var c=this.getFieldElements(b);if(null==c)return void delete this.options.fields[b];for(var d in this.options.fields[b].validators)a.fn.bootstrapValidator.validators[d]||delete this.options.fields[b].validators[d];for(var e=this,f=c.attr("type"),g="radio"==f||"checkbox"==f||"file"==f||"SELECT"==c[0].tagName?"change":e._changeEvent,h=c.length,i=1==h||"radio"==f||"checkbox"==f,j=0;h>j;j++){var k=a(c[j]),l=k.parents(".form-group"),m=this.options.fields[b].container?l.find(this.options.fields[b].container):this._getMessageContainer(k);this.options.fields[b].selector&&k.attr("data-bv-field",b),k.on(g+".update.bv",function(){e._submitIfValid=!1,i?e.updateStatus(b,e.STATUS_NOT_VALIDATED,null):e.updateElementStatus(a(this),e.STATUS_NOT_VALIDATED,null)}),k.data("bv.messages",m);for(d in this.options.fields[b].validators)k.data("bv.result."+d,this.STATUS_NOT_VALIDATED),i&&j!=h-1||a("").css("display","none").attr("data-bv-validator",d).attr("data-bv-validator-for",b).html(this.options.fields[b].validators[d].message||this.options.fields[b].message||this.options.message).addClass("help-block").appendTo(m);if(this.options.feedbackIcons&&this.options.feedbackIcons.validating&&this.options.feedbackIcons.invalid&&this.options.feedbackIcons.valid&&(!i||j==h-1)){l.addClass("has-feedback");var n=a("").css("display","none").addClass("form-control-feedback").attr("data-bv-field",b).insertAfter(k);0==l.find("label").length&&n.css("top",0)}}null==this.options.fields[b].enabled&&(this.options.fields[b].enabled=!0)}},_getMessageContainer:function(a){var b=a.parent();if(b.hasClass("form-group"))return b;var c=b.attr("class");if(!c)return this._getMessageContainer(b);c=c.split(" ");for(var d=c.length,e=0;d>e;e++)if(/^col-(xs|sm|md|lg)-\d+$/.test(c[e])||/^col-(xs|sm|md|lg)-offset-\d+$/.test(c[e]))return b;return this._getMessageContainer(b)},_submit:function(){if(this.isValid())this.options.submitHandler&&"function"==typeof this.options.submitHandler?this.options.submitHandler.call(this,this,this.$form,this.$submitButton):this.disableSubmitButtons(!0).defaultSubmit();else if("submitted"==this.options.live&&this.setLiveMode("enabled"),this.$invalidField){var b,c=this.$invalidField.parents(".tab-pane");c&&(b=c.attr("id"))&&a('a[href="#'+b+'"][data-toggle="tab"]').trigger("click.bs.tab.data-api"),this.$invalidField.focus()}},_isExcluded:function(a){if(this.options.excluded)for(var b in this.options.excluded)if("string"==typeof this.options.excluded[b]&&a.is(this.options.excluded[b])||"function"==typeof this.options.excluded[b]&&1==this.options.excluded[b].call(this,a,this))return!0;return!1},getFieldElements:function(b){var c=this.options.fields[b].selector?a(this.options.fields[b].selector):this.$form.find('[name="'+b+'"]');return 0==c.length?null:c},setLiveMode:function(b){if(this.options.live=b,"submitted"==b)return this;var c=this;for(var d in this.options.fields)!function(e){var f=c.getFieldElements(e);if(f)for(var g=f.attr("type"),h=f.length,i=1==h||"radio"==g||"checkbox"==g,j=c.options.fields[d].trigger||c.options.trigger||("radio"==g||"checkbox"==g||"file"==g||"SELECT"==f[0].tagName?"change":c._changeEvent),k=a.map(j.split(" "),function(a){return a+".live.bv"}).join(" "),l=0;h>l;l++)"enabled"==b?a(f[l]).on(k,function(){i?c.validateField(e):c.validateFieldElement(a(this),!1)}):a(f[l]).off(k)}(d);return this},disableSubmitButtons:function(a){return a?"disabled"!=this.options.live&&this.$form.find(this.options.submitButtons).attr("disabled","disabled"):this.$form.find(this.options.submitButtons).removeAttr("disabled"),this},validate:function(){if(!this.options.fields)return this;this.disableSubmitButtons(!0);for(var a in this.options.fields)this.validateField(a);return this.$submitButton&&this._submit(),this},validateField:function(b){for(var c=this.getFieldElements(b),d=c.attr("type"),e="radio"==d||"checkbox"==d?1:c.length,f=0;e>f;f++)this.validateFieldElement(a(c[f]),1==e);return this},validateFieldElement:function(b,c){var d,e,f=this,g=b.attr("data-bv-field"),h=this.options.fields[g].validators;if(!this.options.fields[g].enabled||this._isExcluded(b))return this;for(d in h){b.data("bv.dfs."+d)&&b.data("bv.dfs."+d).reject();var i=b.data("bv.result."+d);i!=this.STATUS_VALID&&i!=this.STATUS_INVALID&&(b.data("bv.result."+d,this.STATUS_VALIDATING),e=a.fn.bootstrapValidator.validators[d].validate(this,b,h[d]),"object"==typeof e?(c?this.updateStatus(g,this.STATUS_VALIDATING,d):this.updateElementStatus(b,this.STATUS_VALIDATING,d),b.data("bv.dfs."+d,e),e.done(function(a,b,d){a.removeData("bv.dfs."+b),c?f.updateStatus(a.attr("data-bv-field"),d?f.STATUS_VALID:f.STATUS_INVALID,b):f.updateElementStatus(a,d?f.STATUS_VALID:f.STATUS_INVALID,b),d&&1==f._submitIfValid&&f._submit()})):"boolean"==typeof e&&(c?this.updateStatus(g,e?this.STATUS_VALID:this.STATUS_INVALID,d):this.updateElementStatus(b,e?this.STATUS_VALID:this.STATUS_INVALID,d)))}return this},updateStatus:function(b,c,d){for(var e=this.getFieldElements(b),f=e.attr("type"),g="radio"==f||"checkbox"==f?1:e.length,h=0;g>h;h++)this.updateElementStatus(a(e[h]),c,d);return this},updateElementStatus:function(b,c,d){var e=this,f=b.attr("data-bv-field"),g=b.parents(".form-group"),h=b.data("bv.messages"),i=h.find(".help-block[data-bv-validator]"),j=g.find('.form-control-feedback[data-bv-field="'+f+'"]');if(d)b.data("bv.result."+d,c);else for(var k in this.options.fields[f].validators)b.data("bv.result."+k,c);var l,m,n=b.parents(".tab-pane");switch(n&&(l=n.attr("id"))&&(m=a('a[href="#'+l+'"][data-toggle="tab"]').parent()),c){case this.STATUS_VALIDATING:this.disableSubmitButtons(!0),g.removeClass("has-success").removeClass("has-error"),d?i.filter('.help-block[data-bv-validator="'+d+'"]').hide():i.hide(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(),m&&m.removeClass("bv-tab-success").removeClass("bv-tab-error");break;case this.STATUS_INVALID:this.disableSubmitButtons(!0),g.removeClass("has-success").addClass("has-error"),d?i.filter('[data-bv-validator="'+d+'"]').show():i.show(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(),m&&m.removeClass("bv-tab-success").addClass("bv-tab-error");break;case this.STATUS_VALID:d?i.filter('[data-bv-validator="'+d+'"]').hide():i.hide();var o=0==i.filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||b.data("bv.result."+d)!=e.STATUS_VALID}).length;this.disableSubmitButtons(o?!1:!0),j&&j.removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid).addClass(o?this.options.feedbackIcons.valid:this.options.feedbackIcons.invalid).show();var p=function(c){return 0==c.find(".help-block[data-bv-validator]").filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||b.data("bv.result."+d)&&b.data("bv.result."+d)!=e.STATUS_VALID}).length};g.removeClass("has-error has-success").addClass(p(g)?"has-success":"has-error"),m&&m.removeClass("bv-tab-success").removeClass("bv-tab-error").addClass(p(n)?"bv-tab-success":"bv-tab-error");break;case this.STATUS_NOT_VALIDATED:default:this.disableSubmitButtons(!1),g.removeClass("has-success").removeClass("has-error"),d?i.filter('.help-block[data-bv-validator="'+d+'"]').hide():i.hide(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide(),m&&m.removeClass("bv-tab-success").removeClass("bv-tab-error")}return this},isValid:function(){var b,c,d,e,f,g,h,i;for(c in this.options.fields)if(null!=this.options.fields[c]&&this.options.fields[c].enabled)for(b=this.getFieldElements(c),e=b.attr("type"),h="radio"==e||"checkbox"==e?1:b.length,i=0;h>i;i++)if(d=a(b[i]),!this._isExcluded(d))for(g in this.options.fields[c].validators){if(f=d.data("bv.result."+g),f==this.STATUS_NOT_VALIDATED||f==this.STATUS_VALIDATING)return!1;if(f==this.STATUS_INVALID)return this.$invalidField=d,!1}return!0},defaultSubmit:function(){this.$form.off("submit.bv").submit()},resetForm:function(b){var c,d,e,f,g;for(c in this.options.fields){d=this.getFieldElements(c),e=d.length;for(var h=0;e>h;h++)for(g in this.options.fields[c].validators)a(d[h]).removeData("bv.dfs."+g);this.updateStatus(c,this.STATUS_NOT_VALIDATED,null),b&&(f=d.attr("type"),"radio"==f||"checkbox"==f?d.removeAttr("checked").removeAttr("selected"):d.val(""))}return this.$invalidField=null,this.$submitButton=null,this.disableSubmitButtons(!1),this},enableFieldValidators:function(a,b){return this.options.fields[a].enabled=b,this.updateStatus(a,this.STATUS_NOT_VALIDATED,null),this}},a.fn.bootstrapValidator=function(c,d){return this.each(function(){var e=a(this),f=e.data("bootstrapValidator"),g="object"==typeof c&&c;f||(f=new b(this,g),e.data("bootstrapValidator",f)),"string"==typeof c&&f[c](d)})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b,a.fn.bootstrapValidator.helpers={luhn:function(a){for(var b=a.length,c=0,d=[[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8,1,3,5,7,9]],e=0;b--;)e+=d[c][parseInt(a.charAt(b),10)],c^=1;return e%10===0&&e>0},mod_11_10:function(a){for(var b=5,c=a.length,d=0;c>d;d++)b=(2*(b||10)%11+parseInt(a.charAt(d),10))%10;return 1==b},mod_37_36:function(a,b){b=b||"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";for(var c=b.length,d=a.length,e=Math.floor(c/2),f=0;d>f;f++)e=(2*(e||c)%(c+1)+b.indexOf(a.charAt(f)))%c;return 1==e}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.base64={validate:function(a,b){var c=b.val();return""==c?!0:/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={html5Attributes:{message:"message",min:"min",max:"max",inclusive:"inclusive"},enableByHtml5:function(a){return"range"==a.attr("type")?{min:a.attr("min"),max:a.attr("max")}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(b,c,d){var e=c.val();if(d.callback&&"function"==typeof d.callback){var f=new a.Deferred;return f.resolve(c,"callback",d.callback.call(this,e,b)),f}return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.choice={html5Attributes:{message:"message",min:"min",max:"max"},validate:function(a,b,c){var d=b.is("select")?a.getFieldElements(b.attr("data-bv-field")).find("option").filter(":selected").length:a.getFieldElements(b.attr("data-bv-field")).filter(":checked").length;return c.min&&dc.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(b,c){var d=c.val();if(""==d)return!0;if(/[^0-9-\s]+/.test(d))return!1;if(d=d.replace(/\D/g,""),!a.fn.bootstrapValidator.helpers.luhn(d))return!1;var e,f,g={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["6304","6706","6771","6709"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}};for(e in g)for(f in g[e].prefix)if(d.substr(0,g[e].prefix[f].length)==g[e].prefix[f]&&-1!=g[e].length.indexOf(d.length))return!0;return!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.cvv={html5Attributes:{message:"message",ccfield:"creditCardField"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;if(!/^[0-9]{3,4}$/.test(d))return!1;if(!c.creditCardField)return!0;var e=a.getFieldElements(c.creditCardField).val();if(""==e)return!0;var f,g,h={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["6304","6706","6771","6709"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}},i=null;for(f in h)for(g in h[f].prefix)if(e.substr(0,h[f].prefix[g].length)==h[f].prefix[g]&&-1!=h[f].length.indexOf(e.length)){i=f;break}return null==i?!1:"AMERICAN_EXPRESS"==i?4==d.length:3==d.length}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.date={html5Attributes:{message:"message",format:"format"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;c.format=c.format||"MM/DD/YYYY";var e=c.format.split(" "),f=e[0],g=e.length>1?e[1]:null,h=e.length>2?e[2]:null,i=d.split(" "),j=i[0],k=i.length>1?i[1]:null;if(e.length!=i.length)return!1;var l=-1!=j.indexOf("/")?"/":-1!=j.indexOf("-")?"-":null;if(null==l)return!1;j=j.split(l),f=f.split(l);var m=j[f.indexOf("YYYY")],n=j[f.indexOf("MM")],o=j[f.indexOf("DD")],p=null,q=null,r=null;if(g){if(g=g.split(":"),k=k.split(":"),g.length!=k.length)return!1;if(q=k.length>0?k[0]:null,p=k.length>1?k[1]:null,r=k.length>2?k[2]:null,r&&(r=parseInt(r,10),0>r||r>60))return!1;if(q&&(q=parseInt(q,10),0>q||q>=24||h&&q>12))return!1;if(p&&(p=parseInt(p,10),0>p||p>59))return!1}if(o=parseInt(o,10),n=parseInt(n,10),m=parseInt(m,10),1e3>m||m>9999||0==n||n>12)return!1;var s=[31,28,31,30,31,30,31,31,30,31,30,31];return(m%400==0||m%100!=0&&m%4==0)&&(s[1]=29),o>0&&o<=s[n-1]}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={html5Attributes:{message:"message",field:"field"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d!=e.val()?(a.updateStatus(c.field,a.STATUS_VALID,"different"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){var c=b.val();return""==c?!0:/^\d+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.ean={validate:function(a,b){var c=b.val();if(""==c)return!0;if(!/^(\d{8}|\d{12}|\d{13})$/.test(c))return!1;for(var d=c.length,e=0,f=8==d?[3,1]:[1,3],g=0;d-1>g;g++)e+=parseInt(c.charAt(g))*f[g%2];return e=10-e%10,e==c.charAt(d-1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={enableByHtml5:function(a){return"email"==a.attr("type")},validate:function(a,b){var c=b.val();if(""==c)return!0;var d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.file={html5Attributes:{extension:"extension",maxsize:"maxSize",message:"message",type:"type"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e,f=c.extension?c.extension.split(","):null,g=c.type?c.type.split(","):null,h=window.File&&window.FileList&&window.FileReader;if(h)for(var i=b.get(0).files,j=i.length,k=0;j>k;k++){if(c.maxSize&&i[k].size>parseInt(c.maxSize))return!1;if(e=i[k].name.substr(i[k].name.lastIndexOf(".")+1),f&&-1==f.indexOf(e))return!1;if(g&&-1==g.indexOf(i[k].type))return!1}else if(e=d.substr(d.lastIndexOf(".")+1),f&&-1==f.indexOf(e))return!1;return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={html5Attributes:{message:"message",value:"value",inclusive:"inclusive"},enableByHtml5:function(a){var b=a.attr("min");return b?{value:b}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.value:d>=c.value)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.grid={validate:function(b,c){var d=c.val();return""==d?!0:(d=d.toUpperCase(),/^[GRID:]*([0-9A-Z]{2})[-\s]*([0-9A-Z]{5})[-\s]*([0-9A-Z]{10})[-\s]*([0-9A-Z]{1})$/g.test(d)?(d=d.replace(/\s/g,"").replace(/-/g,""),"GRID:"==d.substr(0,5)&&(d=d.substr(5)),a.fn.bootstrapValidator.helpers.mod_37_36(d)):!1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hex={validate:function(a,b){var c=b.val();return""==c?!0:/^[0-9a-fA-F]+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={enableByHtml5:function(a){return"color"==a.attr("type")},validate:function(a,b){var c=b.val();return""==c?!0:/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.iban={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e={AD:"AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}",AE:"AE[0-9]{2}[0-9]{3}[0-9]{16}",AL:"AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}",AO:"AO[0-9]{2}[0-9]{21}",AT:"AT[0-9]{2}[0-9]{5}[0-9]{11}",AZ:"AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}",BA:"BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}",BE:"BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}",BF:"BF[0-9]{2}[0-9]{23}",BG:"BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}",BH:"BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}",BI:"BI[0-9]{2}[0-9]{12}",BJ:"BJ[0-9]{2}[A-Z]{1}[0-9]{23}",BR:"BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]",CH:"CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}",CI:"CI[0-9]{2}[A-Z]{1}[0-9]{23}",CM:"CM[0-9]{2}[0-9]{23}",CR:"CR[0-9]{2}[0-9]{3}[0-9]{14}",CV:"CV[0-9]{2}[0-9]{21}",CY:"CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}",CZ:"CZ[0-9]{2}[0-9]{20}",DE:"DE[0-9]{2}[0-9]{8}[0-9]{10}",DK:"DK[0-9]{2}[0-9]{14}",DO:"DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}",DZ:"DZ[0-9]{2}[0-9]{20}",EE:"EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}",ES:"ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}",FI:"FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}",FO:"FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}",FR:"FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}",GB:"GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}",GE:"GE[0-9]{2}[A-Z]{2}[0-9]{16}",GI:"GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}",GL:"GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}",GR:"GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}",GT:"GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}",HR:"HR[0-9]{2}[0-9]{7}[0-9]{10}",HU:"HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}",IE:"IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}",IL:"IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}",IR:"IR[0-9]{2}[0-9]{22}",IS:"IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}",IT:"IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}",JO:"JO[0-9]{2}[A-Z]{4}[0-9]{4}[0]{8}[A-Z0-9]{10}",KW:"KW[0-9]{2}[A-Z]{4}[0-9]{22}",KZ:"KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}",LB:"LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}",LI:"LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}",LT:"LT[0-9]{2}[0-9]{5}[0-9]{11}",LU:"LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}",LV:"LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}",MC:"MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}",MD:"MD[0-9]{2}[A-Z0-9]{20}",ME:"ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",MG:"MG[0-9]{2}[0-9]{23}",MK:"MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}",ML:"ML[0-9]{2}[A-Z]{1}[0-9]{23}",MR:"MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}",MT:"MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}",MU:"MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}",MZ:"MZ[0-9]{2}[0-9]{21}",NL:"NL[0-9]{2}[A-Z]{4}[0-9]{10}",NO:"NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}",PK:"PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}",PL:"PL[0-9]{2}[0-9]{8}[0-9]{16}",PS:"PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}",PT:"PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}",QA:"QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}",RO:"RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}",RS:"RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",SA:"SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}",SE:"SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}",SI:"SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}",SK:"SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}",SM:"SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}",SN:"SN[0-9]{2}[A-Z]{1}[0-9]{23}",TN:"TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",TR:"TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}",VG:"VG[0-9]{2}[A-Z]{4}[0-9]{16}"};d=d.replace(/[^a-zA-Z0-9]/g,"").toUpperCase();var f=c.country||d.substr(0,2);if(!e[f])return!1;if(!new RegExp("^"+e[f]+"$").test(d))return!1;d=d.substr(4)+d.substr(0,4),d=d.split("").map(function(a){var b=a.charCodeAt(0);return b>="A".charCodeAt(0)&&b<="Z".charCodeAt(0)?b-"A".charCodeAt(0)+10:a}).join("");for(var g=parseInt(d.substr(0,1),10),h=d.length,i=1;h>i;++i)g=(10*g+parseInt(d.substr(i,1),10))%97;return 1==g}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={html5Attributes:{message:"message",field:"field"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d==e.val()?(a.updateStatus(c.field,a.STATUS_VALID,"identical"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.imei={validate:function(b,c){var d=c.val();if(""==d)return!0;switch(!0){case/^\d{15}$/.test(d):case/^\d{2}-\d{6}-\d{6}-\d{1}$/.test(d):case/^\d{2}\s\d{6}\s\d{6}\s\d{1}$/.test(d):return d=d.replace(/[^0-9]/g,""),a.fn.bootstrapValidator.helpers.luhn(d);case/^\d{14}$/.test(d):case/^\d{16}$/.test(d):case/^\d{2}-\d{6}-\d{6}(|-\d{2})$/.test(d):case/^\d{2}\s\d{6}\s\d{6}(|\s\d{2})$/.test(d):return!0;default:return!1}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.integer={enableByHtml5:function(a){return"number"==a.attr("type")},validate:function(a,b){var c=b.val();return""==c?!0:/^(?:-?(?:0|[1-9][0-9]*))$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.ip={html5Attributes:{message:"message",ipv4:"ipv4",ipv6:"ipv6"},validate:function(b,c,d){var e=c.val();return""==e?!0:(d=a.extend({},{ipv4:!0,ipv6:!0},d),d.ipv4?/^(?:(?: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(e):d.ipv6?/^\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(str):!1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.isbn={validate:function(a,b){var c=b.val();if(""==c)return!0;var d;switch(!0){case/^\d{9}[\dX]$/.test(c):case 13==c.length&&/^(\d+)-(\d+)-(\d+)-([\dX])$/.test(c):case 13==c.length&&/^(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(c):d="ISBN10";break;case/^(978|979)\d{9}[\dX]$/.test(c):case 17==c.length&&/^(978|979)-(\d+)-(\d+)-(\d+)-([\dX])$/.test(c):case 17==c.length&&/^(978|979)\s(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(c):d="ISBN13";break;default:return!1}c=c.replace(/[^0-9X]/gi,"");var e,f=c.split(""),g=f.length,h=0;switch(d){case"ISBN10":h=0;for(var i=0;g-1>i;i++)h+=(10-i)*parseInt(f[i]);return e=11-h%11,11==e?e=0:10==e&&(e="X"),e+""==f[g-1];case"ISBN13":h=0;for(var i=0;g-1>i;i++)h+=i%2==0?parseInt(f[i]):3*parseInt(f[i]);return e=10-h%10,10==e&&(e="0"),e+""==f[g-1];default:return!1}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.ismn={validate:function(a,b){var c=b.val();if(""==c)return!0;var d;switch(!0){case/^M\d{9}$/.test(c):case/^M-\d{4}-\d{4}-\d{1}$/.test(c):case/^M\s\d{4}\s\d{4}\s\d{1}$/.test(c):d="ISMN10";break;case/^9790\d{9}$/.test(c):case/^979-0-\d{4}-\d{4}-\d{1}$/.test(c):case/^979\s0\s\d{4}\s\d{4}\s\d{1}$/.test(c):d="ISMN13";break;default:return!1}"ISMN10"==d&&(c="9790"+c.substr(1)),c=c.replace(/[^0-9]/gi,"");for(var e=c.length,f=0,g=[1,3],h=0;e-1>h;h++)f+=parseInt(c.charAt(h))*g[h%2];return f=10-f%10,f==c.charAt(e-1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.issn={validate:function(a,b){var c=b.val();if(""==c)return!0;if(!/^\d{4}\-\d{3}[\dX]$/.test(c))return!1;c=c.replace(/[^0-9X]/gi,"");var d=c.split(""),e=d.length,f=0;"X"==d[7]&&(d[7]=10);for(var g=0;e>g;g++)f+=(8-g)*parseInt(d[g]);return f%11==0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={html5Attributes:{message:"message",value:"value",inclusive:"inclusive"},enableByHtml5:function(a){var b=a.attr("max");return b?{value:b}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!1?d<=c.value:d0:""!=a.trim(c.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.numeric={validate:function(a,b){var c=b.val();return""==c?!0:!isNaN(parseFloat(c))&&isFinite(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.phone={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=(c.country||"US").toUpperCase();switch(e){case"US":default:return d=d.replace(/\D/g,""),/^(?:(1\-?)|(\+1 ?))?\(?(\d{3})[\)\-\.]?(\d{3})[\-\.]?(\d{4})$/.test(d)&&10==d.length}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.regexp={html5Attributes:{message:"message",regexp:"regexp"},enableByHtml5:function(a){var b=a.attr("pattern");return b?{regexp:b}:!1},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e="string"==typeof c.regexp?new RegExp(c.regexp):c.regexp;return e.test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.remote={html5Attributes:{message:"message",url:"url",name:"name"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=c.attr("data-bv-field"),g=d.data;null==g&&(g={}),"function"==typeof g&&(g=g.call(this,b)),g[d.name||f]=e;var h=new a.Deferred,i=a.ajax({type:"POST",url:d.url,dataType:"json",data:g});return i.then(function(a){h.resolve(c,"remote",a.valid===!0||"true"===a.valid)}),h.fail(function(){i.abort()}),h}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.siren={validate:function(b,c){var d=c.val();return""==d?!0:/^\d{9}$/.test(d)?a.fn.bootstrapValidator.helpers.luhn(d):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.siret={validate:function(a,b){var c=b.val();if(""==c)return!0;for(var d,e=0,f=c.length,g=0;f>g;g++)d=parseInt(c.charAt(g),10),g%2==0&&(d=2*d,d>9&&(d-=9)),e+=d;return e%10==0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.step={html5Attributes:{message:"message",base:"baseValue",step:"step"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;if(d=a.extend({},{baseValue:0,step:1},d),e=parseFloat(e),isNaN(e)||!isFinite(e))return!1;var f=function(a,b){var c=Math.pow(10,b);a*=c;var d=a>0|-(0>a),e=a%1===.5*d;return e?(Math.floor(a)+(d>0))/c:Math.round(a)/c},g=function(a,b){if(0==b)return 1;var c=(a+"").split("."),d=(b+"").split("."),e=(1==c.length?0:c[1].length)+(1==d.length?0:d[1].length);return f(a-b*Math.floor(a/b),e)},h=g(e-d.baseValue,d.step);return 0==h||h==d.step}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringCase={html5Attributes:{message:"message","case":"case"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=(c["case"]||"lower").toLowerCase();switch(e){case"upper":return d===d.toUpperCase();case"lower":default:return d===d.toLowerCase() +}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringLength={html5Attributes:{message:"message",min:"min",max:"max"},enableByHtml5:function(a){var b=a.attr("maxlength");return b?{max:parseInt(b,10)}:!1},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=a.trim(e).length;return d.min&&fd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={enableByHtml5:function(a){return"url"==a.attr("type")},validate:function(a,b){var c=b.val();if(""==c)return!0;var d=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uuid={html5Attributes:{message:"message",version:"version"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i},f=c.version?c.version+"":"all";return null==e[f]?!0:e[f].test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.vat={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=c.country||d.substr(0,2),f=["_",e.toLowerCase()].join("");return this[f]&&"function"==typeof this[f]?this[f](d):!0},_at:function(a){if(!/^ATU[0-9]{8}$/.test(a))return!1;a=a.substr(3);for(var b=0,c=[1,2,1,2,1,2,1],d=0,e=0;7>e;e++)d=parseInt(a.charAt(e))*c[e],d>9&&(d=Math.floor(d/10)+d%10),b+=d;return b=10-(b+4)%10,10==b&&(b=0),b==a.substr(7,1)},_be:function(a){if(!/^BE[0]{0,1}[0-9]{9}$/.test(a))return!1;if(a=a.substr(2),9==a.length&&(a="0"+a),0==a.substr(1,1))return!1;var b=parseInt(a.substr(0,8),10)+parseInt(a.substr(8,2),10);return b%97==0},_bg:function(a){if(!/^BG[0-9]{9,10}$/.test(a))return!1;a=a.substr(2);var b=0,c=0;if(9==a.length){for(c=0;8>c;c++)b+=parseInt(a.charAt(c))*(c+1);if(b%=11,10==b)for(b=0,c=0;8>c;c++)b+=parseInt(a.charAt(c))*(c+3);return b%=10,b==a.substr(8)}if(10==a.length){var d=function(a){var b=parseInt(a.substr(0,2),10)+1900,c=parseInt(a.substr(2,2),10),d=parseInt(a.substr(4,2),10);c>40?(b+=100,c-=40):c>20&&(b-=100,c-=20);try{{new Date(b,c,d)}}catch(e){return!1}for(var f=0,g=[2,4,8,5,10,9,7,3,6],h=0;9>h;h++)f+=parseInt(a.charAt(h))*g[h];return f=f%11%10,f==a.substr(9,1)},e=function(a){for(var b=0,c=[21,19,17,13,11,9,7,3,1],d=0;9>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%=10,b==a.substr(9,1)},f=function(a){for(var b=0,c=[4,3,2,7,6,5,4,3,2],d=0;9>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,10==b?!1:(11==b&&(b=0),b==a.substr(9,1))};return d(a)||e(a)||f(a)}return!1},_ch:function(a){if(!/^CHE[0-9]{9}(MWST)?$/.test(a))return!1;a=a.substr(3);for(var b=0,c=[5,4,3,2,7,6,5,4],d=0;8>d;d++)b+=parseInt(a.charAt(d),10)*c[d];return b=11-b%11,10==b?!1:(11==b&&(b=0),b==a.substr(8,1))},_cy:function(a){if(!/^CY[0-5|9]{1}[0-9]{7}[A-Z]{1}$/.test(a))return!1;if(a=a.substr(2),"12"==a.substr(0,2))return!1;for(var b=0,c={0:1,1:0,2:5,3:7,4:9,5:13,6:15,7:17,8:19,9:21},d=0;8>d;d++){var e=parseInt(a.charAt(d),10);d%2==0&&(e=c[e+""]),b+=e}return b="ABCDEFGHIJKLMNOPQRSTUVWXYZ"[b%26],b==a.substr(8,1)},_cz:function(a){if(!/^CZ[0-9]{8,10}$/.test(a))return!1;a=a.substr(2);var b=0,c=0;if(8==a.length){if(a.charAt(0)+""=="9")return!1;for(b=0,c=0;7>c;c++)b+=parseInt(a.charAt(c),10)*(8-c);return b=11-b%11,10==b&&(b=0),11==b&&(b=1),b==a.substr(7,1)}if(9==a.length&&a.charAt(0)+""=="6"){for(b=0,c=0;7>c;c++)b+=parseInt(a.charAt(c+1),10)*(8-c);return b=11-b%11,10==b&&(b=0),11==b&&(b=1),b=[8,7,6,5,4,3,2,1,0,9,10][b-1],b==a.substr(8,1)}if(9==a.length||10==a.length){var d=1900+parseInt(a.substr(0,2)),e=parseInt(a.substr(2,2))%50%20,f=parseInt(a.substr(4,2));if(9==a.length){if(d>=1980&&(d-=100),d>1953)return!1}else 1954>d&&(d+=100);try{{new Date(d,e,f)}}catch(g){return!1}if(10==a.length){var h=parseInt(a.substr(0,9),10)%11;return 1985>d&&(h%=10),h==a.substr(9,1)}return!0}return!1},_de:function(b){return/^DE[0-9]{9}$/.test(b)?(b=b.substr(2),a.fn.bootstrapValidator.helpers.mod_11_10(b)):!1},_dk:function(a){if(!/^DK[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[2,7,6,5,4,3,2,1],d=0;8>d;d++)b+=parseInt(a.charAt(d),10)*c[d];return b%11==0},_ee:function(a){if(!/^EE[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[3,7,1,3,7,1,3,7,1],d=0;9>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%10==0},_es:function(a){if(!/^ES[0-9A-Z][0-9]{7}[0-9A-Z]$/.test(a))return!1;a=a.substr(2);var b=function(a){var b=parseInt(a.substr(0,8),10);return b="TRWAGMYFPDXBNJZSQVHLCKE"[b%23],b==a.substr(8,1)},c=function(a){var b=["XYZ".indexOf(a.charAt(0)),a.substr(1)].join("");return b=parseInt(b,10),b="TRWAGMYFPDXBNJZSQVHLCKE"[b%23],b==a.substr(8,1)},d=function(a){var b,c=a.charAt(0);if(-1!="KLM".indexOf(c))return b=parseInt(a.substr(1,8),10),b="TRWAGMYFPDXBNJZSQVHLCKE"[b%23],b==a.substr(8,1);if(-1!="ABCDEFGHJNPQRSUVW".indexOf(c)){for(var d=0,e=[2,1,2,1,2,1,2],f=0,g=0;7>g;g++)f=parseInt(a.charAt(g+1))*e[g],f>9&&(f=Math.floor(f/10)+f%10),d+=f;return d=10-d%10,d==a.substr(8,1)||"JABCDEFGHI"[d]==a.substr(8,1)}return!1},e=a.charAt(0);return/^[0-9]$/.test(e)?b(a):/^[XYZ]$/.test(e)?c(a):d(a)},_fi:function(a){if(!/^FI[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[7,9,10,5,8,4,2,1],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%11==0},_fr:function(b){if(!/^FR[0-9A-Z]{2}[0-9]{9}$/.test(b))return!1;if(b=b.substr(2),!a.fn.bootstrapValidator.helpers.luhn(b.substr(2)))return!1;if(/^[0-9]{2}$/.test(b.substr(0,2)))return b.substr(0,2)==parseInt(b.substr(2)+"12",10)%97;var c,d="0123456789ABCDEFGHJKLMNPQRSTUVWXYZ";return c=/^[0-9]{1}$/.test(b.charAt(0))?24*d.indexOf(b.charAt(0))+d.indexOf(b.charAt(1))-10:34*d.indexOf(b.charAt(0))+d.indexOf(b.charAt(1))-100,(parseInt(b.substr(2),10)+1+Math.floor(c/11))%11==c%11},_gb:function(a){if(!(/^GB[0-9]{9}$/.test(a)||/^GB[0-9]{12}$/.test(a)||/^GBGD[0-9]{3}$/.test(a)||/^GBHA[0-9]{3}$/.test(a)||/^GB(GD|HA)8888[0-9]{5}$/.test(a)))return!1;a=a.substr(2);var b=a.length;if(5==b){var c=a.substr(0,2),d=parseInt(a.substr(2));return"GD"==c&&500>d||"HA"==c&&d>=500}if(11==b&&("GD8888"==a.substr(0,6)||"HA8888"==a.substr(0,6)))return"GD"==a.substr(0,2)&&parseInt(a.substr(6,3))>=500||"HA"==a.substr(0,2)&&parseInt(a.substr(6,3))<500?!1:parseInt(a.substr(6,3))%97==parseInt(a.substr(9,2));if(9==b||12==b){for(var e=0,f=[8,7,6,5,4,3,2,10,1],g=0;9>g;g++)e+=parseInt(a.charAt(g))*f[g];return e%=97,parseInt(a.substr(0,3))>=100?0==e||42==e||55==e:0==e}return!0},_gr:function(a){if(!/^GR[0-9]{9}$/.test(a))return!1;a=a.substr(2),8==a.length&&(a="0"+a);for(var b=0,c=[256,128,64,32,16,8,4,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=b%11%10,b==a.substr(8,1)},_el:function(a){return/^EL[0-9]{9}$/.test(a)?(a="GR"+a.substr(2),this._gr(a)):!1},_hu:function(a){if(!/^HU[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[9,7,3,1,9,7,3,1],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%10==0},_hr:function(b){return/^HR[0-9]{11}$/.test(b)?(b=b.substr(2),a.fn.bootstrapValidator.helpers.mod_11_10(b)):!1},_ie:function(a){if(!/^IE[0-9]{1}[0-9A-Z\*\+]{1}[0-9]{5}[A-Z]{1,2}$/.test(a))return!1;a=a.substr(2);var b=function(a){for(;a.length<7;)a="0"+a;for(var b="WABCDEFGHIJKLMNOPQRSTUV",c=0,d=0;7>d;d++)c+=parseInt(a.charAt(d))*(8-d);return c+=9*b.indexOf(a.substr(7)),b[c%23]};return/^[0-9]+$/.test(a.substr(0,7))?a.charAt(7)==b(a.substr(0,7)+a.substr(8)+""):-1!="ABCDEFGHIJKLMNOPQRSTUVWXYZ+*".indexOf(a.charAt(1))?a.charAt(7)==b(a.substr(2,5)+a.substr(0,1)+""):!0},_it:function(b){if(!/^IT[0-9]{11}$/.test(b))return!1;if(b=b.substr(2),0==parseInt(b.substr(0,7)))return!1;var c=parseInt(b.substr(7,3));return 1>c||c>201&&999!=c&&888!=c?!1:a.fn.bootstrapValidator.helpers.luhn(b)},_lt:function(a){if(!/^LT([0-9]{7}1[0-9]{1}|[0-9]{10}1[0-9]{1})$/.test(a))return!1;a=a.substr(2);for(var b=a.length,c=0,d=0;b-1>d;d++)c+=parseInt(a.charAt(d))*(1+d%9);var e=c%11;if(10==e){c=0;for(var d=0;b-1>d;d++)c+=parseInt(a.charAt(d))*(1+(d+2)%9)}return e=e%11%10,e==a.charAt(b-1)},_lu:function(a){return/^LU[0-9]{8}$/.test(a)?(a=a.substr(2),a.substr(0,6)%89==a.substr(6,2)):!1},_lv:function(a){if(!/^LV[0-9]{11}$/.test(a))return!1;a=a.substr(2);var b=parseInt(a.charAt(0)),c=0,d=[],e=0,f=a.length;if(b>3){for(c=0,d=[9,1,4,8,3,10,2,5,7,6,1],e=0;f>e;e++)c+=parseInt(a.charAt(e))*d[e];return c%=11,3==c}var g=parseInt(a.substr(0,2)),h=parseInt(a.substr(2,2)),i=parseInt(a.substr(4,2));i=i+1800+100*parseInt(a.charAt(6));try{{new Date(i,h,g)}}catch(j){return!1}for(c=0,d=[10,5,8,4,2,1,6,3,7,9],e=0;f-1>e;e++)c+=parseInt(a.charAt(e))*d[e];return c=(c+1)%11%10,c==a.charAt(f-1)},_mt:function(a){if(!/^MT[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[3,4,6,7,8,9,10,1],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%37==0},_nl:function(a){if(!/^NL[0-9]{9}B[0-9]{2}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[9,8,7,6,5,4,3,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%=11,b>9&&(b=0),b==a.substr(8,1)},_no:function(a){if(!/^NO[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[3,2,7,6,5,4,3,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,11==b&&(b=0),b==a.substr(8,1)},_pl:function(a){if(!/^PL[0-9]{10}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[6,5,7,2,3,4,5,6,7,-1],d=0;10>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%11==0},_pt:function(a){if(!/^PT[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[9,8,7,6,5,4,3,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,b>9&&(b=0),b==a.substr(8,1)},_ro:function(a){if(!/^RO[1-9][0-9]{1,9}$/.test(a))return!1;a=a.substr(2);for(var b=a.length,c=[7,5,3,2,1,7,5,3,2].slice(10-b),d=0,e=0;b-1>e;e++)d+=parseInt(a.charAt(e))*c[e];return d=10*d%11%10,d==a.substr(b-1,1)},_ru:function(a){if(!/^RU([0-9]{9}|[0-9]{12})$/.test(a))return!1;if(a=a.substr(2),10==a.length){for(var b=0,c=[2,4,10,3,5,9,4,6,8,0],d=0;10>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%=11,b>9&&(b%=10),b==a.substr(9,1)}if(12==a.length){for(var e=0,f=[7,2,4,10,3,5,9,4,6,8,0],g=0,h=[3,7,2,4,10,3,5,9,4,6,8,0],d=0;11>d;d++)e+=parseInt(a.charAt(d))*f[d],g+=parseInt(a.charAt(d))*h[d];return e%=11,e>9&&(e%=10),g%=11,g>9&&(g%=10),e==a.substr(10,1)&&g==a.substr(11,1)}return!1},_rs:function(a){if(!/^RS[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=10,c=0,d=0;8>d;d++)c=(parseInt(a.charAt(d))+b)%10,0==c&&(c=10),b=2*c%11;return(b+parseInt(a.substr(8,1)))%10==1},_se:function(b){return/^SE[0-9]{10}01$/.test(b)?(b=b.substr(2,10),a.fn.bootstrapValidator.helpers.luhn(b)):!1},_si:function(a){if(!/^SI[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[8,7,6,5,4,3,2],d=0;7>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,10==b&&(b=0),b==a.substr(7,1)},_sk:function(a){return/^SK[1-9][0-9][(2-4)|(6-9)][0-9]{7}$/.test(a)?(a=a.substr(2),a%11==0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.vin={validate:function(a,b){var c=b.val();if(""==c)return!0;if(!/^[a-hj-npr-z0-9]{8}[0-9xX][a-hj-npr-z0-9]{8}$/i.test(c))return!1;c=c.toUpperCase();for(var d={A:1,B:2,C:3,D:4,E:5,F:6,G:7,H:8,J:1,K:2,L:3,M:4,N:5,P:7,R:9,S:2,T:3,U:4,V:5,W:6,X:7,Y:8,Z:9,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,0:0},e=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],f=0,g=c.length,h=0;g>h;h++)f+=d[c.charAt(h)+""]*e[h];var i=f%11;return 10==i&&(i="X"),i==c.charAt(8)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.zipCode={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d||!c.country)return!0;var e=(c.country||"US").toUpperCase();switch(e){case"CA":return/(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}\s?[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}/i.test(d);case"DK":return/^(DK(-|\s)?)?\d{4}$/i.test(d);case"GB":return this._gb(d);case"SE":return/^(S-)?\d{3}\s?\d{2}$/i.test(d);case"US":default:return/^\d{4,5}([\-]\d{4})?$/.test(d)}},_gb:function(a){for(var b="[ABCDEFGHIJKLMNOPRSTUWYZ]",c="[ABCDEFGHKLMNOPQRSTUVWXY]",d="[ABCDEFGHJKPMNRSTUVWXY]",e="[ABEHMNPRVWXY]",f="[ABDEFGHJLNPQRSTUWXYZ]",g=[new RegExp("^("+b+"{1}"+c+"?[0-9]{1,2})(\\s*)([0-9]{1}"+f+"{2})$","i"),new RegExp("^("+b+"{1}[0-9]{1}"+d+"{1})(\\s*)([0-9]{1}"+f+"{2})$","i"),new RegExp("^("+b+"{1}"+c+"{1}?[0-9]{1}"+e+"{1})(\\s*)([0-9]{1}"+f+"{2})$","i"),new RegExp("^(BF1)(\\s*)([0-6]{1}[ABDEFGHJLNPQRST]{1}[ABDEFGHJLNPQRSTUWZYZ]{1})$","i"),/^(GIR)(\s*)(0AA)$/i,/^(BFPO)(\s*)([0-9]{1,4})$/i,/^(BFPO)(\s*)(c\/o\s*[0-9]{1,3})$/i,/^([A-Z]{4})(\s*)(1ZZ)$/i,/^(AI-2640)$/i],h=0;h a { + color: #3c763d; +} +.nav-tabs li.bv-tab-error > a { + color: #a94442; +} diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.5/css/bootstrapValidator.min.css b/ajax/libs/jquery.bootstrapvalidator/0.4.5/css/bootstrapValidator.min.css new file mode 100644 index 000000000..030cbdf75 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.5/css/bootstrapValidator.min.css @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * The best jQuery plugin to validate form fields. Designed to use with Bootstrap 3 + * + * @version v0.4.5 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + + +.bv-form .help-block{margin-bottom:0}.nav-tabs li.bv-tab-success>a{color:#3c763d}.nav-tabs li.bv-tab-error>a{color:#a94442} \ No newline at end of file diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.5/js/bootstrapValidator.js b/ajax/libs/jquery.bootstrapvalidator/0.4.5/js/bootstrapValidator.js new file mode 100644 index 000000000..a90718dfc --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.5/js/bootstrapValidator.js @@ -0,0 +1,4967 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * The best jQuery plugin to validate form fields. Designed to use with Bootstrap 3 + * + * @version v0.4.5 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +(function($) { + var BootstrapValidator = function(form, options) { + this.$form = $(form); + this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options); + + this.$invalidField = null; // First invalid field + this.$submitButton = null; // The submit button which is clicked to submit form + + // Validating status + this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED'; + this.STATUS_VALIDATING = 'VALIDATING'; + this.STATUS_INVALID = 'INVALID'; + this.STATUS_VALID = 'VALID'; + + // Determine the event that is fired when user change the field value + // Most modern browsers supports input event except IE 7, 8. + // IE 9 supports input event but the event is still not fired if I press the backspace key. + // Get IE version + // https://gist.github.com/padolsey/527683/#comment-7595 + var ieVersion = (function() { + var v = 3, div = document.createElement('div'), a = div.all || []; + while (div.innerHTML = '', a[0]); + return v > 4 ? v : !v; + }()); + + var el = document.createElement('div'); + this._changeEvent = (ieVersion === 9 || !('oninput' in el)) ? 'keyup' : 'input'; + + // The flag to indicate that the form is ready to submit when a remote/callback validator returns + this._submitIfValid = null; + + this._init(); + }; + + // The default options + BootstrapValidator.DEFAULT_OPTIONS = { + // The form CSS class + elementClass: 'bv-form', + + // Default invalid message + message: 'This value is not valid', + + // The field will not be live validated if its length is less than this number of characters + threshold: null, + + // Indicate fields which won't be validated + // By default, the plugin will not validate the following kind of fields: + // - disabled + // - hidden + // - invisible + // + // The setting consists of jQuery filters. Accept 3 formats: + // - A string. Use a comma to separate filter + // - An array. Each element is a filter + // - An array. Each element can be a callback function + // function($field, validator) { + // $field is jQuery object representing the field element + // validator is the BootstrapValidator instance + // return true or false; + // } + // + // The 3 following settings are equivalent: + // + // 1) ':disabled, :hidden, :not(:visible)' + // 2) [':disabled', ':hidden', ':not(:visible)'] + // 3) [':disabled', ':hidden', function($field) { + // return !$field.is(':visible'); + // }] + excluded: [':disabled', ':hidden', ':not(:visible)'], + + // Shows ok/error/loading icons based on the field validity. + // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation). + // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically. + // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later. + // + // Examples: + // - Use Glyphicons icons: + // feedbackIcons: { + // valid: 'glyphicon glyphicon-ok', + // invalid: 'glyphicon glyphicon-remove', + // validating: 'glyphicon glyphicon-refresh' + // } + // - Use FontAwesome icons: + // feedbackIcons: { + // valid: 'fa fa-check', + // invalid: 'fa fa-times', + // validating: 'fa fa-refresh' + // } + feedbackIcons: { + valid: null, + invalid: null, + validating: null + }, + + // The submit buttons selector + // These buttons will be disabled to prevent the valid form from multiple submissions + submitButtons: '[type="submit"]', + + // The custom submit handler + // It will prevent the form from the default submission + // + // submitHandler: function(validator, form) { + // - validator is the BootstrapValidator instance + // - form is the jQuery object present the current form + // } + submitHandler: null, + + // Live validating option + // Can be one of 3 values: + // - enabled: The plugin validates fields as soon as they are changed + // - 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 + }; + + BootstrapValidator.prototype = { + constructor: BootstrapValidator, + + /** + * Init form + */ + _init: function() { + var that = this, + options = { + excluded: this.$form.attr('data-bv-excluded'), + trigger: this.$form.attr('data-bv-trigger'), + message: this.$form.attr('data-bv-message'), + submitButtons: this.$form.attr('data-bv-submitbuttons'), + threshold: this.$form.attr('data-bv-threshold'), + live: this.$form.attr('data-bv-live'), + 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') + } + }, + validator, + v, // Validator name + enabled, + optionName, + optionValue, + html5AttrName, + html5Attrs; + + this.$form + // Disable client side validation in HTML 5 + .attr('novalidate', 'novalidate') + .addClass(this.options.elementClass) + // Disable the default submission first + .on('submit.bv', function(e) { + e.preventDefault(); + that.validate(); + }) + .on('click', this.options.submitButtons, function() { + that.$submitButton = $(this); + // The user just click the submit button + that._submitIfValid = true; + }) + // Find all fields which have either "name" or "data-bv-field" attribute + .find('[name], [data-bv-field]') + .each(function() { + var $field = $(this); + if (that._isExcluded($field)) { + return; + } + + var field = $field.attr('name') || $field.attr('data-bv-field'), + validators = {}; + for (v in $.fn.bootstrapValidator.validators) { + validator = $.fn.bootstrapValidator.validators[v]; + enabled = $field.attr('data-bv-' + v.toLowerCase()) + ''; + html5Attrs = ('function' == typeof validator.enableByHtml5) ? validator.enableByHtml5($(this)) : null; + + if ((html5Attrs && enabled != 'false') + || (html5Attrs !== true && ('' == enabled || 'true' == enabled))) + { + // Try to parse the options via attributes + validator.html5Attributes = validator.html5Attributes || { message: 'message' }; + validators[v] = $.extend({}, html5Attrs == true ? {} : html5Attrs, validators[v]); + + for (html5AttrName in validator.html5Attributes) { + optionName = validator.html5Attributes[html5AttrName]; + optionValue = $field.attr('data-bv-' + v.toLowerCase() + '-' + html5AttrName); + if (optionValue) { + if ('true' == optionValue) { + optionValue = true; + } else if ('false' == optionValue) { + optionValue = false; + } + validators[v][optionName] = optionValue; + } + } + } + } + + var opts = { + trigger: $field.attr('data-bv-trigger'), + message: $field.attr('data-bv-message'), + container: $field.attr('data-bv-container'), + selector: $field.attr('data-bv-selector'), + threshold: $field.attr('data-bv-threshold'), + validators: validators + }; + + // Check if there is any validators set using HTML attributes + if (!$.isEmptyObject(opts.validators) && !$.isEmptyObject(opts)) { + $field.attr('data-bv-field', field); + options.fields[field] = $.extend({}, opts, options.fields[field]); + } + }) + .end() + // Create hidden inputs to send the submit buttons + .find(this.options.submitButtons) + .each(function() { + $('') + .attr('type', 'hidden') + .attr('name', $(this).attr('name')) + .val($(this).val()) + .appendTo(that.$form); + }); + + this.options = $.extend(true, this.options, options); + for (var field in this.options.fields) { + this._initField(field); + } + + this.setLiveMode(this.options.live); + }, + + /** + * Init field + * + * @param {String} field The field name + */ + _initField: function(field) { + if (this.options.fields[field] == null || this.options.fields[field].validators == null) { + return; + } + + var fields = this.getFieldElements(field); + + // We don't need to validate non-existing fields + if (fields == null) { + delete this.options.fields[field]; + return; + } + for (var validatorName in this.options.fields[field].validators) { + if (!$.fn.bootstrapValidator.validators[validatorName]) { + delete this.options.fields[field].validators[validatorName]; + } + } + + var that = this, + type = fields.attr('type'), + event = ('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent, + total = fields.length, + updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type); + + for (var i = 0; i < total; i++) { + var $field = $(fields[i]), + $parent = $field.parents('.form-group'), + // Allow user to indicate where the error messages are shown + $message = this.options.fields[field].container ? $parent.find(this.options.fields[field].container) : this._getMessageContainer($field); + + // Set the attribute to indicate the fields which are defined by selector + if (!$field.attr('data-bv-field')) { + $field.attr('data-bv-field', field); + } + + // Whenever the user change the field value, mark it as not validated yet + $field.on(event + '.update.bv', function() { + // Reset the flag + that._submitIfValid = false; + updateAll ? that.updateStatus(field, that.STATUS_NOT_VALIDATED, null) + : that.updateElementStatus($(this), that.STATUS_NOT_VALIDATED, null); + }); + + // Create help block elements for showing the error messages + $field.data('bv.messages', $message); + for (validatorName in this.options.fields[field].validators) { + $field.data('bv.result.' + validatorName, this.STATUS_NOT_VALIDATED); + + if (!updateAll || i == total - 1) { + $('') + .css('display', 'none') + .attr('data-bv-validator', validatorName) + .attr('data-bv-validator-for', field) + .html(this.options.fields[field].validators[validatorName].message || this.options.fields[field].message || this.options.message) + .addClass('help-block') + .appendTo($message); + } + } + + // Prepare the feedback icons + // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation) + if (this.options.feedbackIcons + && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid + && (!updateAll || i == total - 1)) + { + $parent.addClass('has-feedback'); + var $icon = $('').css('display', 'none').addClass('form-control-feedback').attr('data-bv-icon-for', field).insertAfter($field); + // The feedback icon does not render correctly if there is no label + // https://github.com/twbs/bootstrap/issues/12873 + if ($parent.find('label').length == 0) { + $icon.css('top', 0); + } + } + } + + if (this.options.fields[field]['enabled'] == null) { + this.options.fields[field]['enabled'] = true; + } + }, + + /** + * Get the element to place the error messages + * + * @param {jQuery} $field The field element + * @returns {jQuery} + */ + _getMessageContainer: function($field) { + var $parent = $field.parent(); + if ($parent.hasClass('form-group')) { + return $parent; + } + + var cssClasses = $parent.attr('class'); + if (!cssClasses) { + return this._getMessageContainer($parent); + } + + cssClasses = cssClasses.split(' '); + var n = cssClasses.length; + for (var i = 0; i < n; i++) { + if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i]) || /^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { + return $parent; + } + } + + return this._getMessageContainer($parent); + }, + + /** + * Called when all validations are completed + */ + _submit: function() { + if (!this.isValid()) { + if ('submitted' == this.options.live) { + this.setLiveMode('enabled'); + } + + // Focus to the first invalid field + if (this.$invalidField) { + // Activate the tab containing the invalid field if exists + var $tab = this.$invalidField.parents('.tab-pane'), + tabId; + if ($tab && (tabId = $tab.attr('id'))) { + $('a[href="#' + tabId + '"][data-toggle="tab"]').trigger('click.bs.tab.data-api'); + } + + this.$invalidField.focus(); + } + + return; + } + + // Call the custom submission if enabled + if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) { + // If you want to submit the form inside your submit handler, please call defaultSubmit() method + this.options.submitHandler.call(this, this, this.$form, this.$submitButton); + } else { + this.disableSubmitButtons(true).defaultSubmit(); + } + }, + + /** + * Check if the field is excluded. + * Returning true means that the field will not be validated + * + * @param {jQuery} $field The field element + * @returns {Boolean} + */ + _isExcluded: function($field) { + if (this.options.excluded) { + // Convert to array first + if ('string' == typeof this.options.excluded) { + this.options.excluded = $.map(this.options.excluded.split(','), function(item) { + // Trim the spaces + return $.trim(item); + }); + } + + var length = this.options.excluded.length; + for (var i = 0; i < length; i++) { + if (('string' == typeof this.options.excluded[i] && $field.is(this.options.excluded[i])) + || ('function' == typeof this.options.excluded[i] && this.options.excluded[i].call(this, $field, this) == true)) + { + return true; + } + } + } + + return false; + }, + + /** + * Check if the number of characters of field value exceed the threshold or not + * + * @param {jQuery} $field The field element + * @returns {Boolean} + */ + _exceedThreshold: function($field) { + var field = $field.attr('data-bv-field'), + threshold = this.options.fields[field].threshold || this.options.threshold; + if (!threshold) { + return true; + } + var type = $field.attr('type'), + cannotType = ['button', 'checkbox', 'file', 'hidden', 'image', 'radio', 'reset', 'submit'].indexOf(type) != -1; + return (cannotType || $field.val().length >= threshold); + }, + + // --- Public methods --- + + /** + * Retrieve the field elements by given name + * + * @param {String} field The field name + * @returns {null|jQuery[]} + */ + getFieldElements: function(field) { + var fields = this.options.fields[field].selector ? $(this.options.fields[field].selector) : this.$form.find('[name="' + field + '"]'); + return (fields.length == 0) ? null : fields; + }, + + /** + * Set live validating mode + * + * @param {String} mode Live validating mode. Can be 'enabled', 'disabled', 'submitted' + * @returns {BootstrapValidator} + */ + setLiveMode: function(mode) { + this.options.live = mode; + if ('submitted' == mode) { + return this; + } + + var that = this; + for (var field in this.options.fields) { + (function(f) { + var fields = that.getFieldElements(f); + if (fields) { + var type = fields.attr('type'), + total = fields.length, + updateAll = (total == 1) || ('radio' == type) || ('checkbox' == type), + trigger = that.options.fields[field].trigger + || that.options.trigger + || (('radio' == type || 'checkbox' == type || 'file' == type || 'SELECT' == fields[0].tagName) ? 'change' : that._changeEvent), + events = $.map(trigger.split(' '), function(item) { + return item + '.live.bv'; + }).join(' '); + + for (var i = 0; i < total; i++) { + ('enabled' == mode) + ? $(fields[i]).on(events, function() { + if (that._exceedThreshold($(this))) { + updateAll ? that.validateField(f) : that.validateFieldElement($(this), false); + } + }) + : $(fields[i]).off(events); + } + } + })(field); + } + + return this; + }, + + /** + * Disable/enable submit buttons + * + * @param {Boolean} disabled Can be true or false + * @returns {BootstrapValidator} + */ + disableSubmitButtons: function(disabled) { + if (!disabled) { + this.$form.find(this.options.submitButtons).removeAttr('disabled'); + } else if (this.options.live != 'disabled') { + // Don't disable if the live validating mode is disabled + this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); + } + + return this; + }, + + /** + * Validate the form + * + * @returns {BootstrapValidator} + */ + validate: function() { + if (!this.options.fields) { + return this; + } + this.disableSubmitButtons(true); + + for (var field in this.options.fields) { + this.validateField(field); + } + + // Check if whether the submit button is clicked + if (this.$submitButton) { + this._submit(); + } + + return this; + }, + + /** + * Validate given field + * + * @param {String} field The field name + * @returns {BootstrapValidator} + */ + validateField: function(field) { + var fields = this.getFieldElements(field), + type = fields.attr('type'), + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (var i = 0; i < n; i++) { + this.validateFieldElement($(fields[i]), (n == 1)); + } + + return this; + }, + + /** + * Validate field element + * + * @param {jQuery} $field The field element + * @param {Boolean} updateAll If true, update status of all elements which have the same name + * @returns {BootstrapValidator} + */ + validateFieldElement: function($field, updateAll) { + var that = this, + field = $field.attr('data-bv-field'), + validators = this.options.fields[field].validators, + validatorName, + validateResult; + + if (!this.options.fields[field]['enabled'] || this._isExcluded($field)) { + return this; + } + + for (validatorName in validators) { + if ($field.data('bv.dfs.' + validatorName)) { + $field.data('bv.dfs.' + validatorName).reject(); + } + + // Don't validate field if it is already done + var result = $field.data('bv.result.' + validatorName); + if (result == this.STATUS_VALID || result == this.STATUS_INVALID) { + continue; + } + + $field.data('bv.result.' + validatorName, this.STATUS_VALIDATING); + validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]); + + if ('object' == typeof validateResult) { + updateAll ? this.updateStatus(field, this.STATUS_VALIDATING, validatorName) + : this.updateElementStatus($field, this.STATUS_VALIDATING, validatorName); + $field.data('bv.dfs.' + validatorName, validateResult); + + validateResult.done(function($f, v, isValid) { + // v is validator name + $f.removeData('bv.dfs.' + v); + updateAll ? that.updateStatus($f.attr('data-bv-field'), isValid ? that.STATUS_VALID : that.STATUS_INVALID, v) + : that.updateElementStatus($f, isValid ? that.STATUS_VALID : that.STATUS_INVALID, v); + + if (isValid && that._submitIfValid == true) { + // If a remote validator returns true and the form is ready to submit, then do it + that._submit(); + } + }); + } else if ('boolean' == typeof validateResult) { + updateAll ? this.updateStatus(field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName) + : this.updateElementStatus($field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName); + } + } + + return this; + }, + + /** + * Update all validating results of elements which have the same field name + * + * @param {String} field The field name + * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators + * @returns {BootstrapValidator} + */ + updateStatus: function(field, status, validatorName) { + var fields = this.getFieldElements(field), + type = fields.attr('type'), + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (var i = 0; i < n; i++) { + this.updateElementStatus($(fields[i]), status, validatorName); + } + + return this; + }, + + /** + * Update validating result of given element + * + * @param {jQuery} $field The field element + * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' + * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators + * @returns {BootstrapValidator} + */ + updateElementStatus: function($field, status, validatorName) { + var that = this, + field = $field.attr('data-bv-field'), + $parent = $field.parents('.form-group'), + $message = $field.data('bv.messages'), + $errors = $message.find('.help-block[data-bv-validator]'), + $icon = $parent.find('.form-control-feedback[data-bv-icon-for="' + field + '"]'); + + // Update status + if (validatorName) { + $field.data('bv.result.' + validatorName, status); + } else { + for (var v in this.options.fields[field].validators) { + $field.data('bv.result.' + v, status); + } + } + + // Determine the tab containing the element + var $tabPane = $field.parents('.tab-pane'), + tabId, + $tab; + if ($tabPane && (tabId = $tabPane.attr('id'))) { + $tab = $('a[href="#' + tabId + '"][data-toggle="tab"]').parent(); + } + + // Show/hide error elements and feedback icons + switch (status) { + case this.STATUS_VALIDATING: + this.disableSubmitButtons(true); + $parent.removeClass('has-success').removeClass('has-error'); + // TODO: Show validating message + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(); + } + if ($tab) { + $tab.removeClass('bv-tab-success').removeClass('bv-tab-error'); + } + break; + + case this.STATUS_INVALID: + this.disableSubmitButtons(true); + $parent.removeClass('has-success').addClass('has-error'); + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').show() : $errors.show(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(); + } + if ($tab) { + $tab.removeClass('bv-tab-success').addClass('bv-tab-error'); + } + break; + + case this.STATUS_VALID: + validatorName ? $errors.filter('[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + + // If the field is valid (passes all validators) + var validField = ($errors.filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || ($field.data('bv.result.' + v) != that.STATUS_VALID); + }).length == 0); + this.disableSubmitButtons(!validField); + if ($icon) { + $icon + .removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid) + .addClass(validField ? this.options.feedbackIcons.valid : this.options.feedbackIcons.invalid) + .show(); + } + + // Check if all elements in given container are valid + var isValidContainer = function($container) { + return $container + .find('.help-block[data-bv-validator]') + .filter(function() { + var display = $(this).css('display'), v = $(this).attr('data-bv-validator'); + return ('block' == display) || ($field.data('bv.result.' + v) && $field.data('bv.result.' + v) != that.STATUS_VALID); + }) + .length == 0; + }; + $parent.removeClass('has-error has-success').addClass(isValidContainer($parent) ? 'has-success' : 'has-error'); + if ($tab) { + $tab.removeClass('bv-tab-success').removeClass('bv-tab-error').addClass(isValidContainer($tabPane) ? 'bv-tab-success' : 'bv-tab-error'); + } + break; + + case this.STATUS_NOT_VALIDATED: + default: + this.disableSubmitButtons(false); + $parent.removeClass('has-success').removeClass('has-error'); + validatorName ? $errors.filter('.help-block[data-bv-validator="' + validatorName + '"]').hide() : $errors.hide(); + if ($icon) { + $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide(); + } + if ($tab) { + $tab.removeClass('bv-tab-success').removeClass('bv-tab-error'); + } + break; + } + + return this; + }, + + /** + * Check the form validity + * + * @returns {Boolean} + */ + isValid: function() { + var fields, field, $field, + type, status, validatorName, + n, i; + for (field in this.options.fields) { + if (this.options.fields[field] == null || !this.options.fields[field]['enabled']) { + continue; + } + + fields = this.getFieldElements(field); + type = fields.attr('type'); + n = (('radio' == type) || ('checkbox' == type)) ? 1 : fields.length; + + for (i = 0; i < n; i++) { + $field = $(fields[i]); + if (this._isExcluded($field)) { + continue; + } + + for (validatorName in this.options.fields[field].validators) { + status = $field.data('bv.result.' + validatorName); + if (status == this.STATUS_NOT_VALIDATED || status == this.STATUS_VALIDATING) { + return false; + } + + if (status == this.STATUS_INVALID) { + this.$invalidField = $field; + return false; + } + } + } + } + + return true; + }, + + /** + * Submit the form using default submission. + * It also does not perform any validations when submitting the form + * + * It might be used when you want to submit the form right inside the submitHandler() + */ + defaultSubmit: function() { + this.$form.off('submit.bv').submit(); + }, + + // Useful APIs which aren't used internally + + /** + * Reset the form + * + * @param {Boolean} resetFormData Reset current form data + * @returns {BootstrapValidator} + */ + resetForm: function(resetFormData) { + var field, fields, total, type, validator; + for (field in this.options.fields) { + fields = this.getFieldElements(field); + total = fields.length; + + for (var i = 0; i < total; i++) { + for (validator in this.options.fields[field].validators) { + $(fields[i]).removeData('bv.dfs.' + validator); + } + } + + // Mark field as not validated yet + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + if (resetFormData) { + type = fields.attr('type'); + ('radio' == type || 'checkbox' == type) ? fields.removeAttr('checked').removeAttr('selected') : fields.val(''); + } + } + + this.$invalidField = null; + this.$submitButton = null; + + // Enable submit buttons + this.disableSubmitButtons(false); + + return this; + }, + + /** + * Enable/Disable all validators to given field + * + * @param {String} field The field name + * @param {Boolean} enabled Enable/Disable field validators + * @returns {BootstrapValidator} + */ + enableFieldValidators: function(field, enabled) { + this.options.fields[field]['enabled'] = enabled; + this.updateStatus(field, this.STATUS_NOT_VALIDATED, null); + + return this; + } + }; + + // Plugin definition + $.fn.bootstrapValidator = function(option) { + var params = arguments; + return this.each(function() { + var $this = $(this), + data = $this.data('bootstrapValidator'), + options = 'object' == typeof option && option; + if (!data) { + data = new BootstrapValidator(this, options); + $this.data('bootstrapValidator', data); + } + + // Allow to call plugin method + if ('string' == typeof option) { + data[option].apply(data, Array.prototype.slice.call(params, 1)); + } + }); + }; + + // Available validators + $.fn.bootstrapValidator.validators = {}; + + $.fn.bootstrapValidator.Constructor = BootstrapValidator; + + // Helper methods, which can be used in validator class + $.fn.bootstrapValidator.helpers = { + /** + * Validate a date + * + * @param {Number} year The full year in 4 digits + * @param {Number} month The month number + * @param {Number} day The day number + * @param {Boolean} [notInFuture] If true, the date must not be in the future + * @returns {Boolean} + */ + date: function(year, month, day, notInFuture) { + if (year < 1000 || year > 9999 || month == 0 || month > 12) { + return false; + } + var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; + // Update the number of days in Feb of leap year + if (year % 400 == 0 || (year % 100 != 0 && year % 4 == 0)) { + numDays[1] = 29; + } + + // Check the day + if (day < 0 || day > numDays[month - 1]) { + return false; + } + + if (notInFuture === true) { + var currentDate = new Date(), + currentYear = currentDate.getFullYear(), + currentMonth = currentDate.getMonth(), + currentDay = currentDate.getDate(); + return (year < currentYear + || (year == currentYear && month - 1 < currentMonth) + || (year == currentYear && month - 1 == currentMonth && day < currentDay)); + } + + return true; + }, + + /** + * Implement Luhn validation algorithm ((http://en.wikipedia.org/wiki/Luhn)) + * Credit to https://gist.github.com/ShirtlessKirk/2134376 + * + * @param {String} value + * @returns {Boolean} + */ + luhn: function(value) { + var length = value.length, + mul = 0, + prodArr = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]], + sum = 0; + + while (length--) { + sum += prodArr[mul][parseInt(value.charAt(length), 10)]; + mul ^= 1; + } + + return (sum % 10 === 0 && sum > 0); + }, + + /** + * Implement modulus 11, 10 (ISO 7064) algorithm + * + * @param {String} value + * @returns {Boolean} + */ + mod_11_10: function(value) { + var check = 5, + length = value.length; + for (var i = 0; i < length; i++) { + check = (((check || 10) * 2) % 11 + parseInt(value.charAt(i), 10)) % 10; + } + return (check == 1); + }, + + /** + * Implements Mod 37, 36 (ISO 7064) algorithm + * Usages: + * mod_37_36('A12425GABC1234002M') + * mod_37_36('002006673085', '0123456789') + * + * @param {String} value + * @param {String} alphabet + * @returns {Boolean} + */ + mod_37_36: function(value, alphabet) { + alphabet = alphabet || '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; + var modulus = alphabet.length, + length = value.length, + check = Math.floor(modulus / 2); + for (var i = 0; i < length; i++) { + check = (((check || modulus) * 2) % (modulus + 1) + alphabet.indexOf(value.charAt(i))) % modulus; + } + return (check == 1); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.base64 = { + /** + * Return true if the input value is a base 64 encoded string. + * + * @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; + } + + return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.between = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + if ('range' == $field.attr('type')) { + return { + min: $field.attr('min'), + max: $field.attr('max') + }; + } + + return false; + }, + + /** + * Return true if the input value is between (strictly or not) two given numbers + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - min + * - max + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = parseFloat(value); + return (options.inclusive === true) + ? (value > options.min && value < options.max) + : (value >= options.min && value <= options.max); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.callback = { + /** + * Return result from the callback method + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - callback: The callback method that passes 2 parameters: + * callback: function(fieldValue, validator) { + * // fieldValue is the value of field + * // validator is instance of BootstrapValidator + * } + * - message: The invalid message + * @returns {Boolean|Deferred} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (options.callback && 'function' == typeof options.callback) { + var dfd = new $.Deferred(); + dfd.resolve($field, 'callback', options.callback.call(this, value, validator)); + return dfd; + } + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.choice = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max' + }, + + /** + * Check if the number of checked boxes are less or more than a given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var numChoices = $field.is('select') + ? validator.getFieldElements($field.attr('data-bv-field')).find('option').filter(':selected').length + : validator.getFieldElements($field.attr('data-bv-field')).filter(':checked').length; + if ((options.min && numChoices < options.min) || (options.max && numChoices > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.creditCard = { + /** + * Return true if the input value is valid credit card number + * Based on https://gist.github.com/DiegoSalazar/4075533 + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Accept only digits, dashes or spaces + if (/[^0-9-\s]+/.test(value)) { + return false; + } + value = value.replace(/\D/g, ''); + + if (!$.fn.bootstrapValidator.helpers.luhn(value)) { + return false; + } + + // Validate the card number based on prefix (IIN ranges) and length + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['6304', '6706', '6771', '6709'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + + var type, i; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (value.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(value.length) != -1) // and length + { + return true; + } + } + } + + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.cusip = { + /** + * Validate a CUSIP + * Examples: + * - Valid: 037833100, 931142103, 14149YAR8, 126650BG6 + * - Invalid: 31430F200, 022615AC2 + * + * @see http://en.wikipedia.org/wiki/CUSIP + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = value.toUpperCase(); + if (!/^[0-9A-Z]{9}$/.test(value)) { + return false; + } + + var converted = $.map(value.split(''), function(item) { + var code = item.charCodeAt(0); + return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) + // Replace A, B, C, ..., Z with 10, 11, ..., 35 + ? (code - 'A'.charCodeAt(0) + 10) + : item; + }), + length = converted.length, + sum = 0; + for (var i = 0; i < length - 1; i++) { + var num = parseInt(converted[i]); + if (i % 2 != 0) { + num *= 2; + } + if (num > 9) { + num -= 9; + } + sum += num; + } + + sum = (10 - (sum % 10)) % 10; + return sum == converted[length - 1]; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.cvv = { + html5Attributes: { + message: 'message', + ccfield: 'creditCardField' + }, + + /** + * Return true if the input value is a valid CVV number. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - creditCardField: The credit card number field. It can be null + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^[0-9]{3,4}$/.test(value)) { + return false; + } + + if (!options.creditCardField) { + return true; + } + + // Get the credit card number + var creditCard = validator.getFieldElements(options.creditCardField).val(); + if (creditCard == '') { + return true; + } + + creditCard = creditCard.replace(/\D/g, ''); + + // Supported credit card types + var cards = { + AMERICAN_EXPRESS: { + length: [15], + prefix: ['34', '37'] + }, + DINERS_CLUB: { + length: [14], + prefix: ['300', '301', '302', '303', '304', '305', '36'] + }, + DINERS_CLUB_US: { + length: [16], + prefix: ['54', '55'] + }, + DISCOVER: { + length: [16], + prefix: ['6011', '622126', '622127', '622128', '622129', '62213', + '62214', '62215', '62216', '62217', '62218', '62219', + '6222', '6223', '6224', '6225', '6226', '6227', '6228', + '62290', '62291', '622920', '622921', '622922', '622923', + '622924', '622925', '644', '645', '646', '647', '648', + '649', '65'] + }, + JCB: { + length: [16], + prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] + }, + LASER: { + length: [16, 17, 18, 19], + prefix: ['6304', '6706', '6771', '6709'] + }, + MAESTRO: { + length: [12, 13, 14, 15, 16, 17, 18, 19], + prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] + }, + MASTERCARD: { + length: [16], + prefix: ['51', '52', '53', '54', '55'] + }, + SOLO: { + length: [16, 18, 19], + prefix: ['6334', '6767'] + }, + UNIONPAY: { + length: [16, 17, 18, 19], + prefix: ['622126', '622127', '622128', '622129', '62213', '62214', + '62215', '62216', '62217', '62218', '62219', '6222', '6223', + '6224', '6225', '6226', '6227', '6228', '62290', '62291', + '622920', '622921', '622922', '622923', '622924', '622925'] + }, + VISA: { + length: [16], + prefix: ['4'] + } + }; + var type, i, creditCardType = null; + for (type in cards) { + for (i in cards[type]['prefix']) { + if (creditCard.substr(0, cards[type]['prefix'][i].length) == cards[type]['prefix'][i] // Check the prefix + && cards[type]['length'].indexOf(creditCard.length) != -1) // and length + { + creditCardType = type; + break; + } + } + } + + return (creditCardType == null) + ? false + : (('AMERICAN_EXPRESS' == creditCardType) ? (value.length == 4) : (value.length == 3)); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.date = { + html5Attributes: { + message: 'message', + format: 'format' + }, + + /** + * Return true if the input value is valid date + * + * @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 + * - format: The date format. Default is MM/DD/YYYY + * The format can be: + * + * i) date: Consist of DD, MM, YYYY parts which are separated by / + * ii) date and time: + * The time can consist of h, m, s parts which are separated by : + * ii) date, time and A (indicating AM or PM) + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options.format = options.format || 'MM/DD/YYYY'; + + 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(' '), + date = sections[0], + time = (sections.length > 1) ? sections[1] : null; + + if (formats.length != sections.length) { + return false; + } + + // Determine the separator + var separator = (date.indexOf('/') != -1) ? '/' : ((date.indexOf('-') != -1) ? '-' : null); + if (separator == null) { + return false; + } + + // Determine the date + date = date.split(separator); + dateFormat = dateFormat.split(separator); + var year = date[dateFormat.indexOf('YYYY')], + month = date[dateFormat.indexOf('MM')], + day = date[dateFormat.indexOf('DD')]; + + // Determine the time + var minutes = null, hours = null, seconds = null; + if (timeFormat) { + timeFormat = timeFormat.split(':'), + time = time.split(':'); + + if (timeFormat.length != time.length) { + return false; + } + + hours = time.length > 0 ? time[0] : null; + minutes = time.length > 1 ? time[1] : null; + seconds = time.length > 2 ? time[2] : null; + + // Validate seconds + if (seconds) { + seconds = parseInt(seconds, 10); + if (seconds < 0 || seconds > 60) { + return false; + } + } + + // Validate hours + if (hours) { + hours = parseInt(hours, 10); + if (hours < 0 || hours >= 24 || (amOrPm && hours > 12)) { + return false; + } + } + + // Validate minutes + if (minutes) { + minutes = parseInt(minutes, 10); + if (minutes < 0 || minutes > 59) { + return false; + } + } + } + + // Validate day, month, and year + day = parseInt(day, 10); + month = parseInt(month, 10); + year = parseInt(year, 10); + + return $.fn.bootstrapValidator.helpers.date(year, month, day); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.different = { + html5Attributes: { + message: 'message', + field: 'field' + }, + + /** + * Return true if the input value is different with given field's value + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value != compareWith.val()) { + validator.updateStatus(options.field, validator.STATUS_VALID, 'different'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.digits = { + /** + * Return true if the input value contains digits only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^\d+$/.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.ean = { + /** + * Validate EAN (International Article Number) + * Examples: + * - Valid: 73513537, 9780471117094, 4006381333931 + * - Invalid: 73513536 + * + * @see http://en.wikipedia.org/wiki/European_Article_Number + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^(\d{8}|\d{12}|\d{13})$/.test(value)) { + return false; + } + + var length = value.length, + sum = 0, + weight = (length == 8) ? [3, 1] : [1, 3]; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * weight[i % 2]; + } + sum = 10 - sum % 10; + return (sum == value.charAt(length - 1)); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.emailAddress = { + enableByHtml5: function($field) { + return ('email' == $field.attr('type')); + }, + + /** + * Return true if and only if the input value is a valid email address + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Email address regular expression + // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript + var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/; + return emailRegExp.test(value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.file = { + html5Attributes: { + extension: 'extension', + maxsize: 'maxSize', + message: 'message', + type: 'type' + }, + + /** + * Validate upload file. Use HTML 5 API if the browser supports + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - extension: The allowed extensions, separated by a comma + * - maxSize: The maximum size in bytes + * - message: The invalid message + * - type: The allowed MIME type, separated by a comma + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var ext, + extensions = options.extension ? options.extension.split(',') : null, + types = options.type ? options.type.split(',') : null, + html5 = (window.File && window.FileList && window.FileReader); + + if (html5) { + // Get FileList instance + var files = $field.get(0).files, + total = files.length; + for (var i = 0; i < total; i++) { + // Check file size + if (options.maxSize && files[i].size > parseInt(options.maxSize)) { + return false; + } + + // Check file extension + ext = files[i].name.substr(files[i].name.lastIndexOf('.') + 1); + if (extensions && extensions.indexOf(ext) == -1) { + return false; + } + + // Check file type + if (types && types.indexOf(files[i].type) == -1) { + return false; + } + } + } else { + // Check file extension + ext = value.substr(value.lastIndexOf('.') + 1); + if (extensions && extensions.indexOf(ext) == -1) { + return false; + } + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.greaterThan = { + html5Attributes: { + message: 'message', + value: 'value', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + var min = $field.attr('min'); + if (min) { + return { + value: min + }; + } + + return false; + }, + + /** + * Return true if the input value is greater than or equals to given number + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === true) ? (value > options.value) : (value >= options.value); + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.grid = { + /** + * Validate GRId (Global Release Identifier) + * Examples: + * - Valid: A12425GABC1234002M, A1-2425G-ABC1234002-M, A1 2425G ABC1234002 M, Grid:A1-2425G-ABC1234002-M + * - Invalid: A1-2425G-ABC1234002-Q + * + * @see http://en.wikipedia.org/wiki/Global_Release_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; + } + + value = value.toUpperCase(); + if (!/^[GRID:]*([0-9A-Z]{2})[-\s]*([0-9A-Z]{5})[-\s]*([0-9A-Z]{10})[-\s]*([0-9A-Z]{1})$/g.test(value)) { + return false; + } + value = value.replace(/\s/g, '').replace(/-/g, ''); + if ('GRID:' == value.substr(0, 5)) { + value = value.substr(5); + } + return $.fn.bootstrapValidator.helpers.mod_37_36(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hex = { + /** + * Return true if and only if the input value is a valid hexadecimal number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + return /^[0-9a-fA-F]+$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.hexColor = { + enableByHtml5: function($field) { + return ('color' == $field.attr('type')); + }, + + /** + * Return true if the input value is a valid hex color + * + * @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; + } + return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.iban = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Validate an International Bank Account Number (IBAN) + * To test it, take the sample IBAN from + * http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html + * + * @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 + * - country: The ISO 3166-1 country code + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // See + // http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf + // http://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country + var ibanRegex = { + '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 + }; + value = value.replace(/[^a-zA-Z0-9]/g, '').toUpperCase(); + var country = options.country || value.substr(0, 2); + if (!ibanRegex[country]) { + return false; + } + if (!(new RegExp('^' + ibanRegex[country] + '$')).test(value)) { + return false; + } + + value = value.substr(4) + value.substr(0, 4); + value = $.map(value.split(''), function(n) { + var code = n.charCodeAt(0); + return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) + // Replace A, B, C, ..., Z with 10, 11, ..., 35 + ? (code - 'A'.charCodeAt(0) + 10) + : n; + }); + value = value.join(''); + + var temp = parseInt(value.substr(0, 1), 10), + length = value.length; + for (var i = 1; i < length; ++i) { + temp = (temp * 10 + parseInt(value.substr(i, 1), 10)) % 97; + } + return (temp == 1); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.id = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Validate identification number in different countries + * + * @see http://en.wikipedia.org/wiki/National_identification_number + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166-1 country code + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var country = options.country || value.substr(0, 2), + method = ['_', country.toLowerCase()].join(''); + if (this[method] && 'function' == typeof this[method]) { + return this[method](value); + } + + return true; + }, + + /** + * Validate Unique Master Citizen Number which uses in + * - Bosnia and Herzegovina (country code: BA) + * - Macedonia (MK) + * - Montenegro (ME) + * - Serbia (RS) + * - Slovenia (SI) + * + * @see http://en.wikipedia.org/wiki/Unique_Master_Citizen_Number + * @param {String} value The ID + * @param {String} countryCode The ISO country code, can be BA, MK, ME, RS, SI + * @returns {Boolean} + */ + _validateJMBG: function(value, countryCode) { + if (!/^\d{13}$/.test(value)) { + return false; + } + var day = parseInt(value.substr(0, 2), 10), + month = parseInt(value.substr(2, 2), 10), + year = parseInt(value.substr(4, 3), 10), + rr = parseInt(value.substr(7, 2), 10), + k = parseInt(value.substr(12, 1), 10); + + // Validate date of birth + // FIXME: Validate the year of birth + if (day > 31 || month > 12) { + return false; + } + + // Validate checksum + var sum = 0; + for (var i = 0; i < 6; i++) { + sum += (7 - i) * (parseInt(value.charAt(i)) + parseInt(value.charAt(i + 6))); + } + sum = 11 - sum % 11; + if (sum == 10 || sum == 11) { + sum = 0; + } + if (sum != k) { + return false; + } + + // Validate political region + // rr is the political region of birth, which can be in ranges: + // 10-19: Bosnia and Herzegovina + // 20-29: Montenegro + // 30-39: Croatia (not used anymore) + // 41-49: Macedonia + // 50-59: Slovenia (only 50 is used) + // 70-79: Central Serbia + // 80-89: Serbian province of Vojvodina + // 90-99: Kosovo + switch (countryCode.toUpperCase()) { + case 'BA': + return (10 <= rr && rr <= 19); + case 'MK': + return (41 <= rr && rr <= 49); + case 'ME': + return (20 <= rr && rr <= 29); + case 'RS': + return (70 <= rr && rr <= 99); + case 'SI': + return (50 <= rr && rr <= 59); + default: + return true; + } + }, + + _ba: function(value) { + return this._validateJMBG(value, 'BA'); + }, + _mk: function(value) { + return this._validateJMBG(value, 'MK'); + }, + _me: function(value) { + return this._validateJMBG(value, 'ME'); + }, + _rs: function(value) { + return this._validateJMBG(value, 'RS'); + }, + + /** + * Examples: 0101006500006 + */ + _si: function(value) { + return this._validateJMBG(value, 'SI'); + }, + + /** + * Validate Bulgarian national identification number (EGN) + * Examples: + * - Valid: 7523169263, 8032056031, 803205 603 1, 8001010008, 7501020018, 7552010005, 7542011030 + * - Invalid: 8019010008 + * + * @see http://en.wikipedia.org/wiki/Uniform_civil_number + * @param {String} value The ID + * @returns {Boolean} + */ + _bg: function(value) { + if (!/^\d{10}$/.test(value) && !/^\d{6}\s\d{3}\s\d{1}$/.test(value)) { + return false; + } + value = value.replace(/\s/g, ''); + // Check the birth date + var year = parseInt(value.substr(0, 2), 10) + 1900, + month = parseInt(value.substr(2, 2), 10), + day = parseInt(value.substr(4, 2), 10); + if (month > 40) { + year += 100; + month -= 40; + } else if (month > 20) { + year -= 100; + month -= 20; + } + + if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { + return false; + } + + var sum = 0, + weight = [2, 4, 8, 5, 10, 9, 7, 3, 6]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = (sum % 11) % 10; + return (sum == value.substr(9, 1)); + }, + + /** + * Validate Brazilian national identification number (CPF) + * Examples: + * - Valid: 39053344705, 390.533.447-05, 111.444.777-35 + * - Invalid: 231.002.999-00 + * + * @see http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas + * @param {String} value The ID + * @returns {Boolean} + */ + _br: function(value) { + if (/^1{11}|2{11}|3{11}|4{11}|5{11}|6{11}|7{11}|8{11}|9{11}|0{11}$/.test(value)) { + return false; + } + if (!/^\d{11}$/.test(value) && !/^\d{3}\.\d{3}\.\d{3}-\d{2}$/.test(value)) { + return false; + } + value = value.replace(/\./g, '').replace(/-/g, ''); + + var d1 = 0; + for (var i = 0; i < 9; i++) { + d1 += (10 - i) * parseInt(value.charAt(i)); + } + d1 = 11 - d1 % 11; + if (d1 == 10 || d1 == 11) { + d1 = 0; + } + if (d1 != value.charAt(9)) { + return false; + } + + var d2 = 0; + for (i = 0; i < 10; i++) { + d2 += (11 - i) * parseInt(value.charAt(i)); + } + d2 = 11 - d2 % 11; + if (d2 == 10 || d2 == 11) { + d2 = 0; + } + + return (d2 == value.charAt(10)); + }, + + /** + * Validate Swiss Social Security Number (AHV-Nr/No AVS) + * Examples: + * - Valid: 756.1234.5678.95, 7561234567895 + * + * @see http://en.wikipedia.org/wiki/National_identification_number#Switzerland + * @see http://www.bsv.admin.ch/themen/ahv/00011/02185/index.html?lang=de + * @param {String} value The ID + * @returns {Boolean} + */ + _ch: function(value) { + if (!/^756[\.]{0,1}[0-9]{4}[\.]{0,1}[0-9]{4}[\.]{0,1}[0-9]{2}$/.test(value)) { + return false; + } + value = value.replace(/\D/g, '').substr(3); + var length = value.length, + sum = 0, + weight = (length == 8) ? [3, 1] : [1, 3]; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * weight[i % 2]; + } + sum = 10 - sum % 10; + return (sum == value.charAt(length - 1)); + }, + + /** + * Validate Chilean national identification number (RUN/RUT) + * Examples: + * - Valid: 76086428-5, 22060449-7, 12531909-2 + * + * @see http://en.wikipedia.org/wiki/National_identification_number#Chile + * @see https://palena.sii.cl/cvc/dte/ee_empresas_emisoras.html for samples + * @param {String} value The ID + * @returns {Boolean} + */ + _cl: function(value) { + if (!/^\d{7,8}[-]{0,1}[0-9K]$/.test(value)) { + return false; + } + value = value.replace(/\D/g, ''); + while (value.length < 9) { + value = '0' + value; + } + var sum = 0, + weight = [3, 2, 7, 6, 5, 4, 3, 2]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = 11 - sum % 11; + if (sum == 11) { + sum = 0; + } else if (sum == 10) { + sum = 'K'; + } + return sum == value.charAt(8); + }, + + /** + * Validate Czech national identification number (RC) + * Examples: + * - Valid: 7103192745, 991231123 + * - Invalid: 1103492745, 590312123 + * + * @param {String} value The ID + * @returns {Boolean} + */ + _cz: function(value) { + if (!/^\d{9,10}$/.test(value)) { + return false; + } + var year = 1900 + parseInt(value.substr(0, 2)), + month = parseInt(value.substr(2, 2)) % 50 % 20, + day = parseInt(value.substr(4, 2)); + if (value.length == 9) { + if (year >= 1980) { + year -= 100; + } + if (year > 1953) { + return false; + } + } else if (year < 1954) { + year += 100; + } + + if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { + return false; + } + + // Check that the birth date is not in the future + if (value.length == 10) { + var check = parseInt(value.substr(0, 9), 10) % 11; + if (year < 1985) { + check = check % 10; + } + return (check == value.substr(9, 1)); + } + + return true; + }, + + /** + * Validate Danish Personal Identification number (CPR) + * Examples: + * - Valid: 2110625629, 211062-5629 + * - Invalid: 511062-5629 + * + * @see https://en.wikipedia.org/wiki/Personal_identification_number_(Denmark) + * @param {String} value The ID + * @returns {Boolean} + */ + _dk: function(value) { + if (!/^[0-9]{6}[-]{0,1}[0-9]{4}$/.test(value)) { + return false; + } + value = value.replace(/-/g, ''); + var day = parseInt(value.substr(0, 2), 10), + month = parseInt(value.substr(2, 2), 10), + year = parseInt(value.substr(4, 2), 10); + + switch (true) { + case ('5678'.indexOf(value.charAt(6)) != -1 && year >= 58): + year += 1800; + break; + case ('0123'.indexOf(value.charAt(6)) != -1): + case ('49'.indexOf(value.charAt(6)) != -1 && year >= 37): + year += 1900; + break; + default: + year += 2000; + break; + } + + return $.fn.bootstrapValidator.helpers.date(year, month, day); + }, + + /** + * Validate Estonian Personal Identification Code (isikukood) + * Examples: + * - Valid: 37605030299 + * + * @see http://et.wikipedia.org/wiki/Isikukood + * @param {String} value The ID + * @returns {Boolean} + */ + _ee: function(value) { + // Use the same format as Lithuanian Personal Code + return this._lt(value); + }, + + /** + * Validate Spanish personal identity code (DNI) + * Support i) DNI (for Spanish citizens) and ii) NIE (for foreign people) + * + * Examples: + * - Valid: i) 54362315K, 54362315-K; ii) X2482300W, X-2482300W, X-2482300-W + * - Invalid: i) 54362315Z; ii) X-2482300A + * + * @see https://en.wikipedia.org/wiki/National_identification_number#Spain + * @param {String} value The ID + * @returns {Boolean} + */ + _es: function(value) { + if (!/^[0-9A-Z]{8}[-]{0,1}[0-9A-Z]$/.test(value) // DNI + && !/^[XYZ][-]{0,1}[0-9]{7}[-]{0,1}[0-9A-Z]$/.test(value)) { // NIE + return false; + } + + value = value.replace(/-/g, ''); + var index = 'XYZ'.indexOf(value.charAt(0)); + if (index != -1) { + // It is NIE number + value = index + value.substr(1) + ''; + } + + var check = parseInt(value.substr(0, 8), 10); + check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; + return (check == value.substr(8, 1)); + }, + + /** + * Validate Finnish Personal Identity Code (HETU) + * Examples: + * - Valid: 311280-888Y, 131052-308T + * - Invalid: 131052-308U, 310252-308Y + * + * @param {String} value The ID + * @returns {Boolean} + */ + _fi: function(value) { + if (!/^[0-9]{6}[-+A][0-9]{3}[0-9ABCDEFHJKLMNPRSTUVWXY]$/.test(value)) { + return false; + } + var day = parseInt(value.substr(0, 2), 10), + month = parseInt(value.substr(2, 2), 10), + year = parseInt(value.substr(4, 2), 10), + centuries = { + '+': 1800, + '-': 1900, + 'A': 2000 + }; + year = centuries[value.charAt(6)] + year; + + if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { + return false; + } + + var individual = parseInt(value.substr(7, 3)); + if (individual < 2) { + return false; + } + var n = value.substr(0, 6) + value.substr(7, 3) + ''; + n = parseInt(n); + return '0123456789ABCDEFHJKLMNPRSTUVWXY'.charAt(n % 31) == value.charAt(10); + }, + + /** + * Validate Croatian personal identification number (OIB) + * Examples: + * - Valid: 33392005961 + * - Invalid: 33392005962 + * + * @param {String} value The ID + * @returns {Boolean} + */ + _hr: function(value) { + if (!/^[0-9]{11}$/.test(value)) { + return false; + } + return $.fn.bootstrapValidator.helpers.mod_11_10(value); + }, + + /** + * Validate Irish Personal Public Service Number (PPS) + * Examples: + * - Valid: 6433435F, 6433435FT, 6433435FW, 6433435OA, 6433435IH, 1234567TW, 1234567FA + * - Invalid: 6433435E, 6433435VH + * + * @see https://en.wikipedia.org/wiki/Personal_Public_Service_Number + * @param {String} value The ID + * @returns {Boolean} + */ + _ie: function(value) { + if (!/^\d{7}[A-W][AHWTX]?$/.test(value)) { + return false; + } + + var getCheckDigit = function(value) { + while (value.length < 7) { + value = '0' + value; + } + var alphabet = 'WABCDEFGHIJKLMNOPQRSTUV', + sum = 0; + for (var i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i)) * (8 - i); + } + sum += 9 * alphabet.indexOf(value.substr(7)); + return alphabet[sum % 23]; + }; + + // 2013 format + if (value.length == 9 && ('A' == value.charAt(8) || 'H' == value.charAt(8))) { + return value.charAt(7) == getCheckDigit(value.substr(0, 7) + value.substr(8) + ''); + } + // The old format + else { + return value.charAt(7) == getCheckDigit(value.substr(0, 7)); + } + }, + + /** + * Validate Iceland national identification number (Kennitala) + * Examples: + * - Valid: 120174-3399, 1201743399, 0902862349 + * + * @see http://en.wikipedia.org/wiki/Kennitala + * @param {String} value The ID + * @returns {Boolean} + */ + _is: function(value) { + if (!/^[0-9]{6}[-]{0,1}[0-9]{4}$/.test(value)) { + return false; + } + value = value.replace(/-/g, ''); + var day = parseInt(value.substr(0, 2), 10), + month = parseInt(value.substr(2, 2), 10), + year = parseInt(value.substr(4, 2), 10), + century = parseInt(value.charAt(9)); + + year = (century == 9) ? (1900 + year) : ((20 + century) * 100 + year); + if (!$.fn.bootstrapValidator.helpers.date(year, month, day, true)) { + return false; + } + // Validate the check digit + var sum = 0, + weight = [3, 2, 7, 6, 5, 4, 3, 2]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = 11 - sum % 11; + return (sum == value.charAt(8)); + }, + + /** + * Validate Lithuanian Personal Code (Asmens kodas) + * Examples: + * - Valid: 38703181745 + * - Invalid: 38703181746, 78703181745, 38703421745 + * + * @see http://en.wikipedia.org/wiki/National_identification_number#Lithuania + * @see http://www.adomas.org/midi2007/pcode.html + * @param {String} value The ID + * @returns {Boolean} + */ + _lt: function(value) { + if (!/^[0-9]{11}$/.test(value)) { + return false; + } + var gender = parseInt(value.charAt(0)), + year = parseInt(value.substr(1, 2), 10), + month = parseInt(value.substr(3, 2), 10), + day = parseInt(value.substr(5, 2), 10), + century = (gender % 2 == 0) ? (17 + gender / 2) : (17 + (gender + 1) / 2); + year = century * 100 + year; + if (!$.fn.bootstrapValidator.helpers.date(year, month, day, true)) { + return false; + } + + // Validate the check digit + var sum = 0, + weight = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1]; + for (var i = 0; i < 10; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 11; + if (sum != 10) { + return sum == value.charAt(10); + } + + // Re-calculate the check digit + sum = 0; + weight = [3, 4, 5, 6, 7, 8, 9, 1, 2, 3]; + for (i = 0; i < 10; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 11; + if (sum == 10) { + sum = 0; + } + return (sum == value.charAt(10)); + }, + + /** + * Validate Latvian Personal Code (Personas kods) + * Examples: + * - Valid: 161175-19997, 16117519997 + * - Invalid: 161375-19997 + * + * @see http://laacz.lv/2006/11/25/pk-parbaudes-algoritms/ + * @param {String} value The ID + * @returns {Boolean} + */ + _lv: function(value) { + if (!/^[0-9]{6}[-]{0,1}[0-9]{5}$/.test(value)) { + return false; + } + value = value.replace(/\D/g, ''); + // Check birth date + var day = parseInt(value.substr(0, 2)), + month = parseInt(value.substr(2, 2)), + year = parseInt(value.substr(4, 2)); + year = year + 1800 + parseInt(value.charAt(6)) * 100; + + if (!$.fn.bootstrapValidator.helpers.date(year, month, day, true)) { + return false; + } + + // Check personal code + var sum = 0, + weight = [10, 5, 8, 4, 2, 1, 6, 3, 7, 9]; + for (var i = 0; i < 10; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = (sum + 1) % 11 % 10; + return (sum == value.charAt(10)); + }, + + /** + * Validate Dutch national identification number (BSN) + * Examples: + * - Valid: 111222333, 941331490, 9413.31.490 + * - Invalid: 111252333 + * + * @see https://nl.wikipedia.org/wiki/Burgerservicenummer + * @param {String} value The ID + * @returns {Boolean} + */ + _nl: function(value) { + while (value.length < 9) { + value = '0' + value; + } + if (!/^[0-9]{4}[.]{0,1}[0-9]{2}[.]{0,1}[0-9]{3}$/.test(value)) { + return false; + } + value = value.replace(/\./g, ''); + if (parseInt(value, 10) == 0) { + return false; + } + var sum = 0, + length = value.length; + for (var i = 0; i < length - 1; i++) { + sum += (9 - i) * parseInt(value.charAt(i)); + } + sum = sum % 11; + if (sum == 10) { + sum = 0; + } + return (sum == value.charAt(length - 1)); + }, + + /** + * Validate Romanian numerical personal code (CNP) + * Examples: + * - Valid: 1630615123457, 1800101221144 + * - Invalid: 8800101221144, 1632215123457, 1630615123458 + * + * @see http://en.wikipedia.org/wiki/National_identification_number#Romania + * @param {String} value The ID + * @returns {Boolean} + */ + _ro: function(value) { + if (!/^[0-9]{13}$/.test(value)) { + return false; + } + var gender = parseInt(value.charAt(0)); + if (gender == 0 || gender == 7 || gender == 8) { + return false; + } + + // Determine the date of birth + var year = parseInt(value.substr(1, 2), 10), + month = parseInt(value.substr(3, 2), 10), + day = parseInt(value.substr(5, 2), 10), + // The year of date is determined base on the gender + centuries = { + '1': 1900, // Male born between 1900 and 1999 + '2': 1900, // Female born between 1900 and 1999 + '3': 1800, // Male born between 1800 and 1899 + '4': 1800, // Female born between 1800 and 1899 + '5': 2000, // Male born after 2000 + '6': 2000 // Female born after 2000 + }; + if (day > 31 && month > 12) { + return false; + } + if (gender != 9) { + year = centuries[gender + ''] + year; + if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { + return false; + } + } + + // Validate the check digit + var sum = 0, + weight = [2, 7, 9, 1, 4, 6, 3, 5, 8, 2, 7, 9], + length = value.length; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 11; + if (sum == 10) { + sum = 1; + } + return (sum == value.charAt(length - 1)); + }, + + /** + * Validate Swedish personal identity number (personnummer) + * Examples: + * - Valid: 8112289874, 811228-9874, 811228+9874 + * - Invalid: 811228-9873 + * + * @see http://en.wikipedia.org/wiki/Personal_identity_number_(Sweden) + * @param {String} value The ID + * @returns {Boolean} + */ + _se: function(value) { + if (!/^[0-9]{10}$/.test(value) && !/^[0-9]{6}[-|+][0-9]{4}$/.test(value)) { + return false; + } + value = value.replace(/[^0-9]/g, ''); + + var year = parseInt(value.substr(0, 2)) + 1900, + month = parseInt(value.substr(2, 2)), + day = parseInt(value.substr(4, 2)); + if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { + return false; + } + + // Validate the last check digit + return $.fn.bootstrapValidator.helpers.luhn(value); + }, + + /** + * Validate Slovak national identifier number (RC) + * Examples: + * - Valid: 7103192745, 991231123 + * - Invalid: 7103192746, 1103492745 + * + * @param {String} value The ID + * @returns {Boolean} + */ + _sk: function(value) { + // Slovakia uses the same format as Czech Republic + return this._cz(value); + }, + + /** + * Validate San Marino citizen number + * + * @see http://en.wikipedia.org/wiki/National_identification_number#San_Marino + * @param {String} value The ID + * @returns {Boolean} + */ + _sm: function(value) { + return /^\d{5}$/.test(value); + }, + + /** + * Validate South African ID + * Example: + * - Valid: 8001015009087 + * - Invalid: 8001015009287, 8001015009086 + * + * @see http://en.wikipedia.org/wiki/National_identification_number#South_Africa + * @param {String} value The ID + * @returns {Boolean} + */ + _za: function(value) { + if (!/^[0-9]{10}[0|1][8|9][0-9]$/.test(value)) { + return false; + } + var year = parseInt(value.substr(0, 2)), + currentYear = new Date().getFullYear() % 100, + month = parseInt(value.substr(2, 2)), + day = parseInt(value.substr(4, 2)); + year = (year >= currentYear) ? (year + 1900) : (year + 2000); + + if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { + return false; + } + + // Validate the last check digit + return $.fn.bootstrapValidator.helpers.luhn(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.identical = { + html5Attributes: { + message: 'message', + field: 'field' + }, + + /** + * Check if input value equals to value of particular one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - field: The name of field that will be used to compare with current one + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var compareWith = validator.getFieldElements(options.field); + if (compareWith == null) { + return true; + } + + if (value == compareWith.val()) { + validator.updateStatus(options.field, validator.STATUS_VALID, 'identical'); + return true; + } else { + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.imei = { + /** + * Validate IMEI (International Mobile Station Equipment Identity) + * Examples: + * - Valid: 35-209900-176148-1, 35-209900-176148-23, 3568680000414120, 490154203237518 + * - Invalid: 490154203237517 + * + * @see http://en.wikipedia.org/wiki/International_Mobile_Station_Equipment_Identity + * @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) { + case /^\d{15}$/.test(value): + case /^\d{2}-\d{6}-\d{6}-\d{1}$/.test(value): + case /^\d{2}\s\d{6}\s\d{6}\s\d{1}$/.test(value): + value = value.replace(/[^0-9]/g, ''); + return $.fn.bootstrapValidator.helpers.luhn(value); + break; + + case /^\d{14}$/.test(value): + case /^\d{16}$/.test(value): + case /^\d{2}-\d{6}-\d{6}(|-\d{2})$/.test(value): + case /^\d{2}\s\d{6}\s\d{6}(|\s\d{2})$/.test(value): + return true; + + default: + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.integer = { + enableByHtml5: function($field) { + return ('number' == $field.attr('type')); + }, + + /** + * Return true if the input value is an integer + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + return /^(?:-?(?:0|[1-9][0-9]*))$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.ip = { + html5Attributes: { + message: 'message', + ipv4: 'ipv4', + ipv6: 'ipv6' + }, + + /** + * Return true if the input value is a IP address. + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - ipv4: Enable IPv4 validator, default to true + * - ipv6: Enable IPv6 validator, default to true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + options = $.extend({}, { ipv4: true, ipv6: true }, options); + + if (options.ipv4) { + return /^(?:(?: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); + } else if (options.ipv6) { + return /^\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(str); + } + return false; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.isbn = { + /** + * Return true if the input value is a valid ISBN 10 or ISBN 13 number + * Examples: + * - Valid: + * ISBN 10: 99921-58-10-7, 9971-5-0210-0, 960-425-059-0, 80-902734-1-6, 85-359-0277-5, 1-84356-028-3, 0-684-84328-5, 0-8044-2957-X, 0-85131-041-9, 0-943396-04-2, 0-9752298-0-X + * ISBN 13: 978-0-306-40615-7 + * - Invalid: + * ISBN 10: 99921-58-10-6 + * ISBN 13: 978-0-306-40615-6 + * + * @see http://en.wikipedia.org/wiki/International_Standard_Book_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; + } + + // http://en.wikipedia.org/wiki/International_Standard_Book_Number#Overview + // Groups are separated by a hyphen or a space + var type; + switch (true) { + case /^\d{9}[\dX]$/.test(value): + case (value.length == 13 && /^(\d+)-(\d+)-(\d+)-([\dX])$/.test(value)): + case (value.length == 13 && /^(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(value)): + type = 'ISBN10'; + break; + case /^(978|979)\d{9}[\dX]$/.test(value): + case (value.length == 17 && /^(978|979)-(\d+)-(\d+)-(\d+)-([\dX])$/.test(value)): + case (value.length == 17 && /^(978|979)\s(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(value)): + type = 'ISBN13'; + break; + default: + return false; + } + + // Replace all special characters except digits and X + value = value.replace(/[^0-9X]/gi, ''); + var chars = value.split(''), + length = chars.length, + sum = 0, + checksum; + + switch (type) { + case 'ISBN10': + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += ((10 - i) * parseInt(chars[i])); + } + checksum = 11 - (sum % 11); + if (checksum == 11) { + checksum = 0; + } else if (checksum == 10) { + checksum = 'X'; + } + return (checksum + '' == chars[length - 1]); + + case 'ISBN13': + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += ((i % 2 == 0) ? parseInt(chars[i]) : (parseInt(chars[i]) * 3)); + } + checksum = 10 - (sum % 10); + if (checksum == 10) { + checksum = '0'; + } + return (checksum + '' == chars[length - 1]); + + default: + return false; + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.isin = { + // Available country codes + // See http://isin.net/country-codes/ + COUNTRY_CODES: 'AF|AX|AL|DZ|AS|AD|AO|AI|AQ|AG|AR|AM|AW|AU|AT|AZ|BS|BH|BD|BB|BY|BE|BZ|BJ|BM|BT|BO|BQ|BA|BW|BV|BR|IO|BN|BG|BF|BI|KH|CM|CA|CV|KY|CF|TD|CL|CN|CX|CC|CO|KM|CG|CD|CK|CR|CI|HR|CU|CW|CY|CZ|DK|DJ|DM|DO|EC|EG|SV|GQ|ER|EE|ET|FK|FO|FJ|FI|FR|GF|PF|TF|GA|GM|GE|DE|GH|GI|GR|GL|GD|GP|GU|GT|GG|GN|GW|GY|HT|HM|VA|HN|HK|HU|IS|IN|ID|IR|IQ|IE|IM|IL|IT|JM|JP|JE|JO|KZ|KE|KI|KP|KR|KW|KG|LA|LV|LB|LS|LR|LY|LI|LT|LU|MO|MK|MG|MW|MY|MV|ML|MT|MH|MQ|MR|MU|YT|MX|FM|MD|MC|MN|ME|MS|MA|MZ|MM|NA|NR|NP|NL|NC|NZ|NI|NE|NG|NU|NF|MP|NO|OM|PK|PW|PS|PA|PG|PY|PE|PH|PN|PL|PT|PR|QA|RE|RO|RU|RW|BL|SH|KN|LC|MF|PM|VC|WS|SM|ST|SA|SN|RS|SC|SL|SG|SX|SK|SI|SB|SO|ZA|GS|SS|ES|LK|SD|SR|SJ|SZ|SE|CH|SY|TW|TJ|TZ|TH|TL|TG|TK|TO|TT|TN|TR|TM|TC|TV|UG|UA|AE|GB|US|UM|UY|UZ|VU|VE|VN|VG|VI|WF|EH|YE|ZM|ZW', + + /** + * Validate an ISIN (International Securities Identification Number) + * Examples: + * - Valid: US0378331005, AU0000XVGZA3, GB0002634946 + * - Invalid: US0378331004, AA0000XVGZA3 + * + * @see http://en.wikipedia.org/wiki/International_Securities_Identifying_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; + } + + value = value.toUpperCase(); + var regex = new RegExp('^(' + this.COUNTRY_CODES + ')[0-9A-Z]{10}$'); + if (!regex.test(value)) { + return false; + } + + var converted = '', + length = value.length; + // Convert letters to number + for (var i = 0; i < length - 1; i++) { + var c = value.charCodeAt(i); + converted += ((c > 57) ? (c - 55).toString() : value.charAt(i)); + } + + var digits = '', + n = converted.length, + group = (n % 2 != 0) ? 0 : 1; + for (i = 0; i < n; i++) { + digits += (parseInt(converted[i]) * ((i % 2) == group ? 2 : 1) + ''); + } + + var sum = 0; + for (i = 0; i < digits.length; i++) { + sum += parseInt(digits.charAt(i)); + } + sum = (10 - (sum % 10)) % 10; + return sum == value.charAt(length - 1); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.ismn = { + /** + * Validate ISMN (International Standard Music Number) + * Examples: + * - Valid: M230671187, 979-0-0601-1561-5, 979 0 3452 4680 5, 9790060115615 + * - Invalid: 9790060115614 + * + * @see http://en.wikipedia.org/wiki/International_Standard_Music_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; + } + + // Groups are separated by a hyphen or a space + var type; + switch (true) { + case /^M\d{9}$/.test(value): + case /^M-\d{4}-\d{4}-\d{1}$/.test(value): + case /^M\s\d{4}\s\d{4}\s\d{1}$/.test(value): + type = 'ISMN10'; + break; + case /^9790\d{9}$/.test(value): + case /^979-0-\d{4}-\d{4}-\d{1}$/.test(value): + case /^979\s0\s\d{4}\s\d{4}\s\d{1}$/.test(value): + type = 'ISMN13'; + break; + default: + return false; + } + + if ('ISMN10' == type) { + value = '9790' + value.substr(1); + } + + // Replace all special characters except digits + value = value.replace(/[^0-9]/gi, ''); + var length = value.length, + sum = 0, + weight = [1, 3]; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * weight[i % 2]; + } + sum = 10 - sum % 10; + return (sum == value.charAt(length - 1)); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.issn = { + /** + * Validate ISSN (International Standard Serial Number) + * Examples: + * - Valid: 0378-5955, 0024-9319, 0032-1478 + * - Invalid: 0032-147X + * + * @see http://en.wikipedia.org/wiki/International_Standard_Serial_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; + } + + // Groups are separated by a hyphen or a space + if (!/^\d{4}\-\d{3}[\dX]$/.test(value)) { + return false; + } + + // Replace all special characters except digits and X + value = value.replace(/[^0-9X]/gi, ''); + var chars = value.split(''), + length = chars.length, + sum = 0; + + if (chars[7] == 'X') { + chars[7] = 10; + } + for (var i = 0; i < length; i++) { + sum += ((8 - i) * parseInt(chars[i])); + } + return (sum % 11 == 0); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.lessThan = { + html5Attributes: { + message: 'message', + value: 'value', + inclusive: 'inclusive' + }, + + enableByHtml5: function($field) { + var max = $field.attr('max'); + if (max) { + return { + value: max + }; + } + + return false; + }, + + /** + * Return true if the input value is less than or equal to given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - value: The number used to compare to + * - inclusive [optional]: Can be true or false. Default is true + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + value = parseFloat(value); + return (options.inclusive === false) ? (value <= options.value) : (value < options.value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.mac = { + /** + * Return true if the input value is a MAC address. + * + * @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; + } + + return /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.notEmpty = { + enableByHtml5: function($field) { + var required = $field.attr('required') + ''; + return ('required' == required || 'true' == required); + }, + + /** + * Check if input value is empty or not + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var type = $field.attr('type'); + if ('radio' == type || 'checkbox' == type) { + return validator + .getFieldElements($field.attr('data-bv-field')) + .filter(':checked') + .length > 0; + } + + return $.trim($field.val()) != ''; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.numeric = { + html5Attributes: { + message: 'message', + separator: 'separator' + }, + + /** + * Validate decimal number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - separator: The decimal separator. Can be "." (default), "," + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + var separator = options.separator || '.'; + if (separator != '.') { + value = value.replace(separator, '.'); + } + + return !isNaN(parseFloat(value)) && isFinite(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.phone = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Return true if the input value contains a valid US phone number only + * + * @param {BootstrapValidator} validator Validate plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166 country code + * Currently it only supports United State (US) country + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var country = (options.country || 'US').toUpperCase(); + switch (country) { + case 'US': + default: + // Make sure US phone numbers have 10 digits + // May start with 1, +1, or 1-; should discard + // Area code may be delimited with (), & sections may be delimited with . or - + // Test: http://regexr.com/38mqi + value = value.replace(/\D/g, ''); + return (/^(?:(1\-?)|(\+1 ?))?\(?(\d{3})[\)\-\.]?(\d{3})[\-\.]?(\d{4})$/).test(value) && (value.length == 10); + } + } + } +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.regexp = { + html5Attributes: { + message: 'message', + regexp: 'regexp' + }, + + enableByHtml5: function($field) { + var pattern = $field.attr('pattern'); + if (pattern) { + return { + regexp: pattern + }; + } + + return false; + }, + + /** + * Check if the element value matches given regular expression + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of the following key: + * - regexp: The regular expression you need to check + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var regexp = ('string' == typeof options.regexp) ? new RegExp(options.regexp) : options.regexp; + return regexp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.remote = { + html5Attributes: { + message: 'message', + url: 'url', + name: 'name' + }, + + /** + * Request a remote server to check the input value + * + * @param {BootstrapValidator} validator Plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - url + * - data [optional]: By default, it will take the value + * { + * : + * } + * - name [optional]: Override the field name for the request. + * - message: The invalid message + * @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; + if (data == null) { + data = {}; + } + // Support dynamic data + if ('function' == typeof data) { + data = data.call(this, validator); + } + data[options.name || name] = value; + + var dfd = new $.Deferred(); + var xhr = $.ajax({ + type: 'POST', + url: options.url, + dataType: 'json', + data: data + }); + xhr.then(function(response) { + dfd.resolve($field, 'remote', response.valid === true || response.valid === 'true'); + }); + + dfd.fail(function() { + xhr.abort(); + }); + + return dfd; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.rtn = { + /** + * Validate a RTN (Routing transit number) + * Examples: + * - Valid: 021200025, 789456124 + * + * @see http://en.wikipedia.org/wiki/Routing_transit_number + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^\d{9}$/.test(value)) { + return false; + } + + var sum = 0; + for (var i = 0; i < value.length; i += 3) { + sum += parseInt(value.charAt(i), 10) * 3 + + parseInt(value.charAt(i + 1), 10) * 7 + + parseInt(value.charAt(i + 2), 10); + } + return (sum != 0 && sum % 10 == 0); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.sedol = { + /** + * Validate a SEDOL (Stock Exchange Daily Official List) + * Examples: + * - Valid: 0263494, B0WNLY7 + * + * @see http://en.wikipedia.org/wiki/SEDOL + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + value = value.toUpperCase(); + if (!/^[0-9A-Z]{7}$/.test(value)) { + return false; + } + + var sum = 0, + weight = [1, 3, 1, 7, 3, 9, 1], + length = value.length; + for (var i = 0; i < length - 1; i++) { + sum += weight[i] * parseInt(value.charAt(i), 36); + } + sum = (10 - sum % 10) % 10; + return sum == value.charAt(length - 1); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.siren = { + /** + * Check if a string is a siren number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + if (!/^\d{9}$/.test(value)) { + return false; + } + return $.fn.bootstrapValidator.helpers.luhn(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.siret = { + /** + * Check if a string is a siret number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var sum = 0, + length = value.length, + tmp; + for (var i = 0; i < length; i++) { + tmp = parseInt(value.charAt(i), 10); + if ((i % 2) == 0) { + tmp = tmp * 2; + if (tmp > 9) { + tmp -= 9; + } + } + sum += tmp; + } + return (sum % 10 == 0); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.step = { + html5Attributes: { + message: 'message', + base: 'baseValue', + step: 'step' + }, + + /** + * Return true if the input value is valid step one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Can consist of the following keys: + * - baseValue: The base value + * - step: The step + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + options = $.extend({}, { baseValue: 0, step: 1 }, options); + value = parseFloat(value); + if (isNaN(value) || !isFinite(value)) { + return false; + } + + var round = function(x, precision) { + var m = Math.pow(10, precision); + x = x * m; + var sign = (x > 0) | -(x < 0), + isHalf = (x % 1 === 0.5 * sign); + if (isHalf) { + return (Math.floor(x) + (sign > 0)) / m; + } else { + return Math.round(x) / m; + } + }, + floatMod = function(x, y) { + if (y == 0.0) { + return 1.0; + } + var dotX = (x + '').split('.'), + dotY = (y + '').split('.'), + precision = ((dotX.length == 1) ? 0 : dotX[1].length) + ((dotY.length == 1) ? 0 : dotY[1].length); + return round(x - y * Math.floor(x / y), precision); + }; + + var mod = floatMod(value - options.baseValue, options.step); + return (mod == 0.0 || mod == options.step); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringCase = { + html5Attributes: { + message: 'message', + 'case': 'case' + }, + + /** + * Check if a string is a lower or upper case one + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - case: Can be 'lower' (default) or 'upper' + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var stringCase = (options['case'] || 'lower').toLowerCase(); + switch (stringCase) { + case 'upper': + return value === value.toUpperCase(); + case 'lower': + default: + return value === value.toLowerCase(); + } + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.stringLength = { + html5Attributes: { + message: 'message', + min: 'min', + max: 'max' + }, + + enableByHtml5: function($field) { + var maxLength = $field.attr('maxlength'); + if (maxLength) { + return { + max: parseInt(maxLength, 10) + }; + } + + return false; + }, + + /** + * Check if the length of element value is less or more than given number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consists of following keys: + * - min + * - max + * At least one of two keys is required + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var length = $.trim(value).length; + if ((options.min && length < options.min) || (options.max && length > options.max)) { + return false; + } + + return true; + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uri = { + enableByHtml5: function($field) { + return ('url' == $field.attr('type')); + }, + + /** + * Return true if the input value is a valid URL + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Credit to https://gist.github.com/dperini/729294 + // + // Regular Expression for URL validation + // + // Author: Diego Perini + // Updated: 2010/12/05 + // + // the regular expression composed & commented + // could be easily tweaked for RFC compliance, + // it was expressly modified to fit & satisfy + // these test for an URL shortener: + // + // 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 + // - 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 + // + // Compressed one-line versions: + // + // Javascript version + // + // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i + // + // PHP version + // + // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS + var urlExp = new RegExp( + "^" + + // protocol identifier + "(?:(?:https?|ftp)://)" + + // user:pass authentication + "(?:\\S+(?::\\S*)?@)?" + + "(?:" + + // IP address exclusion + // private & local networks + "(?!10(?:\\.\\d{1,3}){3})" + + "(?!127(?:\\.\\d{1,3}){3})" + + "(?!169\\.254(?:\\.\\d{1,3}){2})" + + "(?!192\\.168(?:\\.\\d{1,3}){2})" + + "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" + + // IP address dotted notation octets + // excludes loopback network 0.0.0.0 + // excludes reserved space >= 224.0.0.0 + // excludes network & broacast addresses + // (first & last IP address of each class) + "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + + "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + + "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + + "|" + + // host name + "(?:(?:[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,}))" + + ")" + + // port number + "(?::\\d{2,5})?" + + // resource path + "(?:/[^\\s]*)?" + + "$", "i" + ); + return urlExp.test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.uuid = { + html5Attributes: { + message: 'message', + version: 'version' + }, + + /** + * Return true if and only if the input value is a valid UUID string + * + * @see http://en.wikipedia.org/wiki/Universally_unique_identifier + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - version: Can be 3, 4, 5, null + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // See the format at http://en.wikipedia.org/wiki/Universally_unique_identifier#Variants_and_versions + var patterns = { + '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, + '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, + all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i + }, + version = options.version ? (options.version + '') : 'all'; + return (null == patterns[version]) ? true : patterns[version].test(value); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.vat = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Validate an European VAT number + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166-1 country code + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + var country = options.country || value.substr(0, 2), + method = ['_', country.toLowerCase()].join(''); + if (this[method] && 'function' == typeof this[method]) { + return this[method](value); + } + + return true; + }, + + // VAT validators + + /** + * Validate Austrian VAT number + * Example: + * - Valid: ATU13585627 + * - Invalid: ATU13585626 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _at: function(value) { + if (!/^ATU[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(3); + var sum = 0, + weight = [1, 2, 1, 2, 1, 2, 1], + temp = 0; + + for (var i = 0; i < 7; i++) { + temp = parseInt(value.charAt(i)) * weight[i]; + if (temp > 9) { + temp = Math.floor(temp / 10) + temp % 10; + } + sum += temp; + } + + sum = 10 - (sum + 4) % 10; + if (sum == 10) { + sum = 0; + } + + return (sum == value.substr(7, 1)); + }, + + /** + * Validate Belgian VAT number + * Example: + * - Valid: BE0428759497 + * - Invalid: BE431150351 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _be: function(value) { + if (!/^BE[0]{0,1}[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + if (value.length == 9) { + value = '0' + value; + } + + if (value.substr(1, 1) == 0) { + return false; + } + + var sum = parseInt(value.substr(0, 8), 10) + parseInt(value.substr(8, 2), 10); + return (sum % 97 == 0); + }, + + /** + * Validate Bulgarian VAT number + * Example: + * - Valid: BG175074752, + * BG7523169263, BG8032056031, + * BG7542011030, + * BG7111042925 + * - Invalid: BG175074753, BG7552A10004, BG7111042922 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _bg: function(value) { + if (!/^BG[0-9]{9,10}$/.test(value)) { + return false; + } + + value = value.substr(2); + + var total = 0, sum = 0, weight = [], i = 0; + + // Legal entities + if (value.length == 9) { + for (i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * (i + 1); + } + sum = sum % 11; + if (sum == 10) { + sum = 0; + for (i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * (i + 3); + } + } + sum = sum % 10; + return (sum == value.substr(8)); + } + // Physical persons, foreigners and others + else if (value.length == 10) { + // Validate Bulgarian national identification numbers + var egn = function(value) { + // Check the birth date + var year = parseInt(value.substr(0, 2), 10) + 1900, + month = parseInt(value.substr(2, 2), 10), + day = parseInt(value.substr(4, 2), 10); + if (month > 40) { + year += 100; + month -= 40; + } else if (month > 20) { + year -= 100; + month -= 20; + } + + if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { + return false; + } + + var sum = 0, + weight = [2, 4, 8, 5, 10, 9, 7, 3, 6]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = (sum % 11) % 10; + return (sum == value.substr(9, 1)); + }, + // Validate Bulgarian personal number of a foreigner + pnf = function(value) { + var sum = 0, + weight = [21, 19, 17, 13, 11, 9, 7, 3, 1]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 10; + return (sum == value.substr(9, 1)); + }, + // Finally, consider it as a VAT number + vat = function(value) { + var sum = 0, + weight = [4, 3, 2, 7, 6, 5, 4, 3, 2]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = 11 - sum % 11; + if (sum == 10) { + return false; + } + if (sum == 11) { + sum = 0; + } + return (sum == value.substr(9, 1)); + }; + return (egn(value) || pnf(value) || vat(value)); + } + + return false; + }, + + /** + * Validate Swiss VAT number + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ch: function(value) { + if (!/^CHE[0-9]{9}(MWST)?$/.test(value)) { + return false; + } + + value = value.substr(3); + var sum = 0, + weight = [5, 4, 3, 2, 7, 6, 5, 4]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i), 10) * weight[i]; + } + + sum = 11 - sum % 11; + if (sum == 10) { + return false; + } + if (sum == 11) { + sum = 0; + } + + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Cypriot VAT number + * Examples: + * - Valid: CY10259033P + * - Invalid: CY10259033Z + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _cy: function(value) { + if (!/^CY[0-5|9]{1}[0-9]{7}[A-Z]{1}$/.test(value)) { + return false; + } + + value = value.substr(2); + + // Do not allow to start with "12" + if (value.substr(0, 2) == '12') { + return false; + } + + // Extract the next digit and multiply by the counter. + var sum = 0, + translation = { + '0': 1, '1': 0, '2': 5, '3': 7, '4': 9, + '5': 13, '6': 15, '7': 17, '8': 19, '9': 21 + }; + for (var i = 0; i < 8; i++) { + var temp = parseInt(value.charAt(i), 10); + if (i % 2 == 0) { + temp = translation[temp + '']; + } + sum += temp; + } + + sum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[sum % 26]; + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Czech Republic VAT number + * Can be: + * i) Legal entities (8 digit numbers) + * ii) Individuals with a RC (the 9 or 10 digit Czech birth number) + * iii) Individuals without a RC (9 digit numbers beginning with 6) + * + * Examples: + * - Valid: i) CZ25123891; ii) CZ7103192745, CZ991231123; iii) CZ640903926 + * - Invalid: i) CZ25123890; ii) CZ1103492745, CZ590312123 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _cz: function(value) { + if (!/^CZ[0-9]{8,10}$/.test(value)) { + return false; + } + + value = value.substr(2); + + var sum = 0, + i = 0; + if (value.length == 8) { + // Do not allow to start with '9' + if (value.charAt(0) + '' == '9') { + return false; + } + + sum = 0; + for (i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i), 10) * (8 - i); + } + sum = 11 - sum % 11; + if (sum == 10) { + sum = 0; + } + if (sum == 11) { + sum = 1; + } + + return (sum == value.substr(7, 1)); + } else if (value.length == 9 && (value.charAt(0) + '' == '6')) { + sum = 0; + // Skip the first (which is 6) + for (i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i + 1), 10) * (8 - i); + } + sum = 11 - sum % 11; + if (sum == 10) { + sum = 0; + } + if (sum == 11) { + sum = 1; + } + sum = [8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 10][sum - 1]; + return (sum == value.substr(8, 1)); + } else if (value.length == 9 || value.length == 10) { + // Validate Czech birth number (Rodné číslo), which is also national identifier + var year = 1900 + parseInt(value.substr(0, 2)), + month = parseInt(value.substr(2, 2)) % 50 % 20, + day = parseInt(value.substr(4, 2)); + if (value.length == 9) { + if (year >= 1980) { + year -= 100; + } + if (year > 1953) { + return false; + } + } else if (year < 1954) { + year += 100; + } + + if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { + return false; + } + + // Check that the birth date is not in the future + if (value.length == 10) { + var check = parseInt(value.substr(0, 9), 10) % 11; + if (year < 1985) { + check = check % 10; + } + return (check == value.substr(9, 1)); + } + + return true; + } + + return false; + }, + + /** + * Validate German VAT number + * Examples: + * - Valid: DE136695976 + * - Invalid: DE136695978 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _de: function(value) { + if (!/^DE[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + return $.fn.bootstrapValidator.helpers.mod_11_10(value); + }, + + /** + * Validate Danish VAT number + * Example: + * - Valid: DK13585628 + * - Invalid: DK13585627 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _dk: function(value) { + if (!/^DK[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [2, 7, 6, 5, 4, 3, 2, 1]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i), 10) * weight[i]; + } + + return (sum % 11 == 0); + }, + + /** + * Validate Estonian VAT number + * Examples: + * - Valid: EE100931558, EE100594102 + * - Invalid: EE100594103 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ee: function(value) { + if (!/^EE[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [3, 7, 1, 3, 7, 1, 3, 7, 1]; + + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 10 == 0); + }, + + /** + * Validate Spanish VAT number (NIF - Número de Identificación Fiscal) + * Can be: + * i) DNI (Documento nacional de identidad), for Spaniards + * ii) NIE (Número de Identificación de Extranjeros), for foreigners + * iii) CIF (Certificado de Identificación Fiscal), for legal entities and others + * + * Examples: + * - Valid: i) ES54362315K; ii) ESX2482300W, ESX5253868R; iii) ESM1234567L, ESJ99216582, ESB58378431, ESB64717838 + * - Invalid: i) ES54362315Z; ii) ESX2482300A; iii) ESJ99216583 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _es: function(value) { + if (!/^ES[0-9A-Z][0-9]{7}[0-9A-Z]$/.test(value)) { + return false; + } + + value = value.substr(2); + var dni = function(value) { + var check = parseInt(value.substr(0, 8), 10); + check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; + return (check == value.substr(8, 1)); + }, + nie = function(value) { + var check = ['XYZ'.indexOf(value.charAt(0)), value.substr(1)].join(''); + check = parseInt(check, 10); + check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; + return (check == value.substr(8, 1)); + }, + cif = function(value) { + var first = value.charAt(0), check; + if ('KLM'.indexOf(first) != -1) { + // K: Spanish younger than 14 year old + // L: Spanish living outside Spain without DNI + // M: Granted the tax to foreigners who have no NIE + check = parseInt(value.substr(1, 8), 10); + check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; + return (check == value.substr(8, 1)); + } else if ('ABCDEFGHJNPQRSUVW'.indexOf(first) != -1) { + var sum = 0, + weight = [2, 1, 2, 1, 2, 1, 2], + temp = 0; + + for (var i = 0; i < 7; i++) { + temp = parseInt(value.charAt(i + 1)) * weight[i]; + if (temp > 9) { + temp = Math.floor(temp / 10) + temp % 10; + } + sum += temp; + } + sum = 10 - sum % 10; + return (sum == value.substr(8, 1) || 'JABCDEFGHI'[sum] == value.substr(8, 1)); + } + + return false; + }; + + var first = value.charAt(0); + if (/^[0-9]$/.test(first)) { + return dni(value); + } else if (/^[XYZ]$/.test(first)) { + return nie(value); + } else { + return cif(value); + } + }, + + /** + * Validate Finnish VAT number + * Examples: + * - Valid: FI20774740 + * - Invalid: FI20774741 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _fi: function(value) { + if (!/^FI[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [7, 9, 10, 5, 8, 4, 2, 1]; + + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 11 == 0); + }, + + /** + * Validate French VAT number (TVA - taxe sur la valeur ajoutée) + * It's constructed by a SIREN number, prefixed by two characters. + * + * Examples: + * - Valid: FR40303265045, FR23334175221, FRK7399859412, FR4Z123456782 + * - Invalid: FR84323140391 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _fr: function(value) { + if (!/^FR[0-9A-Z]{2}[0-9]{9}$/.test(value)) { + return false; + } + + value = 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 + return value.substr(0, 2) == (parseInt(value.substr(2) + '12', 10) % 97); + } else { + // The first characters cann't be O and I + var alphabet = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ', + check; + // First one is digit + if (/^[0-9]{1}$/.test(value.charAt(0))) { + check = alphabet.indexOf(value.charAt(0)) * 24 + alphabet.indexOf(value.charAt(1)) - 10; + } else { + check = alphabet.indexOf(value.charAt(0)) * 34 + alphabet.indexOf(value.charAt(1)) - 100; + } + return ((parseInt(value.substr(2), 10) + 1 + Math.floor(check / 11)) % 11) == (check % 11); + } + }, + + /** + * Validate United Kingdom VAT number + * Example: + * - Valid: GB980780684 + * - Invalid: GB802311781 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _gb: function(value) { + if (!/^GB[0-9]{9}$/.test(value) // Standard + && !/^GB[0-9]{12}$/.test(value) // Branches + && !/^GBGD[0-9]{3}$/.test(value) // Government department + && !/^GBHA[0-9]{3}$/.test(value) // Health authority + && !/^GB(GD|HA)8888[0-9]{5}$/.test(value)) + { + return false; + } + + value = value.substr(2); + var length = value.length; + if (length == 5) { + var firstTwo = value.substr(0, 2), + lastThree = parseInt(value.substr(2)); + return ('GD' == firstTwo && lastThree < 500) || ('HA' == firstTwo && lastThree >= 500); + } else if (length == 11 && ('GD8888' == value.substr(0, 6) || 'HA8888' == value.substr(0, 6))) { + if (('GD' == value.substr(0, 2) && parseInt(value.substr(6, 3)) >= 500) + || ('HA' == value.substr(0, 2) && parseInt(value.substr(6, 3)) < 500)) + { + return false; + } + return (parseInt(value.substr(6, 3)) % 97 == parseInt(value.substr(9, 2))); + } else if (length == 9 || length == 12) { + var sum = 0, + weight = [8, 7, 6, 5, 4, 3, 2, 10, 1]; + for (var i = 0; i < 9; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 97; + + if (parseInt(value.substr(0, 3)) >= 100) { + return (sum == 0 || sum == 42 || sum == 55); + } else { + return (sum == 0); + } + } + + return true; + }, + + /** + * Validate Greek VAT number + * Examples: + * - Valid: GR023456780, EL094259216 + * - Invalid: EL123456781 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _gr: function(value) { + if (!/^GR[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + if (value.length == 8) { + value = '0' + value; + } + + var sum = 0, + weight = [256, 128, 64, 32, 16, 8, 4, 2]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = (sum % 11) % 10; + + return (sum == value.substr(8, 1)); + }, + + // EL is traditionally prefix of Greek VAT numbers + _el: function(value) { + if (!/^EL[0-9]{9}$/.test(value)) { + return false; + } + + value = 'GR' + value.substr(2); + return this._gr(value); + }, + + /** + * Validate Hungarian VAT number + * Examples: + * - Valid: HU12892312 + * - Invalid: HU12892313 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _hu: function(value) { + if (!/^HU[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [9, 7, 3, 1, 9, 7, 3, 1]; + + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 10 == 0); + }, + + /** + * Validate Croatian VAT number + * Examples: + * - Valid: HR33392005961 + * - Invalid: HR33392005962 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _hr: function(value) { + if (!/^HR[0-9]{11}$/.test(value)) { + return false; + } + + value = value.substr(2); + return $.fn.bootstrapValidator.helpers.mod_11_10(value); + }, + + /** + * Validate Irish VAT number + * Examples: + * - Valid: IE6433435F, IE6433435OA, IE8D79739I + * - Invalid: IE8D79738J + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ie: function(value) { + if (!/^IE[0-9]{1}[0-9A-Z\*\+]{1}[0-9]{5}[A-Z]{1,2}$/.test(value)) { + return false; + } + + value = value.substr(2); + var getCheckDigit = function(value) { + while (value.length < 7) { + value = '0' + value; + } + var alphabet = 'WABCDEFGHIJKLMNOPQRSTUV', + sum = 0; + for (var i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i)) * (8 - i); + } + sum += 9 * alphabet.indexOf(value.substr(7)); + return alphabet[sum % 23]; + }; + + // The first 7 characters are digits + if (/^[0-9]+$/.test(value.substr(0, 7))) { + // New system + return value.charAt(7) == getCheckDigit(value.substr(0, 7) + value.substr(8) + ''); + } else if ('ABCDEFGHIJKLMNOPQRSTUVWXYZ+*'.indexOf(value.charAt(1)) != -1) { + // Old system + return value.charAt(7) == getCheckDigit(value.substr(2, 5) + value.substr(0, 1) + ''); + } + + return true; + }, + + /** + * 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 + * + * Examples: + * - Valid: IT00743110157 + * - Invalid: IT00743110158 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _it: function(value) { + if (!/^IT[0-9]{11}$/.test(value)) { + return false; + } + + value = value.substr(2); + if (parseInt(value.substr(0, 7)) == 0) { + return false; + } + + var lastThree = parseInt(value.substr(7, 3)); + if ((lastThree < 1) || (lastThree > 201) && lastThree != 999 && lastThree != 888) { + return false; + } + + return $.fn.bootstrapValidator.helpers.luhn(value); + }, + + /** + * Validate Lithuanian VAT number + * It can be: + * - 9 digits, for legal entities + * - 12 digits, for temporarily registered taxpayers + * + * Examples: + * - Valid: LT119511515, LT100001919017, LT100004801610 + * - Invalid: LT100001919018 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _lt: function(value) { + if (!/^LT([0-9]{7}1[0-9]{1}|[0-9]{10}1[0-9]{1})$/.test(value)) { + return false; + } + + value = value.substr(2); + var length = value.length, + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * (1 + i % 9); + } + var check = sum % 11; + if (check == 10) { + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * (1 + (i + 2) % 9); + } + } + check = check % 11 % 10; + return (check == value.charAt(length - 1)); + }, + + /** + * Validate Luxembourg VAT number + * Examples: + * - Valid: LU15027442 + * - Invalid: LU15027443 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _lu: function(value) { + if (!/^LU[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + return (value.substr(0, 6) % 89 == value.substr(6, 2)); + }, + + /** + * Validate Latvian VAT number + * Examples: + * - Valid: LV40003521600, LV16117519997 + * - Invalid: LV40003521601, LV16137519997 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _lv: function(value) { + if (!/^LV[0-9]{11}$/.test(value)) { + return false; + } + + value = value.substr(2); + var first = parseInt(value.charAt(0)), + sum = 0, + weight = [], + i = 0, + length = value.length; + if (first > 3) { + // Legal entity + sum = 0; + weight = [9, 1, 4, 8, 3, 10, 2, 5, 7, 6, 1]; + for (i = 0; i < length; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 11; + return (sum == 3); + } else { + // Check birth date + var day = parseInt(value.substr(0, 2)), + month = parseInt(value.substr(2, 2)), + year = parseInt(value.substr(4, 2)); + year = year + 1800 + parseInt(value.charAt(6)) * 100; + + if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { + return false; + } + + // Check personal code + sum = 0; + weight = [10, 5, 8, 4, 2, 1, 6, 3, 7, 9]; + for (i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = (sum + 1) % 11 % 10; + return (sum == value.charAt(length - 1)); + } + + return true; + }, + + /** + * Validate Maltese VAT number + * Examples: + * - Valid: MT11679112 + * - Invalid: MT11679113 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _mt: function(value) { + if (!/^MT[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [3, 4, 6, 7, 8, 9, 10, 1]; + + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 37 == 0); + }, + + /** + * Validate Dutch VAT number + * Examples: + * - Valid: NL004495445B01 + * - Invalid: NL123456789B90 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _nl: function(value) { + if (!/^NL[0-9]{9}B[0-9]{2}$/.test(value)) { + return false; + } + value = value.substr(2); + var sum = 0, + weight = [9, 8, 7, 6, 5, 4, 3, 2]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + sum = sum % 11; + if (sum > 9) { + sum = 0; + } + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Norwegian VAT number + * + * @see http://www.brreg.no/english/coordination/number.html + * @param {String} value VAT number + * @returns {Boolean} + */ + _no: function(value) { + if (!/^NO[0-9]{9}$/.test(value)) { + return false; + } + value = value.substr(2); + var sum = 0, + weight = [3, 2, 7, 6, 5, 4, 3, 2]; + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + sum = 11 - sum % 11; + if (sum == 11) { + sum = 0; + } + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Polish VAT number + * Examples: + * - Valid: PL8567346215 + * - Invalid: PL8567346216 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _pl: function(value) { + if (!/^PL[0-9]{10}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [6, 5, 7, 2, 3, 4, 5, 6, 7, -1]; + + for (var i = 0; i < 10; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + return (sum % 11 == 0); + }, + + /** + * Validate Portuguese VAT number + * Examples: + * - Valid: PT501964843 + * - Invalid: PT501964842 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _pt: function(value) { + if (!/^PT[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [9, 8, 7, 6, 5, 4, 3, 2]; + + for (var i = 0; i < 8; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = 11 - sum % 11; + if (sum > 9) { + sum = 0; + } + return (sum == value.substr(8, 1)); + }, + + /** + * Validate Romanian VAT number + * Examples: + * - Valid: RO18547290 + * - Invalid: RO18547291 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ro: function(value) { + if (!/^RO[1-9][0-9]{1,9}$/.test(value)) { + return false; + } + value = value.substr(2); + + var length = value.length, + weight = [7, 5, 3, 2, 1, 7, 5, 3, 2].slice(10 - length), + sum = 0; + for (var i = 0; i < length - 1; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + + sum = (10 * sum) % 11 % 10; + return (sum == value.substr(length - 1, 1)); + }, + + /** + * Validate Russian VAT number (Taxpayer Identification Number - INN) + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _ru: function(value) { + if (!/^RU([0-9]{9}|[0-9]{12})$/.test(value)) { + return false; + } + + value = value.substr(2); + if (value.length == 10) { + var sum = 0, + weight = [2, 4, 10, 3, 5, 9, 4, 6, 8, 0]; + for (var i = 0; i < 10; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = sum % 11; + if (sum > 9) { + sum = sum % 10; + } + + return (sum == value.substr(9, 1)); + } else if (value.length == 12) { + var sum1 = 0, + weight1 = [7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0], + sum2 = 0, + weight2 = [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0]; + + for (var i = 0; i < 11; i++) { + sum1 += parseInt(value.charAt(i)) * weight1[i]; + sum2 += parseInt(value.charAt(i)) * weight2[i]; + } + sum1 = sum1 % 11; + if (sum1 > 9) { + sum1 = sum1 % 10; + } + sum2 = sum2 % 11; + if (sum2 > 9) { + sum2 = sum2 % 10; + } + + return (sum1 == value.substr(10, 1) && sum2 == value.substr(11, 1)); + } + + return false; + }, + + /** + * Validate Serbian VAT number + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _rs: function(value) { + if (!/^RS[0-9]{9}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 10, + temp = 0; + for (var i = 0; i < 8; i++) { + temp = (parseInt(value.charAt(i)) + sum) % 10; + if (temp == 0) { + temp = 10; + } + sum = (2 * temp) % 11; + } + + return ((sum + parseInt(value.substr(8, 1))) % 10 == 1); + }, + + /** + * Validate Swedish VAT number + * Examples: + * - Valid: SE123456789701 + * - Invalid: SE123456789101 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _se: function(value) { + if (!/^SE[0-9]{10}01$/.test(value)) { + return false; + } + + value = value.substr(2, 10); + return $.fn.bootstrapValidator.helpers.luhn(value); + }, + + /** + * Validate Slovenian VAT number + * Examples: + * - Valid: SI50223054 + * - Invalid: SI50223055 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _si: function(value) { + if (!/^SI[0-9]{8}$/.test(value)) { + return false; + } + + value = value.substr(2); + var sum = 0, + weight = [8, 7, 6, 5, 4, 3, 2]; + + for (var i = 0; i < 7; i++) { + sum += parseInt(value.charAt(i)) * weight[i]; + } + sum = 11 - sum % 11; + if (sum == 10) { + sum = 0; + } + return (sum == value.substr(7, 1)); + }, + + /** + * Validate Slovak VAT number + * Examples: + * - Valid: SK2022749619 + * - Invalid: SK2022749618 + * + * @param {String} value VAT number + * @returns {Boolean} + */ + _sk: function(value) { + if (!/^SK[1-9][0-9][(2-4)|(6-9)][0-9]{7}$/.test(value)) { + return false; + } + + value = value.substr(2); + return (value % 11 == 0); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.vin = { + /** + * Validate an US VIN (Vehicle Identification Number) + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '') { + return true; + } + + // Don't accept I, O, Q characters + if (!/^[a-hj-npr-z0-9]{8}[0-9xX][a-hj-npr-z0-9]{8}$/i.test(value)) { + return false; + } + + value = value.toUpperCase(); + var chars = { + A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8, + J: 1, K: 2, L: 3, M: 4, N: 5, P: 7, R: 9, + S: 2, T: 3, U: 4, V: 5, W: 6, X: 7, Y: 8, Z: 9, + '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '0': 0 + }, + weights = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2], + sum = 0, + length = value.length; + for (var i = 0; i < length; i++) { + sum += chars[value.charAt(i) + ''] * weights[i]; + } + + var reminder = sum % 11; + if (reminder == 10) { + reminder = 'X'; + } + + return reminder == value.charAt(8); + } + }; +}(window.jQuery)); +;(function($) { + $.fn.bootstrapValidator.validators.zipCode = { + html5Attributes: { + message: 'message', + country: 'country' + }, + + /** + * Return true if and only if the input value is a valid country zip code + * + * @param {BootstrapValidator} validator The validator plugin instance + * @param {jQuery} $field Field element + * @param {Object} options Consist of key: + * - message: The invalid message + * - country: The ISO 3166 country code + * + * Currently it supports the following countries: + * - US (United State) + * - CA (Canada) + * - DK (Denmark) + * - GB (United Kingdom) + * - IT (Italy) + * - NL (Netherlands) + * - SE (Sweden) + * @returns {Boolean} + */ + validate: function(validator, $field, options) { + var value = $field.val(); + if (value == '' || !options.country) { + return true; + } + + var country = (options.country || 'US').toUpperCase(); + switch (country) { + case 'CA': return /(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}\s?[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}/i.test(value); + case 'DK': return /^(DK(-|\s)?)?\d{4}$/i.test(value); + case 'GB': return this._gb(value); + + // http://en.wikipedia.org/wiki/List_of_postal_codes_in_Italy + case 'IT': return /^(I-|IT-)?\d{5}$/i.test(value); + + // http://en.wikipedia.org/wiki/Postal_codes_in_the_Netherlands + case 'NL': return /^[1-9][0-9]{3} ?(?!sa|sd|ss)[a-z]{2}$/i.test(value); + + case 'SE': return /^(S-)?\d{3}\s?\d{2}$/i.test(value); + case 'US': + default: return /^\d{4,5}([\-]\d{4})?$/.test(value); + } + }, + + /** + * Validate United Kingdom postcode + * Examples: + * - Standard: EC1A 1BB, W1A 1HQ, M1 1AA, B33 8TH, CR2 6XH, DN55 1PT + * - Special cases: + * AI-2640, ASCN 1ZZ, GIR 0AA + * + * @see http://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom + * @param {String} value The postcode + * @returns {Boolean} + */ + _gb: function(value) { + var firstChar = '[ABCDEFGHIJKLMNOPRSTUWYZ]', // Does not accept QVX + secondChar = '[ABCDEFGHKLMNOPQRSTUVWXY]', // Does not accept IJZ + thirdChar = '[ABCDEFGHJKPMNRSTUVWXY]', + fourthChar = '[ABEHMNPRVWXY]', + fifthChar = '[ABDEFGHJLNPQRSTUWXYZ]', + regexps = [ + // AN NAA, ANN NAA, AAN NAA, AANN NAA format + new RegExp('^(' + firstChar + '{1}' + secondChar + '?[0-9]{1,2})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'), + // ANA NAA + new RegExp('^(' + firstChar + '{1}[0-9]{1}' + thirdChar + '{1})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'), + // AANA NAA + new RegExp('^(' + firstChar + '{1}' + secondChar + '{1}?[0-9]{1}' + fourthChar + '{1})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'), + + new RegExp('^(BF1)(\\s*)([0-6]{1}[ABDEFGHJLNPQRST]{1}[ABDEFGHJLNPQRSTUWZYZ]{1})$', 'i'), // BFPO postcodes + /^(GIR)(\s*)(0AA)$/i, // Special postcode GIR 0AA + /^(BFPO)(\s*)([0-9]{1,4})$/i, // Standard BFPO numbers + /^(BFPO)(\s*)(c\/o\s*[0-9]{1,3})$/i, // c/o BFPO numbers + /^([A-Z]{4})(\s*)(1ZZ)$/i, // Overseas Territories + /^(AI-2640)$/i // Anguilla + ]; + for (var i = 0; i < regexps.length; i++) { + if (regexps[i].test(value)) { + return true; + } + } + + return false; + } + }; +}(window.jQuery)); diff --git a/ajax/libs/jquery.bootstrapvalidator/0.4.5/js/bootstrapValidator.min.js b/ajax/libs/jquery.bootstrapvalidator/0.4.5/js/bootstrapValidator.min.js new file mode 100644 index 000000000..c10d0d567 --- /dev/null +++ b/ajax/libs/jquery.bootstrapvalidator/0.4.5/js/bootstrapValidator.min.js @@ -0,0 +1,13 @@ +/** + * BootstrapValidator (http://bootstrapvalidator.com) + * + * The best jQuery plugin to validate form fields. Designed to use with Bootstrap 3 + * + * @version v0.4.5 + * @author https://twitter.com/nghuuphuoc + * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc + * @license MIT + */ + +!function(a){var b=function(c,d){this.$form=a(c),this.options=a.extend({},b.DEFAULT_OPTIONS,d),this.$invalidField=null,this.$submitButton=null,this.STATUS_NOT_VALIDATED="NOT_VALIDATED",this.STATUS_VALIDATING="VALIDATING",this.STATUS_INVALID="INVALID",this.STATUS_VALID="VALID";var e=function(){for(var a=3,b=document.createElement("div"),c=b.all||[];b.innerHTML="",c[0];);return a>4?a:!a}(),f=document.createElement("div");this._changeEvent=9!==e&&"oninput"in f?"input":"keyup",this._submitIfValid=null,this._init()};b.DEFAULT_OPTIONS={elementClass:"bv-form",message:"This value is not valid",threshold:null,excluded:[":disabled",":hidden",":not(:visible)"],feedbackIcons:{valid:null,invalid:null,validating:null},submitButtons:'[type="submit"]',submitHandler:null,live:"enabled",fields:null},b.prototype={constructor:b,_init:function(){var b,c,d,e,f,g,h,i=this,j={excluded:this.$form.attr("data-bv-excluded"),trigger:this.$form.attr("data-bv-trigger"),message:this.$form.attr("data-bv-message"),submitButtons:this.$form.attr("data-bv-submitbuttons"),threshold:this.$form.attr("data-bv-threshold"),live:this.$form.attr("data-bv-live"),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")}};this.$form.attr("novalidate","novalidate").addClass(this.options.elementClass).on("submit.bv",function(a){a.preventDefault(),i.validate()}).on("click",this.options.submitButtons,function(){i.$submitButton=a(this),i._submitIfValid=!0}).find("[name], [data-bv-field]").each(function(){var k=a(this);if(!i._isExcluded(k)){var l=k.attr("name")||k.attr("data-bv-field"),m={};for(c in a.fn.bootstrapValidator.validators)if(b=a.fn.bootstrapValidator.validators[c],d=k.attr("data-bv-"+c.toLowerCase())+"",h="function"==typeof b.enableByHtml5?b.enableByHtml5(a(this)):null,h&&"false"!=d||h!==!0&&(""==d||"true"==d)){b.html5Attributes=b.html5Attributes||{message:"message"},m[c]=a.extend({},1==h?{}:h,m[c]);for(g in b.html5Attributes)e=b.html5Attributes[g],f=k.attr("data-bv-"+c.toLowerCase()+"-"+g),f&&("true"==f?f=!0:"false"==f&&(f=!1),m[c][e]=f)}var n={trigger:k.attr("data-bv-trigger"),message:k.attr("data-bv-message"),container:k.attr("data-bv-container"),selector:k.attr("data-bv-selector"),threshold:k.attr("data-bv-threshold"),validators:m};a.isEmptyObject(n.validators)||a.isEmptyObject(n)||(k.attr("data-bv-field",l),j.fields[l]=a.extend({},n,j.fields[l]))}}).end().find(this.options.submitButtons).each(function(){a("").attr("type","hidden").attr("name",a(this).attr("name")).val(a(this).val()).appendTo(i.$form)}),this.options=a.extend(!0,this.options,j);for(var k in this.options.fields)this._initField(k);this.setLiveMode(this.options.live)},_initField:function(b){if(null!=this.options.fields[b]&&null!=this.options.fields[b].validators){var c=this.getFieldElements(b);if(null==c)return void delete this.options.fields[b];for(var d in this.options.fields[b].validators)a.fn.bootstrapValidator.validators[d]||delete this.options.fields[b].validators[d];for(var e=this,f=c.attr("type"),g="radio"==f||"checkbox"==f||"file"==f||"SELECT"==c[0].tagName?"change":e._changeEvent,h=c.length,i=1==h||"radio"==f||"checkbox"==f,j=0;h>j;j++){var k=a(c[j]),l=k.parents(".form-group"),m=this.options.fields[b].container?l.find(this.options.fields[b].container):this._getMessageContainer(k);k.attr("data-bv-field")||k.attr("data-bv-field",b),k.on(g+".update.bv",function(){e._submitIfValid=!1,i?e.updateStatus(b,e.STATUS_NOT_VALIDATED,null):e.updateElementStatus(a(this),e.STATUS_NOT_VALIDATED,null)}),k.data("bv.messages",m);for(d in this.options.fields[b].validators)k.data("bv.result."+d,this.STATUS_NOT_VALIDATED),i&&j!=h-1||a("").css("display","none").attr("data-bv-validator",d).attr("data-bv-validator-for",b).html(this.options.fields[b].validators[d].message||this.options.fields[b].message||this.options.message).addClass("help-block").appendTo(m);if(this.options.feedbackIcons&&this.options.feedbackIcons.validating&&this.options.feedbackIcons.invalid&&this.options.feedbackIcons.valid&&(!i||j==h-1)){l.addClass("has-feedback");var n=a("").css("display","none").addClass("form-control-feedback").attr("data-bv-icon-for",b).insertAfter(k);0==l.find("label").length&&n.css("top",0)}}null==this.options.fields[b].enabled&&(this.options.fields[b].enabled=!0)}},_getMessageContainer:function(a){var b=a.parent();if(b.hasClass("form-group"))return b;var c=b.attr("class");if(!c)return this._getMessageContainer(b);c=c.split(" ");for(var d=c.length,e=0;d>e;e++)if(/^col-(xs|sm|md|lg)-\d+$/.test(c[e])||/^col-(xs|sm|md|lg)-offset-\d+$/.test(c[e]))return b;return this._getMessageContainer(b)},_submit:function(){if(this.isValid())this.options.submitHandler&&"function"==typeof this.options.submitHandler?this.options.submitHandler.call(this,this,this.$form,this.$submitButton):this.disableSubmitButtons(!0).defaultSubmit();else if("submitted"==this.options.live&&this.setLiveMode("enabled"),this.$invalidField){var b,c=this.$invalidField.parents(".tab-pane");c&&(b=c.attr("id"))&&a('a[href="#'+b+'"][data-toggle="tab"]').trigger("click.bs.tab.data-api"),this.$invalidField.focus()}},_isExcluded:function(b){if(this.options.excluded){"string"==typeof this.options.excluded&&(this.options.excluded=a.map(this.options.excluded.split(","),function(b){return a.trim(b)}));for(var c=this.options.excluded.length,d=0;c>d;d++)if("string"==typeof this.options.excluded[d]&&b.is(this.options.excluded[d])||"function"==typeof this.options.excluded[d]&&1==this.options.excluded[d].call(this,b,this))return!0}return!1},_exceedThreshold:function(a){var b=a.attr("data-bv-field"),c=this.options.fields[b].threshold||this.options.threshold;if(!c)return!0;var d=a.attr("type"),e=-1!=["button","checkbox","file","hidden","image","radio","reset","submit"].indexOf(d);return e||a.val().length>=c},getFieldElements:function(b){var c=this.options.fields[b].selector?a(this.options.fields[b].selector):this.$form.find('[name="'+b+'"]');return 0==c.length?null:c},setLiveMode:function(b){if(this.options.live=b,"submitted"==b)return this;var c=this;for(var d in this.options.fields)!function(e){var f=c.getFieldElements(e);if(f)for(var g=f.attr("type"),h=f.length,i=1==h||"radio"==g||"checkbox"==g,j=c.options.fields[d].trigger||c.options.trigger||("radio"==g||"checkbox"==g||"file"==g||"SELECT"==f[0].tagName?"change":c._changeEvent),k=a.map(j.split(" "),function(a){return a+".live.bv"}).join(" "),l=0;h>l;l++)"enabled"==b?a(f[l]).on(k,function(){c._exceedThreshold(a(this))&&(i?c.validateField(e):c.validateFieldElement(a(this),!1))}):a(f[l]).off(k)}(d);return this},disableSubmitButtons:function(a){return a?"disabled"!=this.options.live&&this.$form.find(this.options.submitButtons).attr("disabled","disabled"):this.$form.find(this.options.submitButtons).removeAttr("disabled"),this},validate:function(){if(!this.options.fields)return this;this.disableSubmitButtons(!0);for(var a in this.options.fields)this.validateField(a);return this.$submitButton&&this._submit(),this},validateField:function(b){for(var c=this.getFieldElements(b),d=c.attr("type"),e="radio"==d||"checkbox"==d?1:c.length,f=0;e>f;f++)this.validateFieldElement(a(c[f]),1==e);return this},validateFieldElement:function(b,c){var d,e,f=this,g=b.attr("data-bv-field"),h=this.options.fields[g].validators;if(!this.options.fields[g].enabled||this._isExcluded(b))return this;for(d in h){b.data("bv.dfs."+d)&&b.data("bv.dfs."+d).reject();var i=b.data("bv.result."+d);i!=this.STATUS_VALID&&i!=this.STATUS_INVALID&&(b.data("bv.result."+d,this.STATUS_VALIDATING),e=a.fn.bootstrapValidator.validators[d].validate(this,b,h[d]),"object"==typeof e?(c?this.updateStatus(g,this.STATUS_VALIDATING,d):this.updateElementStatus(b,this.STATUS_VALIDATING,d),b.data("bv.dfs."+d,e),e.done(function(a,b,d){a.removeData("bv.dfs."+b),c?f.updateStatus(a.attr("data-bv-field"),d?f.STATUS_VALID:f.STATUS_INVALID,b):f.updateElementStatus(a,d?f.STATUS_VALID:f.STATUS_INVALID,b),d&&1==f._submitIfValid&&f._submit()})):"boolean"==typeof e&&(c?this.updateStatus(g,e?this.STATUS_VALID:this.STATUS_INVALID,d):this.updateElementStatus(b,e?this.STATUS_VALID:this.STATUS_INVALID,d)))}return this},updateStatus:function(b,c,d){for(var e=this.getFieldElements(b),f=e.attr("type"),g="radio"==f||"checkbox"==f?1:e.length,h=0;g>h;h++)this.updateElementStatus(a(e[h]),c,d);return this},updateElementStatus:function(b,c,d){var e=this,f=b.attr("data-bv-field"),g=b.parents(".form-group"),h=b.data("bv.messages"),i=h.find(".help-block[data-bv-validator]"),j=g.find('.form-control-feedback[data-bv-icon-for="'+f+'"]');if(d)b.data("bv.result."+d,c);else for(var k in this.options.fields[f].validators)b.data("bv.result."+k,c);var l,m,n=b.parents(".tab-pane");switch(n&&(l=n.attr("id"))&&(m=a('a[href="#'+l+'"][data-toggle="tab"]').parent()),c){case this.STATUS_VALIDATING:this.disableSubmitButtons(!0),g.removeClass("has-success").removeClass("has-error"),d?i.filter('.help-block[data-bv-validator="'+d+'"]').hide():i.hide(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(),m&&m.removeClass("bv-tab-success").removeClass("bv-tab-error");break;case this.STATUS_INVALID:this.disableSubmitButtons(!0),g.removeClass("has-success").addClass("has-error"),d?i.filter('[data-bv-validator="'+d+'"]').show():i.show(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(),m&&m.removeClass("bv-tab-success").addClass("bv-tab-error");break;case this.STATUS_VALID:d?i.filter('[data-bv-validator="'+d+'"]').hide():i.hide();var o=0==i.filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||b.data("bv.result."+d)!=e.STATUS_VALID}).length;this.disableSubmitButtons(!o),j&&j.removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid).addClass(o?this.options.feedbackIcons.valid:this.options.feedbackIcons.invalid).show();var p=function(c){return 0==c.find(".help-block[data-bv-validator]").filter(function(){var c=a(this).css("display"),d=a(this).attr("data-bv-validator");return"block"==c||b.data("bv.result."+d)&&b.data("bv.result."+d)!=e.STATUS_VALID}).length};g.removeClass("has-error has-success").addClass(p(g)?"has-success":"has-error"),m&&m.removeClass("bv-tab-success").removeClass("bv-tab-error").addClass(p(n)?"bv-tab-success":"bv-tab-error");break;case this.STATUS_NOT_VALIDATED:default:this.disableSubmitButtons(!1),g.removeClass("has-success").removeClass("has-error"),d?i.filter('.help-block[data-bv-validator="'+d+'"]').hide():i.hide(),j&&j.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide(),m&&m.removeClass("bv-tab-success").removeClass("bv-tab-error")}return this},isValid:function(){var b,c,d,e,f,g,h,i;for(c in this.options.fields)if(null!=this.options.fields[c]&&this.options.fields[c].enabled)for(b=this.getFieldElements(c),e=b.attr("type"),h="radio"==e||"checkbox"==e?1:b.length,i=0;h>i;i++)if(d=a(b[i]),!this._isExcluded(d))for(g in this.options.fields[c].validators){if(f=d.data("bv.result."+g),f==this.STATUS_NOT_VALIDATED||f==this.STATUS_VALIDATING)return!1;if(f==this.STATUS_INVALID)return this.$invalidField=d,!1}return!0},defaultSubmit:function(){this.$form.off("submit.bv").submit()},resetForm:function(b){var c,d,e,f,g;for(c in this.options.fields){d=this.getFieldElements(c),e=d.length;for(var h=0;e>h;h++)for(g in this.options.fields[c].validators)a(d[h]).removeData("bv.dfs."+g);this.updateStatus(c,this.STATUS_NOT_VALIDATED,null),b&&(f=d.attr("type"),"radio"==f||"checkbox"==f?d.removeAttr("checked").removeAttr("selected"):d.val(""))}return this.$invalidField=null,this.$submitButton=null,this.disableSubmitButtons(!1),this},enableFieldValidators:function(a,b){return this.options.fields[a].enabled=b,this.updateStatus(a,this.STATUS_NOT_VALIDATED,null),this}},a.fn.bootstrapValidator=function(c){var d=arguments;return this.each(function(){var e=a(this),f=e.data("bootstrapValidator"),g="object"==typeof c&&c;f||(f=new b(this,g),e.data("bootstrapValidator",f)),"string"==typeof c&&f[c].apply(f,Array.prototype.slice.call(d,1))})},a.fn.bootstrapValidator.validators={},a.fn.bootstrapValidator.Constructor=b,a.fn.bootstrapValidator.helpers={date:function(a,b,c,d){if(1e3>a||a>9999||0==b||b>12)return!1;var e=[31,28,31,30,31,30,31,31,30,31,30,31];if((a%400==0||a%100!=0&&a%4==0)&&(e[1]=29),0>c||c>e[b-1])return!1;if(d===!0){var f=new Date,g=f.getFullYear(),h=f.getMonth(),i=f.getDate();return g>a||a==g&&h>b-1||a==g&&b-1==h&&i>c}return!0},luhn:function(a){for(var b=a.length,c=0,d=[[0,1,2,3,4,5,6,7,8,9],[0,2,4,6,8,1,3,5,7,9]],e=0;b--;)e+=d[c][parseInt(a.charAt(b),10)],c^=1;return e%10===0&&e>0},mod_11_10:function(a){for(var b=5,c=a.length,d=0;c>d;d++)b=(2*(b||10)%11+parseInt(a.charAt(d),10))%10;return 1==b},mod_37_36:function(a,b){b=b||"0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";for(var c=b.length,d=a.length,e=Math.floor(c/2),f=0;d>f;f++)e=(2*(e||c)%(c+1)+b.indexOf(a.charAt(f)))%c;return 1==e}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.base64={validate:function(a,b){var c=b.val();return""==c?!0:/^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.between={html5Attributes:{message:"message",min:"min",max:"max",inclusive:"inclusive"},enableByHtml5:function(a){return"range"==a.attr("type")?{min:a.attr("min"),max:a.attr("max")}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.min&&d=c.min&&d<=c.max)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.callback={validate:function(b,c,d){var e=c.val();if(d.callback&&"function"==typeof d.callback){var f=new a.Deferred;return f.resolve(c,"callback",d.callback.call(this,e,b)),f}return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.choice={html5Attributes:{message:"message",min:"min",max:"max"},validate:function(a,b,c){var d=b.is("select")?a.getFieldElements(b.attr("data-bv-field")).find("option").filter(":selected").length:a.getFieldElements(b.attr("data-bv-field")).filter(":checked").length;return c.min&&dc.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.creditCard={validate:function(b,c){var d=c.val();if(""==d)return!0;if(/[^0-9-\s]+/.test(d))return!1;if(d=d.replace(/\D/g,""),!a.fn.bootstrapValidator.helpers.luhn(d))return!1;var e,f,g={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["6304","6706","6771","6709"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}};for(e in g)for(f in g[e].prefix)if(d.substr(0,g[e].prefix[f].length)==g[e].prefix[f]&&-1!=g[e].length.indexOf(d.length))return!0;return!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.cusip={validate:function(b,c){var d=c.val();if(""==d)return!0;if(d=d.toUpperCase(),!/^[0-9A-Z]{9}$/.test(d))return!1;for(var e=a.map(d.split(""),function(a){var b=a.charCodeAt(0);return b>="A".charCodeAt(0)&&b<="Z".charCodeAt(0)?b-"A".charCodeAt(0)+10:a}),f=e.length,g=0,h=0;f-1>h;h++){var i=parseInt(e[h]);h%2!=0&&(i*=2),i>9&&(i-=9),g+=i}return g=(10-g%10)%10,g==e[f-1]}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.cvv={html5Attributes:{message:"message",ccfield:"creditCardField"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;if(!/^[0-9]{3,4}$/.test(d))return!1;if(!c.creditCardField)return!0;var e=a.getFieldElements(c.creditCardField).val();if(""==e)return!0;e=e.replace(/\D/g,"");var f,g,h={AMERICAN_EXPRESS:{length:[15],prefix:["34","37"]},DINERS_CLUB:{length:[14],prefix:["300","301","302","303","304","305","36"]},DINERS_CLUB_US:{length:[16],prefix:["54","55"]},DISCOVER:{length:[16],prefix:["6011","622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925","644","645","646","647","648","649","65"]},JCB:{length:[16],prefix:["3528","3529","353","354","355","356","357","358"]},LASER:{length:[16,17,18,19],prefix:["6304","6706","6771","6709"]},MAESTRO:{length:[12,13,14,15,16,17,18,19],prefix:["5018","5020","5038","6304","6759","6761","6762","6763","6764","6765","6766"]},MASTERCARD:{length:[16],prefix:["51","52","53","54","55"]},SOLO:{length:[16,18,19],prefix:["6334","6767"]},UNIONPAY:{length:[16,17,18,19],prefix:["622126","622127","622128","622129","62213","62214","62215","62216","62217","62218","62219","6222","6223","6224","6225","6226","6227","6228","62290","62291","622920","622921","622922","622923","622924","622925"]},VISA:{length:[16],prefix:["4"]}},i=null;for(f in h)for(g in h[f].prefix)if(e.substr(0,h[f].prefix[g].length)==h[f].prefix[g]&&-1!=h[f].length.indexOf(e.length)){i=f;break}return null==i?!1:"AMERICAN_EXPRESS"==i?4==d.length:3==d.length}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.date={html5Attributes:{message:"message",format:"format"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;d.format=d.format||"MM/DD/YYYY";var f=d.format.split(" "),g=f[0],h=f.length>1?f[1]:null,i=f.length>2?f[2]:null,j=e.split(" "),k=j[0],l=j.length>1?j[1]:null;if(f.length!=j.length)return!1;var m=-1!=k.indexOf("/")?"/":-1!=k.indexOf("-")?"-":null;if(null==m)return!1;k=k.split(m),g=g.split(m);var n=k[g.indexOf("YYYY")],o=k[g.indexOf("MM")],p=k[g.indexOf("DD")],q=null,r=null,s=null;if(h){if(h=h.split(":"),l=l.split(":"),h.length!=l.length)return!1;if(r=l.length>0?l[0]:null,q=l.length>1?l[1]:null,s=l.length>2?l[2]:null,s&&(s=parseInt(s,10),0>s||s>60))return!1;if(r&&(r=parseInt(r,10),0>r||r>=24||i&&r>12))return!1;if(q&&(q=parseInt(q,10),0>q||q>59))return!1}return p=parseInt(p,10),o=parseInt(o,10),n=parseInt(n,10),a.fn.bootstrapValidator.helpers.date(n,o,p)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.different={html5Attributes:{message:"message",field:"field"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d!=e.val()?(a.updateStatus(c.field,a.STATUS_VALID,"different"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.digits={validate:function(a,b){var c=b.val();return""==c?!0:/^\d+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.ean={validate:function(a,b){var c=b.val();if(""==c)return!0;if(!/^(\d{8}|\d{12}|\d{13})$/.test(c))return!1;for(var d=c.length,e=0,f=8==d?[3,1]:[1,3],g=0;d-1>g;g++)e+=parseInt(c.charAt(g))*f[g%2];return e=10-e%10,e==c.charAt(d-1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.emailAddress={enableByHtml5:function(a){return"email"==a.attr("type")},validate:function(a,b){var c=b.val();if(""==c)return!0;var d=/^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.file={html5Attributes:{extension:"extension",maxsize:"maxSize",message:"message",type:"type"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e,f=c.extension?c.extension.split(","):null,g=c.type?c.type.split(","):null,h=window.File&&window.FileList&&window.FileReader;if(h)for(var i=b.get(0).files,j=i.length,k=0;j>k;k++){if(c.maxSize&&i[k].size>parseInt(c.maxSize))return!1;if(e=i[k].name.substr(i[k].name.lastIndexOf(".")+1),f&&-1==f.indexOf(e))return!1;if(g&&-1==g.indexOf(i[k].type))return!1}else if(e=d.substr(d.lastIndexOf(".")+1),f&&-1==f.indexOf(e))return!1;return!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.greaterThan={html5Attributes:{message:"message",value:"value",inclusive:"inclusive"},enableByHtml5:function(a){var b=a.attr("min");return b?{value:b}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!0?d>c.value:d>=c.value)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.grid={validate:function(b,c){var d=c.val();return""==d?!0:(d=d.toUpperCase(),/^[GRID:]*([0-9A-Z]{2})[-\s]*([0-9A-Z]{5})[-\s]*([0-9A-Z]{10})[-\s]*([0-9A-Z]{1})$/g.test(d)?(d=d.replace(/\s/g,"").replace(/-/g,""),"GRID:"==d.substr(0,5)&&(d=d.substr(5)),a.fn.bootstrapValidator.helpers.mod_37_36(d)):!1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hex={validate:function(a,b){var c=b.val();return""==c?!0:/^[0-9a-fA-F]+$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.hexColor={enableByHtml5:function(a){return"color"==a.attr("type")},validate:function(a,b){var c=b.val();return""==c?!0:/(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.iban={html5Attributes:{message:"message",country:"country"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f={AD:"AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}",AE:"AE[0-9]{2}[0-9]{3}[0-9]{16}",AL:"AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}",AO:"AO[0-9]{2}[0-9]{21}",AT:"AT[0-9]{2}[0-9]{5}[0-9]{11}",AZ:"AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}",BA:"BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}",BE:"BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}",BF:"BF[0-9]{2}[0-9]{23}",BG:"BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}",BH:"BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}",BI:"BI[0-9]{2}[0-9]{12}",BJ:"BJ[0-9]{2}[A-Z]{1}[0-9]{23}",BR:"BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]",CH:"CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}",CI:"CI[0-9]{2}[A-Z]{1}[0-9]{23}",CM:"CM[0-9]{2}[0-9]{23}",CR:"CR[0-9]{2}[0-9]{3}[0-9]{14}",CV:"CV[0-9]{2}[0-9]{21}",CY:"CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}",CZ:"CZ[0-9]{2}[0-9]{20}",DE:"DE[0-9]{2}[0-9]{8}[0-9]{10}",DK:"DK[0-9]{2}[0-9]{14}",DO:"DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}",DZ:"DZ[0-9]{2}[0-9]{20}",EE:"EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}",ES:"ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}",FI:"FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}",FO:"FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}",FR:"FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}",GB:"GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}",GE:"GE[0-9]{2}[A-Z]{2}[0-9]{16}",GI:"GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}",GL:"GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}",GR:"GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}",GT:"GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}",HR:"HR[0-9]{2}[0-9]{7}[0-9]{10}",HU:"HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}",IE:"IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}",IL:"IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}",IR:"IR[0-9]{2}[0-9]{22}",IS:"IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}",IT:"IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}",JO:"JO[0-9]{2}[A-Z]{4}[0-9]{4}[0]{8}[A-Z0-9]{10}",KW:"KW[0-9]{2}[A-Z]{4}[0-9]{22}",KZ:"KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}",LB:"LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}",LI:"LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}",LT:"LT[0-9]{2}[0-9]{5}[0-9]{11}",LU:"LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}",LV:"LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}",MC:"MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}",MD:"MD[0-9]{2}[A-Z0-9]{20}",ME:"ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",MG:"MG[0-9]{2}[0-9]{23}",MK:"MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}",ML:"ML[0-9]{2}[A-Z]{1}[0-9]{23}",MR:"MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}",MT:"MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}",MU:"MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}",MZ:"MZ[0-9]{2}[0-9]{21}",NL:"NL[0-9]{2}[A-Z]{4}[0-9]{10}",NO:"NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}",PK:"PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}",PL:"PL[0-9]{2}[0-9]{8}[0-9]{16}",PS:"PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}",PT:"PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}",QA:"QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}",RO:"RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}",RS:"RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",SA:"SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}",SE:"SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}",SI:"SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}",SK:"SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}",SM:"SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}",SN:"SN[0-9]{2}[A-Z]{1}[0-9]{23}",TN:"TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}",TR:"TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}",VG:"VG[0-9]{2}[A-Z]{4}[0-9]{16}"};e=e.replace(/[^a-zA-Z0-9]/g,"").toUpperCase();var g=d.country||e.substr(0,2);if(!f[g])return!1;if(!new RegExp("^"+f[g]+"$").test(e))return!1;e=e.substr(4)+e.substr(0,4),e=a.map(e.split(""),function(a){var b=a.charCodeAt(0);return b>="A".charCodeAt(0)&&b<="Z".charCodeAt(0)?b-"A".charCodeAt(0)+10:a}),e=e.join("");for(var h=parseInt(e.substr(0,1),10),i=e.length,j=1;i>j;++j)h=(10*h+parseInt(e.substr(j,1),10))%97;return 1==h}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.id={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=c.country||d.substr(0,2),f=["_",e.toLowerCase()].join("");return this[f]&&"function"==typeof this[f]?this[f](d):!0},_validateJMBG:function(a,b){if(!/^\d{13}$/.test(a))return!1;var c=parseInt(a.substr(0,2),10),d=parseInt(a.substr(2,2),10),e=(parseInt(a.substr(4,3),10),parseInt(a.substr(7,2),10)),f=parseInt(a.substr(12,1),10);if(c>31||d>12)return!1;for(var g=0,h=0;6>h;h++)g+=(7-h)*(parseInt(a.charAt(h))+parseInt(a.charAt(h+6)));if(g=11-g%11,(10==g||11==g)&&(g=0),g!=f)return!1;switch(b.toUpperCase()){case"BA":return e>=10&&19>=e;case"MK":return e>=41&&49>=e;case"ME":return e>=20&&29>=e;case"RS":return e>=70&&99>=e;case"SI":return e>=50&&59>=e;default:return!0}},_ba:function(a){return this._validateJMBG(a,"BA")},_mk:function(a){return this._validateJMBG(a,"MK")},_me:function(a){return this._validateJMBG(a,"ME")},_rs:function(a){return this._validateJMBG(a,"RS")},_si:function(a){return this._validateJMBG(a,"SI")},_bg:function(b){if(!/^\d{10}$/.test(b)&&!/^\d{6}\s\d{3}\s\d{1}$/.test(b))return!1;b=b.replace(/\s/g,"");var c=parseInt(b.substr(0,2),10)+1900,d=parseInt(b.substr(2,2),10),e=parseInt(b.substr(4,2),10);if(d>40?(c+=100,d-=40):d>20&&(c-=100,d-=20),!a.fn.bootstrapValidator.helpers.date(c,d,e))return!1;for(var f=0,g=[2,4,8,5,10,9,7,3,6],h=0;9>h;h++)f+=parseInt(b.charAt(h))*g[h];return f=f%11%10,f==b.substr(9,1)},_br:function(a){if(/^1{11}|2{11}|3{11}|4{11}|5{11}|6{11}|7{11}|8{11}|9{11}|0{11}$/.test(a))return!1;if(!/^\d{11}$/.test(a)&&!/^\d{3}\.\d{3}\.\d{3}-\d{2}$/.test(a))return!1;a=a.replace(/\./g,"").replace(/-/g,"");for(var b=0,c=0;9>c;c++)b+=(10-c)*parseInt(a.charAt(c));if(b=11-b%11,(10==b||11==b)&&(b=0),b!=a.charAt(9))return!1;var d=0;for(c=0;10>c;c++)d+=(11-c)*parseInt(a.charAt(c));return d=11-d%11,(10==d||11==d)&&(d=0),d==a.charAt(10)},_ch:function(a){if(!/^756[\.]{0,1}[0-9]{4}[\.]{0,1}[0-9]{4}[\.]{0,1}[0-9]{2}$/.test(a))return!1;a=a.replace(/\D/g,"").substr(3);for(var b=a.length,c=0,d=8==b?[3,1]:[1,3],e=0;b-1>e;e++)c+=parseInt(a.charAt(e))*d[e%2];return c=10-c%10,c==a.charAt(b-1)},_cl:function(a){if(!/^\d{7,8}[-]{0,1}[0-9K]$/.test(a))return!1;for(a=a.replace(/\D/g,"");a.length<9;)a="0"+a;for(var b=0,c=[3,2,7,6,5,4,3,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,11==b?b=0:10==b&&(b="K"),b==a.charAt(8)},_cz:function(b){if(!/^\d{9,10}$/.test(b))return!1;var c=1900+parseInt(b.substr(0,2)),d=parseInt(b.substr(2,2))%50%20,e=parseInt(b.substr(4,2));if(9==b.length){if(c>=1980&&(c-=100),c>1953)return!1}else 1954>c&&(c+=100);if(!a.fn.bootstrapValidator.helpers.date(c,d,e))return!1;if(10==b.length){var f=parseInt(b.substr(0,9),10)%11;return 1985>c&&(f%=10),f==b.substr(9,1)}return!0},_dk:function(b){if(!/^[0-9]{6}[-]{0,1}[0-9]{4}$/.test(b))return!1;b=b.replace(/-/g,"");var c=parseInt(b.substr(0,2),10),d=parseInt(b.substr(2,2),10),e=parseInt(b.substr(4,2),10);switch(!0){case-1!="5678".indexOf(b.charAt(6))&&e>=58:e+=1800;break;case-1!="0123".indexOf(b.charAt(6)):case-1!="49".indexOf(b.charAt(6))&&e>=37:e+=1900;break;default:e+=2e3}return a.fn.bootstrapValidator.helpers.date(e,d,c)},_ee:function(a){return this._lt(a)},_es:function(a){if(!/^[0-9A-Z]{8}[-]{0,1}[0-9A-Z]$/.test(a)&&!/^[XYZ][-]{0,1}[0-9]{7}[-]{0,1}[0-9A-Z]$/.test(a))return!1;a=a.replace(/-/g,"");var b="XYZ".indexOf(a.charAt(0));-1!=b&&(a=b+a.substr(1)+"");var c=parseInt(a.substr(0,8),10);return c="TRWAGMYFPDXBNJZSQVHLCKE"[c%23],c==a.substr(8,1)},_fi:function(b){if(!/^[0-9]{6}[-+A][0-9]{3}[0-9ABCDEFHJKLMNPRSTUVWXY]$/.test(b))return!1;var c=parseInt(b.substr(0,2),10),d=parseInt(b.substr(2,2),10),e=parseInt(b.substr(4,2),10),f={"+":1800,"-":1900,A:2e3};if(e=f[b.charAt(6)]+e,!a.fn.bootstrapValidator.helpers.date(e,d,c))return!1;var g=parseInt(b.substr(7,3));if(2>g)return!1;var h=b.substr(0,6)+b.substr(7,3)+"";return h=parseInt(h),"0123456789ABCDEFHJKLMNPRSTUVWXY".charAt(h%31)==b.charAt(10)},_hr:function(b){return/^[0-9]{11}$/.test(b)?a.fn.bootstrapValidator.helpers.mod_11_10(b):!1},_ie:function(a){if(!/^\d{7}[A-W][AHWTX]?$/.test(a))return!1;var b=function(a){for(;a.length<7;)a="0"+a;for(var b="WABCDEFGHIJKLMNOPQRSTUV",c=0,d=0;7>d;d++)c+=parseInt(a.charAt(d))*(8-d);return c+=9*b.indexOf(a.substr(7)),b[c%23]};return 9!=a.length||"A"!=a.charAt(8)&&"H"!=a.charAt(8)?a.charAt(7)==b(a.substr(0,7)):a.charAt(7)==b(a.substr(0,7)+a.substr(8)+"")},_is:function(b){if(!/^[0-9]{6}[-]{0,1}[0-9]{4}$/.test(b))return!1;b=b.replace(/-/g,"");var c=parseInt(b.substr(0,2),10),d=parseInt(b.substr(2,2),10),e=parseInt(b.substr(4,2),10),f=parseInt(b.charAt(9));if(e=9==f?1900+e:100*(20+f)+e,!a.fn.bootstrapValidator.helpers.date(e,d,c,!0))return!1;for(var g=0,h=[3,2,7,6,5,4,3,2],i=0;8>i;i++)g+=parseInt(b.charAt(i))*h[i];return g=11-g%11,g==b.charAt(8)},_lt:function(b){if(!/^[0-9]{11}$/.test(b))return!1;var c=parseInt(b.charAt(0)),d=parseInt(b.substr(1,2),10),e=parseInt(b.substr(3,2),10),f=parseInt(b.substr(5,2),10),g=c%2==0?17+c/2:17+(c+1)/2;if(d=100*g+d,!a.fn.bootstrapValidator.helpers.date(d,e,f,!0))return!1;for(var h=0,i=[1,2,3,4,5,6,7,8,9,1],j=0;10>j;j++)h+=parseInt(b.charAt(j))*i[j];if(h%=11,10!=h)return h==b.charAt(10);for(h=0,i=[3,4,5,6,7,8,9,1,2,3],j=0;10>j;j++)h+=parseInt(b.charAt(j))*i[j];return h%=11,10==h&&(h=0),h==b.charAt(10)},_lv:function(b){if(!/^[0-9]{6}[-]{0,1}[0-9]{5}$/.test(b))return!1;b=b.replace(/\D/g,"");var c=parseInt(b.substr(0,2)),d=parseInt(b.substr(2,2)),e=parseInt(b.substr(4,2));if(e=e+1800+100*parseInt(b.charAt(6)),!a.fn.bootstrapValidator.helpers.date(e,d,c,!0))return!1;for(var f=0,g=[10,5,8,4,2,1,6,3,7,9],h=0;10>h;h++)f+=parseInt(b.charAt(h))*g[h];return f=(f+1)%11%10,f==b.charAt(10)},_nl:function(a){for(;a.length<9;)a="0"+a;if(!/^[0-9]{4}[.]{0,1}[0-9]{2}[.]{0,1}[0-9]{3}$/.test(a))return!1;if(a=a.replace(/\./g,""),0==parseInt(a,10))return!1;for(var b=0,c=a.length,d=0;c-1>d;d++)b+=(9-d)*parseInt(a.charAt(d));return b%=11,10==b&&(b=0),b==a.charAt(c-1)},_ro:function(b){if(!/^[0-9]{13}$/.test(b))return!1;var c=parseInt(b.charAt(0));if(0==c||7==c||8==c)return!1;var d=parseInt(b.substr(1,2),10),e=parseInt(b.substr(3,2),10),f=parseInt(b.substr(5,2),10),g={1:1900,2:1900,3:1800,4:1800,5:2e3,6:2e3};if(f>31&&e>12)return!1;if(9!=c&&(d=g[c+""]+d,!a.fn.bootstrapValidator.helpers.date(d,e,f)))return!1;for(var h=0,i=[2,7,9,1,4,6,3,5,8,2,7,9],j=b.length,k=0;j-1>k;k++)h+=parseInt(b.charAt(k))*i[k]; +return h%=11,10==h&&(h=1),h==b.charAt(j-1)},_se:function(b){if(!/^[0-9]{10}$/.test(b)&&!/^[0-9]{6}[-|+][0-9]{4}$/.test(b))return!1;b=b.replace(/[^0-9]/g,"");var c=parseInt(b.substr(0,2))+1900,d=parseInt(b.substr(2,2)),e=parseInt(b.substr(4,2));return a.fn.bootstrapValidator.helpers.date(c,d,e)?a.fn.bootstrapValidator.helpers.luhn(b):!1},_sk:function(a){return this._cz(a)},_sm:function(a){return/^\d{5}$/.test(a)},_za:function(b){if(!/^[0-9]{10}[0|1][8|9][0-9]$/.test(b))return!1;var c=parseInt(b.substr(0,2)),d=(new Date).getFullYear()%100,e=parseInt(b.substr(2,2)),f=parseInt(b.substr(4,2));return c=c>=d?c+1900:c+2e3,a.fn.bootstrapValidator.helpers.date(c,e,f)?a.fn.bootstrapValidator.helpers.luhn(b):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.identical={html5Attributes:{message:"message",field:"field"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=a.getFieldElements(c.field);return null==e?!0:d==e.val()?(a.updateStatus(c.field,a.STATUS_VALID,"identical"),!0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.imei={validate:function(b,c){var d=c.val();if(""==d)return!0;switch(!0){case/^\d{15}$/.test(d):case/^\d{2}-\d{6}-\d{6}-\d{1}$/.test(d):case/^\d{2}\s\d{6}\s\d{6}\s\d{1}$/.test(d):return d=d.replace(/[^0-9]/g,""),a.fn.bootstrapValidator.helpers.luhn(d);case/^\d{14}$/.test(d):case/^\d{16}$/.test(d):case/^\d{2}-\d{6}-\d{6}(|-\d{2})$/.test(d):case/^\d{2}\s\d{6}\s\d{6}(|\s\d{2})$/.test(d):return!0;default:return!1}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.integer={enableByHtml5:function(a){return"number"==a.attr("type")},validate:function(a,b){var c=b.val();return""==c?!0:/^(?:-?(?:0|[1-9][0-9]*))$/.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.ip={html5Attributes:{message:"message",ipv4:"ipv4",ipv6:"ipv6"},validate:function(b,c,d){var e=c.val();return""==e?!0:(d=a.extend({},{ipv4:!0,ipv6:!0},d),d.ipv4?/^(?:(?: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(e):d.ipv6?/^\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(str):!1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.isbn={validate:function(a,b){var c=b.val();if(""==c)return!0;var d;switch(!0){case/^\d{9}[\dX]$/.test(c):case 13==c.length&&/^(\d+)-(\d+)-(\d+)-([\dX])$/.test(c):case 13==c.length&&/^(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(c):d="ISBN10";break;case/^(978|979)\d{9}[\dX]$/.test(c):case 17==c.length&&/^(978|979)-(\d+)-(\d+)-(\d+)-([\dX])$/.test(c):case 17==c.length&&/^(978|979)\s(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(c):d="ISBN13";break;default:return!1}c=c.replace(/[^0-9X]/gi,"");var e,f=c.split(""),g=f.length,h=0;switch(d){case"ISBN10":h=0;for(var i=0;g-1>i;i++)h+=(10-i)*parseInt(f[i]);return e=11-h%11,11==e?e=0:10==e&&(e="X"),e+""==f[g-1];case"ISBN13":h=0;for(var i=0;g-1>i;i++)h+=i%2==0?parseInt(f[i]):3*parseInt(f[i]);return e=10-h%10,10==e&&(e="0"),e+""==f[g-1];default:return!1}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.isin={COUNTRY_CODES:"AF|AX|AL|DZ|AS|AD|AO|AI|AQ|AG|AR|AM|AW|AU|AT|AZ|BS|BH|BD|BB|BY|BE|BZ|BJ|BM|BT|BO|BQ|BA|BW|BV|BR|IO|BN|BG|BF|BI|KH|CM|CA|CV|KY|CF|TD|CL|CN|CX|CC|CO|KM|CG|CD|CK|CR|CI|HR|CU|CW|CY|CZ|DK|DJ|DM|DO|EC|EG|SV|GQ|ER|EE|ET|FK|FO|FJ|FI|FR|GF|PF|TF|GA|GM|GE|DE|GH|GI|GR|GL|GD|GP|GU|GT|GG|GN|GW|GY|HT|HM|VA|HN|HK|HU|IS|IN|ID|IR|IQ|IE|IM|IL|IT|JM|JP|JE|JO|KZ|KE|KI|KP|KR|KW|KG|LA|LV|LB|LS|LR|LY|LI|LT|LU|MO|MK|MG|MW|MY|MV|ML|MT|MH|MQ|MR|MU|YT|MX|FM|MD|MC|MN|ME|MS|MA|MZ|MM|NA|NR|NP|NL|NC|NZ|NI|NE|NG|NU|NF|MP|NO|OM|PK|PW|PS|PA|PG|PY|PE|PH|PN|PL|PT|PR|QA|RE|RO|RU|RW|BL|SH|KN|LC|MF|PM|VC|WS|SM|ST|SA|SN|RS|SC|SL|SG|SX|SK|SI|SB|SO|ZA|GS|SS|ES|LK|SD|SR|SJ|SZ|SE|CH|SY|TW|TJ|TZ|TH|TL|TG|TK|TO|TT|TN|TR|TM|TC|TV|UG|UA|AE|GB|US|UM|UY|UZ|VU|VE|VN|VG|VI|WF|EH|YE|ZM|ZW",validate:function(a,b){var c=b.val();if(""==c)return!0;c=c.toUpperCase();var d=new RegExp("^("+this.COUNTRY_CODES+")[0-9A-Z]{10}$");if(!d.test(c))return!1;for(var e="",f=c.length,g=0;f-1>g;g++){var h=c.charCodeAt(g);e+=h>57?(h-55).toString():c.charAt(g)}var i="",j=e.length,k=j%2!=0?0:1;for(g=0;j>g;g++)i+=parseInt(e[g])*(g%2==k?2:1)+"";var l=0;for(g=0;gh;h++)f+=parseInt(c.charAt(h))*g[h%2];return f=10-f%10,f==c.charAt(e-1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.issn={validate:function(a,b){var c=b.val();if(""==c)return!0;if(!/^\d{4}\-\d{3}[\dX]$/.test(c))return!1;c=c.replace(/[^0-9X]/gi,"");var d=c.split(""),e=d.length,f=0;"X"==d[7]&&(d[7]=10);for(var g=0;e>g;g++)f+=(8-g)*parseInt(d[g]);return f%11==0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.lessThan={html5Attributes:{message:"message",value:"value",inclusive:"inclusive"},enableByHtml5:function(a){var b=a.attr("max");return b?{value:b}:!1},validate:function(a,b,c){var d=b.val();return""==d?!0:(d=parseFloat(d),c.inclusive===!1?d<=c.value:d0:""!=a.trim(c.val())}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.numeric={html5Attributes:{message:"message",separator:"separator"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=c.separator||".";return"."!=e&&(d=d.replace(e,".")),!isNaN(parseFloat(d))&&isFinite(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.phone={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=(c.country||"US").toUpperCase();switch(e){case"US":default:return d=d.replace(/\D/g,""),/^(?:(1\-?)|(\+1 ?))?\(?(\d{3})[\)\-\.]?(\d{3})[\-\.]?(\d{4})$/.test(d)&&10==d.length}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.regexp={html5Attributes:{message:"message",regexp:"regexp"},enableByHtml5:function(a){var b=a.attr("pattern");return b?{regexp:b}:!1},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e="string"==typeof c.regexp?new RegExp(c.regexp):c.regexp;return e.test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.remote={html5Attributes:{message:"message",url:"url",name:"name"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=c.attr("data-bv-field"),g=d.data;null==g&&(g={}),"function"==typeof g&&(g=g.call(this,b)),g[d.name||f]=e;var h=new a.Deferred,i=a.ajax({type:"POST",url:d.url,dataType:"json",data:g});return i.then(function(a){h.resolve(c,"remote",a.valid===!0||"true"===a.valid)}),h.fail(function(){i.abort()}),h}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.rtn={validate:function(a,b){var c=b.val();if(""==c)return!0;if(!/^\d{9}$/.test(c))return!1;for(var d=0,e=0;eg;g++)d+=e[g]*parseInt(c.charAt(g),36);return d=(10-d%10)%10,d==c.charAt(f-1)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.siren={validate:function(b,c){var d=c.val();return""==d?!0:/^\d{9}$/.test(d)?a.fn.bootstrapValidator.helpers.luhn(d):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.siret={validate:function(a,b){var c=b.val();if(""==c)return!0;for(var d,e=0,f=c.length,g=0;f>g;g++)d=parseInt(c.charAt(g),10),g%2==0&&(d=2*d,d>9&&(d-=9)),e+=d;return e%10==0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.step={html5Attributes:{message:"message",base:"baseValue",step:"step"},validate:function(b,c,d){var e=c.val();if(""==e)return!0;if(d=a.extend({},{baseValue:0,step:1},d),e=parseFloat(e),isNaN(e)||!isFinite(e))return!1;var f=function(a,b){var c=Math.pow(10,b);a*=c;var d=a>0|-(0>a),e=a%1===.5*d;return e?(Math.floor(a)+(d>0))/c:Math.round(a)/c},g=function(a,b){if(0==b)return 1;var c=(a+"").split("."),d=(b+"").split("."),e=(1==c.length?0:c[1].length)+(1==d.length?0:d[1].length);return f(a-b*Math.floor(a/b),e)},h=g(e-d.baseValue,d.step);return 0==h||h==d.step}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringCase={html5Attributes:{message:"message","case":"case"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=(c["case"]||"lower").toLowerCase();switch(e){case"upper":return d===d.toUpperCase();case"lower":default:return d===d.toLowerCase()}}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.stringLength={html5Attributes:{message:"message",min:"min",max:"max"},enableByHtml5:function(a){var b=a.attr("maxlength");return b?{max:parseInt(b,10)}:!1},validate:function(b,c,d){var e=c.val();if(""==e)return!0;var f=a.trim(e).length;return d.min&&fd.max?!1:!0}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uri={enableByHtml5:function(a){return"url"==a.attr("type")},validate:function(a,b){var c=b.val();if(""==c)return!0;var d=new RegExp("^(?:(?:https?|ftp)://)(?:\\S+(?::\\S*)?@)?(?:(?!10(?:\\.\\d{1,3}){3})(?!127(?:\\.\\d{1,3}){3})(?!169\\.254(?:\\.\\d{1,3}){2})(?!192\\.168(?:\\.\\d{1,3}){2})(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))|(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*(?:\\.(?:[a-z\\u00a1-\\uffff]{2,})))(?::\\d{2,5})?(?:/[^\\s]*)?$","i");return d.test(c)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.uuid={html5Attributes:{message:"message",version:"version"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e={3:/^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,4:/^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,5:/^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,all:/^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i},f=c.version?c.version+"":"all";return null==e[f]?!0:e[f].test(d)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.vat={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d)return!0;var e=c.country||d.substr(0,2),f=["_",e.toLowerCase()].join("");return this[f]&&"function"==typeof this[f]?this[f](d):!0},_at:function(a){if(!/^ATU[0-9]{8}$/.test(a))return!1;a=a.substr(3);for(var b=0,c=[1,2,1,2,1,2,1],d=0,e=0;7>e;e++)d=parseInt(a.charAt(e))*c[e],d>9&&(d=Math.floor(d/10)+d%10),b+=d;return b=10-(b+4)%10,10==b&&(b=0),b==a.substr(7,1)},_be:function(a){if(!/^BE[0]{0,1}[0-9]{9}$/.test(a))return!1;if(a=a.substr(2),9==a.length&&(a="0"+a),0==a.substr(1,1))return!1;var b=parseInt(a.substr(0,8),10)+parseInt(a.substr(8,2),10);return b%97==0},_bg:function(b){if(!/^BG[0-9]{9,10}$/.test(b))return!1;b=b.substr(2);var c=0,d=0;if(9==b.length){for(d=0;8>d;d++)c+=parseInt(b.charAt(d))*(d+1);if(c%=11,10==c)for(c=0,d=0;8>d;d++)c+=parseInt(b.charAt(d))*(d+3);return c%=10,c==b.substr(8)}if(10==b.length){var e=function(b){var c=parseInt(b.substr(0,2),10)+1900,d=parseInt(b.substr(2,2),10),e=parseInt(b.substr(4,2),10);if(d>40?(c+=100,d-=40):d>20&&(c-=100,d-=20),!a.fn.bootstrapValidator.helpers.date(c,d,e))return!1;for(var f=0,g=[2,4,8,5,10,9,7,3,6],h=0;9>h;h++)f+=parseInt(b.charAt(h))*g[h];return f=f%11%10,f==b.substr(9,1)},f=function(a){for(var b=0,c=[21,19,17,13,11,9,7,3,1],d=0;9>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%=10,b==a.substr(9,1)},g=function(a){for(var b=0,c=[4,3,2,7,6,5,4,3,2],d=0;9>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,10==b?!1:(11==b&&(b=0),b==a.substr(9,1))};return e(b)||f(b)||g(b)}return!1},_ch:function(a){if(!/^CHE[0-9]{9}(MWST)?$/.test(a))return!1;a=a.substr(3);for(var b=0,c=[5,4,3,2,7,6,5,4],d=0;8>d;d++)b+=parseInt(a.charAt(d),10)*c[d];return b=11-b%11,10==b?!1:(11==b&&(b=0),b==a.substr(8,1))},_cy:function(a){if(!/^CY[0-5|9]{1}[0-9]{7}[A-Z]{1}$/.test(a))return!1;if(a=a.substr(2),"12"==a.substr(0,2))return!1;for(var b=0,c={0:1,1:0,2:5,3:7,4:9,5:13,6:15,7:17,8:19,9:21},d=0;8>d;d++){var e=parseInt(a.charAt(d),10);d%2==0&&(e=c[e+""]),b+=e}return b="ABCDEFGHIJKLMNOPQRSTUVWXYZ"[b%26],b==a.substr(8,1)},_cz:function(b){if(!/^CZ[0-9]{8,10}$/.test(b))return!1;b=b.substr(2);var c=0,d=0;if(8==b.length){if(b.charAt(0)+""=="9")return!1;for(c=0,d=0;7>d;d++)c+=parseInt(b.charAt(d),10)*(8-d);return c=11-c%11,10==c&&(c=0),11==c&&(c=1),c==b.substr(7,1)}if(9==b.length&&b.charAt(0)+""=="6"){for(c=0,d=0;7>d;d++)c+=parseInt(b.charAt(d+1),10)*(8-d);return c=11-c%11,10==c&&(c=0),11==c&&(c=1),c=[8,7,6,5,4,3,2,1,0,9,10][c-1],c==b.substr(8,1)}if(9==b.length||10==b.length){var e=1900+parseInt(b.substr(0,2)),f=parseInt(b.substr(2,2))%50%20,g=parseInt(b.substr(4,2));if(9==b.length){if(e>=1980&&(e-=100),e>1953)return!1}else 1954>e&&(e+=100);if(!a.fn.bootstrapValidator.helpers.date(e,f,g))return!1;if(10==b.length){var h=parseInt(b.substr(0,9),10)%11;return 1985>e&&(h%=10),h==b.substr(9,1)}return!0}return!1},_de:function(b){return/^DE[0-9]{9}$/.test(b)?(b=b.substr(2),a.fn.bootstrapValidator.helpers.mod_11_10(b)):!1},_dk:function(a){if(!/^DK[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[2,7,6,5,4,3,2,1],d=0;8>d;d++)b+=parseInt(a.charAt(d),10)*c[d];return b%11==0},_ee:function(a){if(!/^EE[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[3,7,1,3,7,1,3,7,1],d=0;9>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%10==0},_es:function(a){if(!/^ES[0-9A-Z][0-9]{7}[0-9A-Z]$/.test(a))return!1;a=a.substr(2);var b=function(a){var b=parseInt(a.substr(0,8),10);return b="TRWAGMYFPDXBNJZSQVHLCKE"[b%23],b==a.substr(8,1)},c=function(a){var b=["XYZ".indexOf(a.charAt(0)),a.substr(1)].join("");return b=parseInt(b,10),b="TRWAGMYFPDXBNJZSQVHLCKE"[b%23],b==a.substr(8,1)},d=function(a){var b,c=a.charAt(0);if(-1!="KLM".indexOf(c))return b=parseInt(a.substr(1,8),10),b="TRWAGMYFPDXBNJZSQVHLCKE"[b%23],b==a.substr(8,1);if(-1!="ABCDEFGHJNPQRSUVW".indexOf(c)){for(var d=0,e=[2,1,2,1,2,1,2],f=0,g=0;7>g;g++)f=parseInt(a.charAt(g+1))*e[g],f>9&&(f=Math.floor(f/10)+f%10),d+=f;return d=10-d%10,d==a.substr(8,1)||"JABCDEFGHI"[d]==a.substr(8,1)}return!1},e=a.charAt(0);return/^[0-9]$/.test(e)?b(a):/^[XYZ]$/.test(e)?c(a):d(a)},_fi:function(a){if(!/^FI[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[7,9,10,5,8,4,2,1],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%11==0},_fr:function(b){if(!/^FR[0-9A-Z]{2}[0-9]{9}$/.test(b))return!1;if(b=b.substr(2),!a.fn.bootstrapValidator.helpers.luhn(b.substr(2)))return!1;if(/^[0-9]{2}$/.test(b.substr(0,2)))return b.substr(0,2)==parseInt(b.substr(2)+"12",10)%97;var c,d="0123456789ABCDEFGHJKLMNPQRSTUVWXYZ";return c=/^[0-9]{1}$/.test(b.charAt(0))?24*d.indexOf(b.charAt(0))+d.indexOf(b.charAt(1))-10:34*d.indexOf(b.charAt(0))+d.indexOf(b.charAt(1))-100,(parseInt(b.substr(2),10)+1+Math.floor(c/11))%11==c%11},_gb:function(a){if(!(/^GB[0-9]{9}$/.test(a)||/^GB[0-9]{12}$/.test(a)||/^GBGD[0-9]{3}$/.test(a)||/^GBHA[0-9]{3}$/.test(a)||/^GB(GD|HA)8888[0-9]{5}$/.test(a)))return!1;a=a.substr(2);var b=a.length;if(5==b){var c=a.substr(0,2),d=parseInt(a.substr(2));return"GD"==c&&500>d||"HA"==c&&d>=500}if(11==b&&("GD8888"==a.substr(0,6)||"HA8888"==a.substr(0,6)))return"GD"==a.substr(0,2)&&parseInt(a.substr(6,3))>=500||"HA"==a.substr(0,2)&&parseInt(a.substr(6,3))<500?!1:parseInt(a.substr(6,3))%97==parseInt(a.substr(9,2));if(9==b||12==b){for(var e=0,f=[8,7,6,5,4,3,2,10,1],g=0;9>g;g++)e+=parseInt(a.charAt(g))*f[g];return e%=97,parseInt(a.substr(0,3))>=100?0==e||42==e||55==e:0==e}return!0},_gr:function(a){if(!/^GR[0-9]{9}$/.test(a))return!1;a=a.substr(2),8==a.length&&(a="0"+a);for(var b=0,c=[256,128,64,32,16,8,4,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=b%11%10,b==a.substr(8,1)},_el:function(a){return/^EL[0-9]{9}$/.test(a)?(a="GR"+a.substr(2),this._gr(a)):!1},_hu:function(a){if(!/^HU[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[9,7,3,1,9,7,3,1],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%10==0},_hr:function(b){return/^HR[0-9]{11}$/.test(b)?(b=b.substr(2),a.fn.bootstrapValidator.helpers.mod_11_10(b)):!1},_ie:function(a){if(!/^IE[0-9]{1}[0-9A-Z\*\+]{1}[0-9]{5}[A-Z]{1,2}$/.test(a))return!1;a=a.substr(2);var b=function(a){for(;a.length<7;)a="0"+a;for(var b="WABCDEFGHIJKLMNOPQRSTUV",c=0,d=0;7>d;d++)c+=parseInt(a.charAt(d))*(8-d);return c+=9*b.indexOf(a.substr(7)),b[c%23]};return/^[0-9]+$/.test(a.substr(0,7))?a.charAt(7)==b(a.substr(0,7)+a.substr(8)+""):-1!="ABCDEFGHIJKLMNOPQRSTUVWXYZ+*".indexOf(a.charAt(1))?a.charAt(7)==b(a.substr(2,5)+a.substr(0,1)+""):!0},_it:function(b){if(!/^IT[0-9]{11}$/.test(b))return!1;if(b=b.substr(2),0==parseInt(b.substr(0,7)))return!1;var c=parseInt(b.substr(7,3));return 1>c||c>201&&999!=c&&888!=c?!1:a.fn.bootstrapValidator.helpers.luhn(b)},_lt:function(a){if(!/^LT([0-9]{7}1[0-9]{1}|[0-9]{10}1[0-9]{1})$/.test(a))return!1;a=a.substr(2);for(var b=a.length,c=0,d=0;b-1>d;d++)c+=parseInt(a.charAt(d))*(1+d%9);var e=c%11;if(10==e){c=0;for(var d=0;b-1>d;d++)c+=parseInt(a.charAt(d))*(1+(d+2)%9)}return e=e%11%10,e==a.charAt(b-1)},_lu:function(a){return/^LU[0-9]{8}$/.test(a)?(a=a.substr(2),a.substr(0,6)%89==a.substr(6,2)):!1},_lv:function(b){if(!/^LV[0-9]{11}$/.test(b))return!1;b=b.substr(2);var c=parseInt(b.charAt(0)),d=0,e=[],f=0,g=b.length;if(c>3){for(d=0,e=[9,1,4,8,3,10,2,5,7,6,1],f=0;g>f;f++)d+=parseInt(b.charAt(f))*e[f];return d%=11,3==d}var h=parseInt(b.substr(0,2)),i=parseInt(b.substr(2,2)),j=parseInt(b.substr(4,2));if(j=j+1800+100*parseInt(b.charAt(6)),!a.fn.bootstrapValidator.helpers.date(j,i,h))return!1;for(d=0,e=[10,5,8,4,2,1,6,3,7,9],f=0;g-1>f;f++)d+=parseInt(b.charAt(f))*e[f];return d=(d+1)%11%10,d==b.charAt(g-1)},_mt:function(a){if(!/^MT[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[3,4,6,7,8,9,10,1],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%37==0},_nl:function(a){if(!/^NL[0-9]{9}B[0-9]{2}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[9,8,7,6,5,4,3,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%=11,b>9&&(b=0),b==a.substr(8,1)},_no:function(a){if(!/^NO[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[3,2,7,6,5,4,3,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,11==b&&(b=0),b==a.substr(8,1)},_pl:function(a){if(!/^PL[0-9]{10}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[6,5,7,2,3,4,5,6,7,-1],d=0;10>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%11==0},_pt:function(a){if(!/^PT[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[9,8,7,6,5,4,3,2],d=0;8>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,b>9&&(b=0),b==a.substr(8,1)},_ro:function(a){if(!/^RO[1-9][0-9]{1,9}$/.test(a))return!1;a=a.substr(2);for(var b=a.length,c=[7,5,3,2,1,7,5,3,2].slice(10-b),d=0,e=0;b-1>e;e++)d+=parseInt(a.charAt(e))*c[e];return d=10*d%11%10,d==a.substr(b-1,1)},_ru:function(a){if(!/^RU([0-9]{9}|[0-9]{12})$/.test(a))return!1;if(a=a.substr(2),10==a.length){for(var b=0,c=[2,4,10,3,5,9,4,6,8,0],d=0;10>d;d++)b+=parseInt(a.charAt(d))*c[d];return b%=11,b>9&&(b%=10),b==a.substr(9,1)}if(12==a.length){for(var e=0,f=[7,2,4,10,3,5,9,4,6,8,0],g=0,h=[3,7,2,4,10,3,5,9,4,6,8,0],d=0;11>d;d++)e+=parseInt(a.charAt(d))*f[d],g+=parseInt(a.charAt(d))*h[d];return e%=11,e>9&&(e%=10),g%=11,g>9&&(g%=10),e==a.substr(10,1)&&g==a.substr(11,1)}return!1},_rs:function(a){if(!/^RS[0-9]{9}$/.test(a))return!1;a=a.substr(2);for(var b=10,c=0,d=0;8>d;d++)c=(parseInt(a.charAt(d))+b)%10,0==c&&(c=10),b=2*c%11;return(b+parseInt(a.substr(8,1)))%10==1},_se:function(b){return/^SE[0-9]{10}01$/.test(b)?(b=b.substr(2,10),a.fn.bootstrapValidator.helpers.luhn(b)):!1},_si:function(a){if(!/^SI[0-9]{8}$/.test(a))return!1;a=a.substr(2);for(var b=0,c=[8,7,6,5,4,3,2],d=0;7>d;d++)b+=parseInt(a.charAt(d))*c[d];return b=11-b%11,10==b&&(b=0),b==a.substr(7,1)},_sk:function(a){return/^SK[1-9][0-9][(2-4)|(6-9)][0-9]{7}$/.test(a)?(a=a.substr(2),a%11==0):!1}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.vin={validate:function(a,b){var c=b.val();if(""==c)return!0;if(!/^[a-hj-npr-z0-9]{8}[0-9xX][a-hj-npr-z0-9]{8}$/i.test(c))return!1;c=c.toUpperCase();for(var d={A:1,B:2,C:3,D:4,E:5,F:6,G:7,H:8,J:1,K:2,L:3,M:4,N:5,P:7,R:9,S:2,T:3,U:4,V:5,W:6,X:7,Y:8,Z:9,1:1,2:2,3:3,4:4,5:5,6:6,7:7,8:8,9:9,0:0},e=[8,7,6,5,4,3,2,10,0,9,8,7,6,5,4,3,2],f=0,g=c.length,h=0;g>h;h++)f+=d[c.charAt(h)+""]*e[h];var i=f%11;return 10==i&&(i="X"),i==c.charAt(8)}}}(window.jQuery),function(a){a.fn.bootstrapValidator.validators.zipCode={html5Attributes:{message:"message",country:"country"},validate:function(a,b,c){var d=b.val();if(""==d||!c.country)return!0;var e=(c.country||"US").toUpperCase();switch(e){case"CA":return/(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}\s?[0-9]{1}(?:A|B|C|E|G|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}/i.test(d);case"DK":return/^(DK(-|\s)?)?\d{4}$/i.test(d);case"GB":return this._gb(d);case"IT":return/^(I-|IT-)?\d{5}$/i.test(d);case"NL":return/^[1-9][0-9]{3} ?(?!sa|sd|ss)[a-z]{2}$/i.test(d);case"SE":return/^(S-)?\d{3}\s?\d{2}$/i.test(d);case"US":default:return/^\d{4,5}([\-]\d{4})?$/.test(d)}},_gb:function(a){for(var b="[ABCDEFGHIJKLMNOPRSTUWYZ]",c="[ABCDEFGHKLMNOPQRSTUVWXY]",d="[ABCDEFGHJKPMNRSTUVWXY]",e="[ABEHMNPRVWXY]",f="[ABDEFGHJLNPQRSTUWXYZ]",g=[new RegExp("^("+b+"{1}"+c+"?[0-9]{1,2})(\\s*)([0-9]{1}"+f+"{2})$","i"),new RegExp("^("+b+"{1}[0-9]{1}"+d+"{1})(\\s*)([0-9]{1}"+f+"{2})$","i"),new RegExp("^("+b+"{1}"+c+"{1}?[0-9]{1}"+e+"{1})(\\s*)([0-9]{1}"+f+"{2})$","i"),new RegExp("^(BF1)(\\s*)([0-6]{1}[ABDEFGHJLNPQRST]{1}[ABDEFGHJLNPQRSTUWZYZ]{1})$","i"),/^(GIR)(\s*)(0AA)$/i,/^(BFPO)(\s*)([0-9]{1,4})$/i,/^(BFPO)(\s*)(c\/o\s*[0-9]{1,3})$/i,/^([A-Z]{4})(\s*)(1ZZ)$/i,/^(AI-2640)$/i],h=0;h