1/*! 2 * BootstrapValidator (http://bootstrapvalidator.com) 3 * The best jQuery plugin to validate form fields. Designed to use with Bootstrap 3 4 * 5 * @version v0.5.0, built on 2014-07-14 4:31:02 PM 6 * @author https://twitter.com/nghuuphuoc 7 * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc 8 * @license MIT 9 */ 10(function($) { 11 var BootstrapValidator = function(form, options) { 12 this.$form = $(form); 13 this.options = $.extend({}, $.fn.bootstrapValidator.DEFAULT_OPTIONS, options); 14 15 this.$invalidFields = $([]); // Array of invalid fields 16 this.$submitButton = null; // The submit button which is clicked to submit form 17 18 // Validating status 19 this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED'; 20 this.STATUS_VALIDATING = 'VALIDATING'; 21 this.STATUS_INVALID = 'INVALID'; 22 this.STATUS_VALID = 'VALID'; 23 24 // Determine the event that is fired when user change the field value 25 // Most modern browsers supports input event except IE 7, 8. 26 // IE 9 supports input event but the event is still not fired if I press the backspace key. 27 // Get IE version 28 // https://gist.github.com/padolsey/527683/#comment-7595 29 var ieVersion = (function() { 30 var v = 3, div = document.createElement('div'), a = div.all || []; 31 while (div.innerHTML = '<!--[if gt IE '+(++v)+']><br><![endif]-->', a[0]) {} 32 return v > 4 ? v : !v; 33 }()); 34 35 var el = document.createElement('div'); 36 this._changeEvent = (ieVersion === 9 || !('oninput' in el)) ? 'keyup' : 'input'; 37 38 // The flag to indicate that the form is ready to submit when a remote/callback validator returns 39 this._submitIfValid = null; 40 41 // Field elements 42 this._cacheFields = {}; 43 44 this._init(); 45 }; 46 47 BootstrapValidator.prototype = { 48 constructor: BootstrapValidator, 49 50 /** 51 * Init form 52 */ 53 _init: function() { 54 var that = this, 55 options = { 56 excluded: this.$form.attr('data-bv-excluded'), 57 trigger: this.$form.attr('data-bv-trigger'), 58 message: this.$form.attr('data-bv-message'), 59 container: this.$form.attr('data-bv-container'), 60 group: this.$form.attr('data-bv-group'), 61 submitButtons: this.$form.attr('data-bv-submitbuttons'), 62 threshold: this.$form.attr('data-bv-threshold'), 63 live: this.$form.attr('data-bv-live'), 64 onSuccess: this.$form.attr('data-bv-onsuccess'), 65 onError: this.$form.attr('data-bv-onerror'), 66 fields: {}, 67 feedbackIcons: { 68 valid: this.$form.attr('data-bv-feedbackicons-valid'), 69 invalid: this.$form.attr('data-bv-feedbackicons-invalid'), 70 validating: this.$form.attr('data-bv-feedbackicons-validating') 71 } 72 }; 73 74 this.$form 75 // Disable client side validation in HTML 5 76 .attr('novalidate', 'novalidate') 77 .addClass(this.options.elementClass) 78 // Disable the default submission first 79 .on('submit.bv', function(e) { 80 e.preventDefault(); 81 that.validate(); 82 }) 83 .on('click.bv', this.options.submitButtons, function() { 84 that.$submitButton = $(this); 85 // The user just click the submit button 86 that._submitIfValid = true; 87 }) 88 // Find all fields which have either "name" or "data-bv-field" attribute 89 .find('[name], [data-bv-field]') 90 .each(function() { 91 var $field = $(this), 92 field = $field.attr('name') || $field.attr('data-bv-field'), 93 opts = that._parseOptions($field); 94 if (opts) { 95 $field.attr('data-bv-field', field); 96 options.fields[field] = $.extend({}, opts, options.fields[field]); 97 } 98 }); 99 100 this.options = $.extend(true, this.options, options); 101 for (var field in this.options.fields) { 102 this._initField(field); 103 } 104 105 this.$form.trigger($.Event('init.form.bv'), { 106 bv: this, 107 options: this.options 108 }); 109 110 // Prepare the events 111 if (this.options.onSuccess) { 112 this.$form.on('success.form.bv', function(e) { 113 $.fn.bootstrapValidator.helpers.call(that.options.onSuccess, [e]); 114 }); 115 } 116 if (this.options.onError) { 117 this.$form.on('error.form.bv', function(e) { 118 $.fn.bootstrapValidator.helpers.call(that.options.onError, [e]); 119 }); 120 } 121 }, 122 123 /** 124 * Parse the validator options from HTML attributes 125 * 126 * @param {jQuery} $field The field element 127 * @returns {Object} 128 */ 129 _parseOptions: function($field) { 130 var field = $field.attr('name') || $field.attr('data-bv-field'), 131 validators = {}, 132 validator, 133 v, // Validator name 134 enabled, 135 optionName, 136 optionValue, 137 html5AttrName, 138 html5AttrMap; 139 140 for (v in $.fn.bootstrapValidator.validators) { 141 validator = $.fn.bootstrapValidator.validators[v]; 142 enabled = $field.attr('data-bv-' + v.toLowerCase()) + ''; 143 html5AttrMap = ('function' === typeof validator.enableByHtml5) ? validator.enableByHtml5($field) : null; 144 145 if ((html5AttrMap && enabled !== 'false') 146 || (html5AttrMap !== true && ('' === enabled || 'true' === enabled))) 147 { 148 // Try to parse the options via attributes 149 validator.html5Attributes = $.extend({}, { message: 'message', onerror: 'onError', onsuccess: 'onSuccess' }, validator.html5Attributes); 150 validators[v] = $.extend({}, html5AttrMap === true ? {} : html5AttrMap, validators[v]); 151 152 for (html5AttrName in validator.html5Attributes) { 153 optionName = validator.html5Attributes[html5AttrName]; 154 optionValue = $field.attr('data-bv-' + v.toLowerCase() + '-' + html5AttrName); 155 if (optionValue) { 156 if ('true' === optionValue) { 157 optionValue = true; 158 } else if ('false' === optionValue) { 159 optionValue = false;
160 } 161 validators[v][optionName] = optionValue; 162 } 163 } 164 } 165 } 166 167 var opts = { 168 excluded: $field.attr('data-bv-excluded'), 169 feedbackIcons: $field.attr('data-bv-feedbackicons'), 170 trigger: $field.attr('data-bv-trigger'), 171 message: $field.attr('data-bv-message'), 172 container: $field.attr('data-bv-container'), 173 group: $field.attr('data-bv-group'), 174 selector: $field.attr('data-bv-selector'), 175 threshold: $field.attr('data-bv-threshold'), 176 onStatus: $field.attr('data-bv-onstatus'), 177 onSuccess: $field.attr('data-bv-onsuccess'), 178 onError: $field.attr('data-bv-onerror'), 179 validators: validators 180 }, 181 emptyOptions = $.isEmptyObject(opts), // Check if the field options are set using HTML attributes 182 emptyValidators = $.isEmptyObject(validators); // Check if the field validators are set using HTML attributes 183 184 if (!emptyValidators || (!emptyOptions && this.options.fields && this.options.fields[field])) { 185 opts.validators = validators; 186 return opts; 187 } else { 188 return null; 189 } 190 }, 191 192 /** 193 * Init field 194 * 195 * @param {String|jQuery} field The field name or field element 196 */ 197 _initField: function(field) { 198 var fields = $([]); 199 switch (typeof field) { 200 case 'object': 201 fields = field; 202 field = field.attr('data-bv-field'); 203 break; 204 case 'string': 205 fields = this.getFieldElements(field); 206 fields.attr('data-bv-field', field); 207 break; 208 default: 209 break; 210 } 211 212 if (this.options.fields[field] === null || this.options.fields[field].validators === null) { 213 return; 214 } 215 216 // We don't need to validate non-existing fields 217 if (fields.length === 0) { 218 delete this.options.fields[field]; 219 return; 220 } 221 var validatorName; 222 for (validatorName in this.options.fields[field].validators) { 223 if (!$.fn.bootstrapValidator.validators[validatorName]) { 224 delete this.options.fields[field].validators[validatorName]; 225 } 226 } 227 if (this.options.fields[field].enabled === null) { 228 this.options.fields[field].enabled = true; 229 } 230 231 var that = this, 232 total = fields.length, 233 type = fields.attr('type'), 234 updateAll = (total === 1) || ('radio' === type) || ('checkbox' === type), 235 event = ('radio' === type || 'checkbox' === type || 'file' === type || 'SELECT' === fields.eq(0).get(0).tagName) ? 'change' : this._changeEvent, 236 trigger = (this.options.fields[field].trigger || this.options.trigger || event).split(' '), 237 events = $.map(trigger, function(item) { 238 return item + '.update.bv'; 239 }).join(' '); 240 241 for (var i = 0; i < total; i++) { 242 var $field = fields.eq(i), 243 group = this.options.fields[field].group || this.options.group, 244 $parent = $field.parents(group), 245 // Allow user to indicate where the error messages are shown 246 container = this.options.fields[field].container || this.options.container, 247 $message = (container && container !== 'tooltip' && container !== 'popover') ? $(container) : this._getMessageContainer($field, group); 248 249 if (container && container !== 'tooltip' && container !== 'popover') { 250 $message.addClass('has-danger'); 251 } 252 253 // Remove all error messages and feedback icons 254 $message.find('.help-block[data-bv-validator][data-bv-for="' + field + '"]').remove(); 255 $parent.find('i[data-bv-icon-for="' + field + '"]').remove(); 256 257 // Whenever the user change the field value, mark it as not val
257idated yet 258 $field.off(events).on(events, function() { 259 that.updateStatus($(this), that.STATUS_NOT_VALIDATED); 260 }); 261 262 // Create help block elements for showing the error messages 263 $field.data('bv.messages', $message); 264 for (validatorName in this.options.fields[field].validators) { 265 $field.data('bv.result.' + validatorName, this.STATUS_NOT_VALIDATED); 266 267 if (!updateAll || i === total - 1) { 268 $('<small/>') 269 .css('display', 'none') 270 .addClass('help-block') 271 .attr('data-bv-validator', validatorName) 272 .attr('data-bv-for', field) 273 .attr('data-bv-result', this.STATUS_NOT_VALIDATED) 274 .html(this._getMessage(field, validatorName)) 275 .appendTo($message); 276 } 277 278 // Prepare the validator events 279 if (this.options.fields[field].validators[validatorName].onSuccess) { 280 $field.on('success.validator.bv', function(e, data) { 281 $.fn.bootstrapValidator.helpers.call(that.options.fields[field].validators[validatorName].onSuccess, [e, data]); 282 }); 283 } 284 if (this.options.fields[field].validators[validatorName].onError) { 285 $field.on('error.validator.bv', function(e, data) { 286 $.fn.bootstrapValidator.helpers.call(that.options.fields[field].validators[validatorName].onError, [e, data]); 287 }); 288 } 289 } 290 291 // Prepare the feedback icons 292 // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation) 293 if (this.options.fields[field].feedbackIcons !== false && this.options.fields[field].feedbackIcons !== 'false' 294 && this.options.feedbackIcons 295 && this.options.feedbackIcons.validating && this.options.feedbackIcons.invalid && this.options.feedbackIcons.valid 296 && (!updateAll || i === total - 1)) 297 { 298 $parent.removeClass('has-success').removeClass('has-danger').addClass('has-feedback'); 299 var $icon = $('<i/>') 300 .css('display', 'none') 301 .addClass('form-control-feedback') 302 .attr('data-bv-icon-for', field) 303 // Place it after the label containing the checkbox/radio 304 // so when clicking the icon, it doesn't effect to the checkbox/radio element 305 .insertAfter(('checkbox' === type || 'radio' === type) ? $field.parent() : $field); 306 307 // The feedback icon does not render correctly if there is no label 308 // https://github.com/twbs/bootstrap/issues/12873 309 if ($parent.find('label').length === 0) { 310 $icon.css('top', 0); 311 } 312 // Fix feedback icons in input-group 313 if ($parent.find('.input-group').length !== 0) { 314 $icon.css({ 315 'top': 0, 316 'z-index': 100 317 }).insertAfter($parent.find('.input-group').eq(0)); 318 } 319 } 320 } 321 322 // Prepare the events 323 if (this.options.fields[field].onSuccess) { 324 fields.on('success.field.bv', function(e, data) { 325 $.fn.bootstrapValidator.helpers.call(that.options.fields[field].onSuccess, [e, data]); 326 }); 327 } 328 if (this.options.fields[field].onError) { 329 fields.on('error.field.bv', function(e, data) { 330 $.fn.bootstrapValidator.helpers.call(that.options.fields[field].onError, [e, data]); 331 }); 332 } 333 if (this.options.fields[field].onStatus) { 334 fields.on('status.field.bv', function(e, data) { 335 $.fn.bootstrapValidator.helpers.call(that.options.fields[field].onStatus, [e, data]); 336 }); 337 } 338 339 // Set live mode 340 events = $.map(trigger, function(item) { 341 return item + '.live.bv'; 342 }).join(' '); 343 switch (this.options.live) { 344 case 'submitted': 345 break; 346 case 'disabled': 347 fields.off(events); 348 break; 349 case 'enabled': 350 /* falls through */ 351 default: 352 fields.off(events).on(events, function() { 353 if (that._exceedThreshold($(this))) { 354 that.validateField($(this)); 355 } 356 }); 357 break; 358 } 359 360 fields.trigger($.Event('init.field.bv'), { 361 bv: this, 362 field: field, 363 element: fields 364 }); 365 }, 366 367 /** 368 * Get the error message for given field and validator 369 * 370 * @param {String} field The field name 371 * @param {String} validatorName The validator name 372 * @returns {String} 373 */ 374 _getMessage: function(field, validatorName) { 375 if (!this.options.fields[field] || !$.fn.bootstrapValidator.validators[validatorName] 376 || !this.options.fields[field].validators || !this.options.fields[field].validators[validatorName]) 377 { 378 return ''; 379 } 380 381 var options = this.options.fields[field].validators[validatorName]; 382 switch (true) { 383 case (!!options.message): 384 return options.message; 385 case (!!this.options.fields[field].message): 386 return this.options.fields[field].message; 387 case (!!$.fn.bootstrapValidator.i18n[validatorName]): 388 return $.fn.bootstrapValidator.i18n[validatorName]['default']; 389 default: 390 return this.options.message; 391 } 392 }, 393 394 /** 395 * Get the element to place the error messages 396 * 397 * @param {jQuery} $field The field element 398 * @param {String} group 399 * @returns {jQuery} 400 */ 401 _getMessageContainer: function($field, group) { 402 var $parent = $field.parent(); 403 if ($parent.is(group)) { 404 return $parent; 405 } 406
407 var cssClasses = $parent.attr('class'); 408 if (!cssClasses) { 409 return this._getMessageContainer($parent, group); 410 } 411 412 cssClasses = cssClasses.split(' '); 413 var n = cssClasses.length; 414 for (var i = 0; i < n; i++) { 415 if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i]) || /^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) { 416 return $parent; 417 } 418 } 419 420 return this._getMessageContainer($parent, group); 421 }, 422 423 /** 424 * Called when all validations are completed 425 */ 426 _submit: function() { 427 var isValid = this.isValid(), 428 eventType = isValid ? 'success.form.bv' : 'error.form.bv', 429 e = $.Event(eventType); 430 431 this.$form.trigger(e); 432 433 // Call default handler 434 // Check if whether the submit button is clicked 435 if (this.$submitButton) { 436 isValid ? this._onSuccess(e) : this._onError(e); 437 } 438 }, 439 440 /** 441 * Check if the field is excluded. 442 * Returning true means that the field will not be validated 443 * 444 * @param {jQuery} $field The field element 445 * @returns {Boolean} 446 */ 447 _isExcluded: function($field) { 448 var excludedAttr = $field.attr('data-bv-excluded'), 449 // I still need to check the 'name' attribute while initializing the field 450 field = $field.attr('data-bv-field') || $field.attr('name'); 451 452 switch (true) { 453 case (!!field && this.options.fields && this.options.fields[field] && (this.options.fields[field].excluded === 'true' || this.options.fields[field].excluded === true)): 454 case (excludedAttr === 'true'): 455 case (excludedAttr === ''): 456 return true; 457 458 case (!!field && this.options.fields && this.options.fields[field] && (this.options.fields[field].excluded === 'false' || this.options.fields[field].excluded === false)): 459 case (excludedAttr === 'false'): 460 return false; 461 462 default: 463 if (this.options.excluded) { 464 // Convert to array first 465 if ('string' === typeof this.options.excluded) { 466 this.options.excluded = $.map(this.options.excluded.split(','), function(item) { 467 // Trim the spaces 468 return $.trim(item); 469 }); 470 } 471 472 var length = this.options.excluded.length; 473 for (var i = 0; i < length; i++) { 474 if (('string' === typeof this.options.excluded[i] && $field.is(this.options.excluded[i])) 475 || ('function' === typeof this.options.excluded[i] && this.options.excluded[i].call(this, $field, this) === true)) 476 { 477 return true; 478 } 479 } 480 } 481 return false; 482 } 483 }, 484 485 /** 486 * Check if the number of characters of field value exceed the threshold or not 487 * 488 * @param {jQuery} $field The field element 489 * @returns {Boolean} 490 */ 491 _exceedThreshold: function($field) { 492 var field = $field.attr('data-bv-field'), 493 threshold = this.options.fields[field].threshold || this.options.threshold; 494 if (!threshold) { 495 return true; 496 } 497 var cannotType = $.inArray($field.attr('type'), ['button', 'checkbox', 'file', 'hidden', 'image', 'radio', 'reset', 'submit']) !== -1; 498 return (cannotType || $field.val().length >= threshold); 499 }, 500 501 // --- 502 // Events 503 // --- 504 505 /** 506 * The default handler of error.form.bv event.
507 * It will be called when there is a invalid field 508 * 509 * @param {jQuery.Event} e The jQuery event object 510 */ 511 _onError: function(e) { 512 if (e.isDefaultPrevented()) { 513 return; 514 } 515 516 if ('submitted' === this.options.live) { 517 // Enable live mode 518 this.options.live = 'enabled'; 519 var that = this; 520 for (var field in this.options.fields) { 521 (function(f) { 522 var fields = that.getFieldElements(f); 523 if (fields.length) { 524 var type = $(fields[0]).attr('type'), 525 event = ('radio' === type || 'checkbox' === type || 'file' === type || 'SELECT' === $(fields[0]).get(0).tagName) ? 'change' : that._changeEvent, 526 trigger = that.options.fields[field].trigger || that.options.trigger || event, 527 events = $.map(trigger.split(' '), function(item) { 528 return item + '.live.bv'; 529 }).join(' '); 530 531 fields.off(events).on(events, function() { 532 if (that._exceedThreshold($(this))) { 533 that.validateField($(this)); 534 } 535 }); 536 } 537 })(field); 538 } 539 } 540 541 var $invalidField = this.$invalidFields.eq(0); 542 if ($invalidField) { 543 // Activate the tab containing the invalid field if exists 544 var $tabPane = $invalidField.parents('.tab-pane'), tabId; 545 if ($tabPane && (tabId = $tabPane.attr('id'))) { 546 $('a[href="#' + tabId + '"][data-toggle="tab"]').tab('show'); 547 } 548 549 // Focus to the first invalid field 550 $invalidField.focus(); 551 } 552 }, 553 554 /** 555 * The default handler of success.form.bv event. 556 * It will be called when all the fields are valid 557 * 558 * @param {jQuery.Event} e The jQuery event object 559 */ 560 _onSuccess: function(e) { 561 if (e.isDefaultPrevented()) { 562 return; 563 } 564 565 // Submit the form 566 this.disableSubmitButtons(true).defaultSubmit(); 567 }, 568 569 /** 570 * Called after validating a field element 571 * 572 * @param {jQuery} $field The field element 573 * @param {String} [validatorName] The validator name 574 */ 575 _onFieldValidated: function($field, validatorName) { 576 var field = $field.attr('data-bv-field'), 577 validators = this.options.fields[field].validators, 578 counter = {}, 579 numValidators = 0, 580 data = { 581 bv: this, 582 field: field, 583 element: $field, 584 validator: validatorName 585 }; 586 587 // Trigger an event after given validator completes 588 if (validatorName) { 589 switch ($field.data('bv.result.' + validatorName)) { 590 case this.STATUS_INVALID: 591 $field.trigger($.Event('error.validator.bv'), data); 592 break; 593 case this.STATUS_VALID: 594 $field.trigger($.Event('success.validator.bv'), data); 595 break; 596 default: 597 break; 598 } 599 } 600 601 counter[this.STATUS_NOT_VALIDATED] = 0; 602 counter[this.STATUS_VALIDATING] = 0; 603 counter[this.STATUS_INVALID] = 0; 604 counter[this.STATUS_VALID] = 0; 605 606 for (var v in validators) { 607 if (validators[v].enabled === false) { 608 continue; 609 } 610 611 numValidators++; 612 var result = $field.data('bv.result.' + v); 613 if (result) { 614 counter[result]++; 615 } 616 } 617 618 if (counter[this.STATUS_VALID] === numValidators) { 619 // Remove from the list of invalid fields 620 this.$invalidFields = this.$invalidFields.not($field); 621 622 $field.trigger($.Event('success.field.bv'), data); 623 } 624 // If all validators are completed and there is at least one validator which doesn't pass 625 else if (counter[this.STATUS_NOT_VALIDATED] === 0 && counter[this.STATUS_VALIDATING] === 0 && counter[this.STATUS_INVALID] > 0) { 626 // Add to the list of invalid fields 627 this.$invalidFields = this.$invalidFields.add($field); 628 629 $field.trigger($.Event('error.field.bv'), data); 630 } 631 }, 632 633 // --- 634 // Public methods 635 // --- 636 637 /** 638 * Retrieve the field elements by given name 639 * 640 * @param {String} field The field name 641 * @returns {null|jQuery[]} 642 */ 643 getFieldElements: function(field) { 644 if (!this._cacheFields[field]) { 645 this._cacheFields[field] = (this.options.fields[field] && this.options.fields[field].selector) 646 ? $(this.options.fields[field].selector) 647 : this.$form.find('[name="' + field + '"]'); 648 } 649 650 return this._cacheFields[field]; 651 }, 652 653 /** 654 * Disable/enable submit buttons 655 * 656 * @param {Boolean} disabled Can be true or false 657 * @returns {BootstrapValidator} 658 */ 659 disableSubmitButtons: function(disabled) { 660 if (!disabled) { 661 this.$form.find(this.options.submitButtons).removeAttr('disabled'); 662 } else if (this.options.live !== 'disabled') { 663 // Don't disable if the live validating mode is disabled 664 this.$form.find(this.options.submitButtons).attr('disabled', 'disabled'); 665 } 666 667 return this; 668 }, 669 670 /** 671 * Validate the form 672 * 673 * @returns {BootstrapValidator} 674 */ 675 validate: function() { 676 if (!this.options.fields) { 677 return this; 678 } 679 this.disableSubmitButtons(true); 680 681 for (var field in this.options.fields) { 682 this.validateField(field); 683 } 684 685 this._submit(); 686 687 return this; 688 }, 689 690 /** 691 * Validate given field 692 * 693 * @param {String|jQuery} field The field name or field element 694 * @returns {BootstrapValidator} 695 */ 696 validateField: function(field) { 697 var fields = $([]); 698 switch (typeof field) { 699 case 'object': 700 fields = field; 701 field = field.attr('data-bv-field'); 702 break; 703 case 'string': 704 fields = this.getFieldElements(field); 705 break; 706 default: 707 break; 708 } 709 710 if (this.options.fields[field] && this.options.fields[field].enabled === false) { 711 return this; 712 } 713 714 var that = this, 715 type = fields.attr('type'), 716 total = ('radio' === type || 'checkbox' === type) ? 1 : fields.length, 717 updateAll = ('radio' === type || 'checkbox' === type), 718 validators = this.options.fields[field].validators, 719 validatorName, 720 validateResult; 721 722 for (var i = 0; i < total; i++) { 723 var $field = fields.eq(i); 724 if (this._isExcluded($field)) { 725 continue; 726 } 727 728 for (validatorName in validators) { 729 if ($field.data('bv.dfs.' + validatorName)) { 730 $field.data('bv.dfs.' + validatorName).reject(); 731 } 732 733 // Don't validate field if it is already done 734 var result = $field.data('bv.result.' + validatorName); 735 if (result === this.STATUS_VALID || result === this.STATUS_INVALID || validators[validatorName].enabled === false) { 736 this._onFieldValidated($field, validatorName); 737 continue; 738 } 739 740 $field.data('bv.result.' + validatorName, this.STATUS_VALIDATING); 741 validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]); 742 743 // validateResult can be a $.Deferred object ... 744 if ('object' === typeof validateResult && validateResult.resolve) { 745 this.updateStatus(updateAll ? field : $field, this.STATUS_VALIDATING, validatorName); 746 $field.data('bv.dfs.' + validatorName, validateResult); 747 748 validateResult.done(function($f, v, isValid, message) { 749 // v is validator name 750 $f.removeData('bv.dfs.' + v); 751 if (message) { 752 that.updateMessage($f, v, message); 753 } 754 755 that.updateStatus(updateAll ? $f.attr('data-bv-field') : $f, isValid ? that.STATUS_VALID : that.STATUS_INVALID, v); 756 757 if (isValid && that._submitIfValid === true) { 758 // If a remote validator returns true and the form is ready to submit, then do it 759 that._submit(); 760 } 761 }); 762 }
763 // ... or object { valid: true/false, message: 'dynamic message' } 764 else if ('object' === typeof validateResult && validateResult.valid !== undefined && validateResult.message !== undefined) { 765 this.updateMessage(updateAll ? field : $field, validatorName, validateResult.message); 766 this.updateStatus(updateAll ? field : $field, validateResult.valid ? this.STATUS_VALID : this.STATUS_INVALID, validatorName); 767 } 768 // ... or a boolean value 769 else if ('boolean' === typeof validateResult) { 770 this.updateStatus(updateAll ? field : $field, validateResult ? this.STATUS_VALID : this.STATUS_INVALID, validatorName); 771 } 772 } 773 } 774 775 return this; 776 }, 777 778 /** 779 * Update the error message 780 * 781 * @param {String|jQuery} field The field name or field element 782 * @param {String} validator The validator name 783 * @param {String} message The message 784 * @returns {BootstrapValidator} 785 */ 786 updateMessage: function(field, validator, message) { 787 var $fields = $([]); 788 switch (typeof field) { 789 case 'object': 790 $fields = field; 791 field = field.attr('data-bv-field'); 792 break; 793 case 'string': 794 $fields = this.getFieldElements(field); 795 break; 796 default: 797 break; 798 } 799 800 $fields.each(function() { 801 $(this).data('bv.messages').find('.help-block[data-bv-validator="' + validator + '"][data-bv-for="' + field + '"]').html(message); 802 }); 803 }, 804 805 /** 806 * Update all validating results of field 807 * 808 * @param {String|jQuery} field The field name or field element 809 * @param {String} status The status. Can be 'NOT_VALIDATED', 'VALIDATING', 'INVALID' or 'VALID' 810 * @param {String} [validatorName] The validator name. If null, the method updates validity result for all validators 811 * @returns {BootstrapValidator} 812 */ 813 updateStatus: function(field, status, validatorName) { 814 var fields = $([]); 815 switch (typeof field) { 816 case 'object': 817 fields = field; 818 field = field.attr('data-bv-field'); 819 break; 820 case 'string': 821 fields = this.getFieldElements(field); 822 break; 823 default: 824 break; 825 } 826 827 if (status === this.STATUS_NOT_VALIDATED) { 828 // Reset the flag 829 this._submitIfValid = false; 830 } 831 832 var that = this, 833 type = fields.attr('type'), 834 group = this.options.fields[field].group || this.options.group, 835 total = ('radio' === type || 'checkbox' === type) ? 1 : fields.length; 836 837 for (var i = 0; i < total; i++) { 838 var $field = fields.eq(i); 839 if (this._isExcluded($field)) { 840 continue; 841 } 842 843 var $parent = $field.parents(group), 844 $message = $field.data('bv.messages'), 845 $allErrors = $message.find('.help-block[data-bv-validator][data-bv-for="' + field + '"]'), 846 $errors = validatorName ? $allErrors.filter('[data-bv-validator="' + validatorName + '"]') : $allErrors, 847 $icon = $parent.find('.form-control-feedback[data-bv-icon-for="' + field + '"]'), 848 container = this.options.fields[field].container || this.options.container, 849 isValidField = null; 850 851 // Update status 852 if (validatorName) { 853 $field.data('bv.result.' + validatorName, status); 854 } else { 855 for (var v in this.options.fields[field].validators) { 856 $field.data('bv.result.' + v, status); 857 } 858 } 859 860 // Show/hide error elements and feedback icons 861 $errors.attr('data-bv-result', status); 862 863 // Determine the tab containing the element 864 var $tabPane = $field.parents('.tab-pane'), 865 tabId, $tab; 866 if ($tabPane && (tabId = $tabPane.attr('id'))) { 867 $tab = $('a[href="#' + tabId + '"][data-toggle="tab"]').parent(); 868 } 869 870 switch (status) { 871 case this.STATUS_VALIDATING: 872 isValidField = null; 873 this.disableSubmitButtons(true); 874 $parent.removeClass('has-success').removeClass('has-danger'); 875 if ($icon) { 876 $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).addClass(this.options.feedbackIcons.validating).show(); 877 } 878 if ($tab) { 879 $tab.removeClass('bv-tab-success').removeClass('bv-tab-error'); 880 } 881 break; 882 883 case this.STATUS_INVALID: 884 isValidField = false;
885 this.disableSubmitButtons(true); 886 $parent.removeClass('has-success').addClass('has-danger'); 887 if ($icon) { 888 $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.validating).addClass(this.options.feedbackIcons.invalid).show(); 889 } 890 if ($tab) { 891 $tab.removeClass('bv-tab-success').addClass('bv-tab-error'); 892 } 893 break; 894 895 case this.STATUS_VALID: 896 // If the field is valid (passes all validators) 897 isValidField = ($allErrors.filter('[data-bv-result="' + this.STATUS_NOT_VALIDATED +'"]').length === 0) 898 ? ($allErrors.filter('[data-bv-result="' + this.STATUS_VALID +'"]').length === $allErrors.length) // All validators are completed 899 : null; // There are some validators that have not done 900 if (isValidField !== null) { 901 this.disableSubmitButtons(this.$submitButton ? !this.isValid() : !isValidField); 902 if ($icon) { 903 $icon 904 .removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).removeClass(this.options.feedbackIcons.valid) 905 .addClass(isValidField ? this.options.feedbackIcons.valid : this.options.feedbackIcons.invalid) 906 .show(); 907 } 908 } 909 910 $parent.removeClass('has-danger has-success').addClass(this.isValidContainer($parent) ? 'has-success' : 'has-danger'); 911 if ($tab) { 912 $tab.removeClass('bv-tab-success').removeClass('bv-tab-error').addClass(this.isValidContainer($tabPane) ? 'bv-tab-success' : 'bv-tab-error'); 913 } 914 break; 915 916 case this.STATUS_NOT_VALIDATED: 917 /* falls through */ 918 default: 919 isValidField = null; 920 this.disableSubmitButtons(false); 921 $parent.removeClass('has-success').removeClass('has-danger'); 922 if ($icon) { 923 $icon.removeClass(this.options.feedbackIcons.valid).removeClass(this.options.feedbackIcons.invalid).removeClass(this.options.feedbackIcons.validating).hide(); 924 } 925 if ($tab) { 926 $tab.removeClass('bv-tab-success').removeClass('bv-tab-error'); 927 } 928 break; 929 } 930 931 switch (true) { 932 // Only show the first error message if it is placed inside a tooltip ... 933 case ($icon && 'tooltip' === container): 934 (isValidField === false) 935 ? $icon.css('cursor', 'pointer').tooltip('destroy').tooltip({ 936 html: true, 937 placement: 'top', 938 title: $allErrors.filter('[data-bv-result="' + that.STATUS_INVALID + '"]').eq(0).html() 939 }) 940 : $icon.css('cursor', '').tooltip('destroy'); 941 break; 942 // ... or popover 943 case ($icon && 'popover' === container): 944 (isValidField === false) 945 ? $icon.css('cursor', 'pointer').popover('destroy').popover({ 946 content: $allErrors.filter('[data-bv-result="' + that.STATUS_INVALID + '"]').eq(0).html(), 947 html: true, 948 placement: 'top', 949 trigger: 'hover click' 950 }) 951 : $icon.css('cursor', '').popover('destroy'); 952 break; 953 default: 954 (status === this.STATUS_INVALID) ? $errors.show() : $errors.hide(); 955 break; 956 } 957 958 // Trigger an event 959 $field.trigger($.Event('status.field.bv'), { 960 bv: this, 961 field: field, 962 element: $field, 963 status: status 964 }); 965 this._onFieldValidated($field, validatorName); 966 } 967 968 return this; 969 }, 970 971 /** 972 * Check the form validity 973 * 974 * @returns {Boolean} 975 */ 976 isValid: function() { 977 for (var field in this.options.fields) { 978 if (!this.isValidField(field)) { 979 return false;
980 } 981 } 982 983 return true; 984 }, 985 986 /** 987 * Check if the field is valid or not 988 * 989 * @param {String|jQuery} field The field name or field element 990 * @returns {Boolean} 991 */ 992 isValidField: function(field) { 993 var fields = $([]); 994 switch (typeof field) { 995 case 'object': 996 fields = field; 997 field = field.attr('data-bv-field'); 998 break; 999 case 'string': 1000 fields = this.getFieldElements(field); 1001 break; 1002 default: 1003 break; 1004 } 1005 if (fields.length === 0 || this.options.fields[field] === null || this.options.fields[field].enabled === false) { 1006 return true; 1007 } 1008 1009 var type = fields.attr('type'), 1010 total = ('radio' === type || 'checkbox' === type) ? 1 : fields.length, 1011 $field, validatorName, status; 1012 for (var i = 0; i < total; i++) { 1013 $field = fields.eq(i); 1014 if (this._isExcluded($field)) { 1015 continue; 1016 } 1017 1018 for (validatorName in this.options.fields[field].validators) { 1019 if (this.options.fields[field].validators[validatorName].enabled === false) { 1020 continue; 1021 } 1022 1023 status = $field.data('bv.result.' + validatorName); 1024 if (status !== this.STATUS_VALID) { 1025 return false; 1026 } 1027 } 1028 } 1029 1030 return true; 1031 }, 1032 1033 /** 1034 * Check if all fields inside a given container are valid. 1035 * It's useful when working with a wizard-like such as tab, collapse 1036 * 1037 * @param {String|jQuery} container The container selector or element 1038 * @returns {Boolean} 1039 */ 1040 isValidContainer: function(container) { 1041 var that = this, 1042 map = {}, 1043 $container = ('string' === typeof container) ? $(container) : container; 1044 if ($container.length === 0) { 1045 return true; 1046 } 1047 1048 $container.find('[data-bv-field]').each(function() { 1049 var $field = $(this), 1050 field = $field.attr('data-bv-field'); 1051 if (!that._isExcluded($field) && !map[field]) { 1052 map[field] = $field; 1053 } 1054 }); 1055 1056 for (var field in map) { 1057 var $f = map[field]; 1058 if ($f.data('bv.messages') 1059 .find('.help-block[data-bv-validator][data-bv-for="' + field + '"]') 1060 .filter(function() { 1061 var v = $(this).attr('data-bv-validator'), 1062 f = $(this).attr('data-bv-for'); 1063 return (that.options.fields[f].validators[v].enabled !== false 1064 && $f.data('bv.result.' + v) && $f.data('bv.result.' + v) !== that.STATUS_VALID); 1065 }) 1066 .length !== 0) 1067 { 1068 // The field is not valid 1069 return false; 1070 } 1071 } 1072 1073 return true; 1074 }, 1075 1076 /** 1077 * Submit the form using default submission. 1078 * It also does not perform any validations when submitting the form 1079 */ 1080 defaultSubmit: function() { 1081 if (this.$submitButton) { 1082 // Create hidden input to send the submit buttons 1083 $('<input/>') 1084 .attr('type', 'hidden') 1085 .attr('data-bv-submit-hidden', '') 1086 .attr('name', this.$submitButton.attr('name')) 1087 .val(this.$submitButton.val()) 1088 .appendTo(this.$form); 1089 } 1090 1091 // Submit form 1092 this.$form.off('submit.bv').submit(); 1093 }, 1094 1095 // --- 1096 // Useful APIs which aren't used internally 1097 // --- 1098 1099 /** 1100 * Get the list of invalid fields 1101 * 1102 * @returns {jQuery[]} 1103 */ 1104 getInvalidFields: function() { 1105 return this.$invalidFields; 1106 }, 1107 1108 /** 1109 * Returns the clicked submit button 1110 * 1111 * @returns {jQuery} 1112 */ 1113 getSubmitButton: function() { 1114 return this.$submitButton; 1115 }, 1116 1117 /** 1118 * Get the error messages 1119 * 1120 * @param {String|jQuery} [field] The field name or field element 1121 * If the field is not defined, the method returns all error messages of all fields 1122 * @param {String} [validator] The name of validator 1123 * If the validator is not defined, the method returns error messages of all validators 1124 * @returns {String[]} 1125 */ 1126 getMessages: function(field, validator) { 1127 var that = this, 1128 messages = [], 1129 $fields = $([]); 1130 1131 switch (true) { 1132 case (field && 'object' === typeof field): 1133 $fields = field; 1134 break; 1135 case (field && 'string' === typeof field): 1136 var f = this.getFieldElements(field); 1137 if (f.length > 0) { 1138 var type = f.attr('type'); 1139 $fields = ('radio' === type || 'checkbox' === type) ? f.eq(0) : f; 1140 } 1141 break; 1142 default: 1143 $fields = this.$invalidFields; 1144 break; 1145 } 1146 1147 var filter = validator ? '[data-bv-validator="' + validator + '"]' : ''; 1148 $fields.each(function() { 1149 messages = messages.concat( 1150 $(this) 1151 .data('bv.messages') 1152 .find('.help-block[data-bv-for="' + $(this).attr('data-bv-field') + '"][data-bv-result="' + that.STATUS_INVALID + '"]' + filter) 1153 .map(function() { 1154 var v = $(this).attr('data-bv-validator'), 1155 f = $(this).attr('data-bv-for'); 1156 return (that.options.fields[f].validators[v].enabled === false) ? '' : $(this).html(); 1157 }) 1158 .get() 1159 ); 1160 }); 1161 1162 return messages; 1163 }, 1164 1165 /** 1166 * Get the field options 1167 * 1168 * @param {String|jQuery} [field] The field name or field element. If it is not set, the method returns the form options 1169 * @param {String} [validator] The name of validator. It null, the method returns form options 1170 * @param {String} [option] The option name 1171 * @return {String|Object} 1172 */ 1173 getOptions: function(field, validator, option) { 1174 if (!field) { 1175 return this.options; 1176 } 1177 if ('object' === typeof field) { 1178 field = field.attr('data-bv-field'); 1179 } 1180 if (!this.options.fields[field]) { 1181 return null; 1182 } 1183 1184 var options = this.options.fields[field]; 1185 if (!validator) { 1186 return options; 1187 } 1188 if (!options.validators || !options.validators[validator]) { 1189 return null; 1190 } 1191 1192 return option ? options.validators[validator][option] : options.validators[validator]; 1193 }, 1194 1195 /** 1196 * Update the option of a specific validator 1197 * 1198 * @param {String|jQuery} field The field name or field element 1199 * @param {String} validator The validator name 1200 * @param {String} option The option name 1201 * @param {String} value The value to set 1202 * @returns {BootstrapValidator} 1203 */ 1204 updateOption: function(field, validator, option, value) { 1205 if ('object' === typeof field) { 1206 field = field.attr('data-bv-field'); 1207 } 1208 if (this.options.fields[field] && this.options.fields[field].validators[validator]) { 1209 this.options.fields[field].validators[validator][option] = value; 1210 this.updateStatus(field, this.STATUS_NOT_VALIDATED, validator); 1211 } 1212 1213 return this; 1214 }, 1215 1216 /** 1217 * Add a new field 1218 * 1219 * @param {String|jQuery} field The field name or field element 1220 * @param {Object} [options] The validator rules 1221 * @returns {BootstrapValidator} 1222 */ 1223 addField: function(field, options) { 1224 var fields = $([]); 1225 switch (typeof field) { 1226 case 'object': 1227 fields = field; 1228 field = field.attr('data-bv-field') || field.attr('name'); 1229 break; 1230 case 'string': 1231 delete this._cacheFields[field]; 1232 fields = this.getFieldElements(field); 1233 break; 1234 default: 1235 break; 1236 } 1237 1238 fields.attr('data-bv-field', field); 1239 1240 var type = fields.attr('type'), 1241 total = ('radio' === type || 'checkbox' === type) ? 1 : fields.length; 1242 1243 for (var i = 0; i < total; i++) { 1244 var $field = fields.eq(i); 1245 1246 // Try to parse the options from HTML attributes 1247 var opts = this._parseOptions($field); 1248 opts = (opts === null) ? options : $.extend(true, options, opts); 1249 1250 this.options.fields[field] = $.extend(true, this.options.fields[field], opts); 1251 1252 // Update the cache 1253 this._cacheFields[field] = this._cacheFields[field] ? this._cacheFields[field].add($field) : $field; 1254 1255 // Init the element 1256 this._initField(('checkbox' === type || 'radio' === type) ? field : $field); 1257 } 1258 1259 this.disableSubmitButtons(false); 1260 // Trigger an event 1261 this.$form.trigger($.Event('added.field.bv'), { 1262 field: field, 1263 element: fields, 1264 options: this.options.fields[field] 1265 }); 1266 1267 return this; 1268 }, 1269 1270 /** 1271 * Remove a given field 1272 * 1273 * @param {String|jQuery} field The field name or field element 1274 * @returns {BootstrapValidator} 1275 */ 1276 removeField: function(field) { 1277 var fields = $([]); 1278 switch (typeof field) { 1279 case 'object': 1280 fields = field; 1281 field = field.attr('data-bv-field') || field.attr('name'); 1282 fields.attr('data-bv-field', field); 1283 break; 1284 case 'string': 1285 fields = this.getFieldElements(field); 1286 break; 1287 default: 1288 break; 1289 } 1290 1291 if (fields.length === 0) { 1292 return this; 1293 } 1294 1295 var type = fields.attr('type'), 1296 total = ('radio' === type || 'checkbox' === type) ? 1 : fields.length; 1297 1298 for (var i = 0; i < total; i++) { 1299 var $field = fields.eq(i); 1300 1301 // Remove from the list of invalid fields 1302 this.$invalidFields = this.$invalidFields.not($field); 1303 1304 // Update the cache 1305 this._cacheFields[field] = this._cacheFields[field].not($field); 1306 } 1307 1308 if (!this._cacheFields[field] || this._cacheFields[field].length === 0) { 1309 delete this.options.fields[field]; 1310 }
1311 if ('checkbox' === type || 'radio' === type) { 1312 this._initField(field); 1313 } 1314 1315 this.disableSubmitButtons(false); 1316 // Trigger an event 1317 this.$form.trigger($.Event('removed.field.bv'), { 1318 field: field, 1319 element: fields 1320 }); 1321 1322 return this; 1323 }, 1324 1325 /** 1326 * Reset given field 1327 * 1328 * @param {String|jQuery} field The field name or field element 1329 * @param {Boolean} [resetValue] If true, the method resets field value to empty or remove checked/selected attribute (for radio/checkbox) 1330 * @returns {BootstrapValidator} 1331 */ 1332 resetField: function(field, resetValue) { 1333 var $fields = $([]); 1334 switch (typeof field) { 1335 case 'object': 1336 $fields = field; 1337 field = field.attr('data-bv-field'); 1338 break; 1339 case 'string': 1340 $fields = this.getFieldElements(field); 1341 break; 1342 default: 1343 break; 1344 } 1345 1346 var total = $fields.length; 1347 if (this.options.fields[field]) { 1348 for (var i = 0; i < total; i++) { 1349 for (var validator in this.options.fields[field].validators) { 1350 $fields.eq(i).removeData('bv.dfs.' + validator); 1351 } 1352 } 1353 } 1354
1355 // Mark field as not validated yet 1356 this.updateStatus(field, this.STATUS_NOT_VALIDATED); 1357 1358 if (resetValue) { 1359 var type = $fields.attr('type'); 1360 ('radio' === type || 'checkbox' === type) ? $fields.removeAttr('checked').removeAttr('selected') : $fields.val(''); 1361 } 1362 1363 return this; 1364 }, 1365 1366 /** 1367 * Reset the form 1368 * 1369 * @param {Boolean} [resetValue] If true, the method resets field value to empty or remove checked/selected attribute (for radio/checkbox) 1370 * @returns {BootstrapValidator} 1371 */ 1372 resetForm: function(resetValue) { 1373 for (var field in this.options.fields) { 1374 this.resetField(field, resetValue); 1375 } 1376 1377 this.$invalidFields = $([]); 1378 this.$submitButton = null; 1379 1380 // Enable submit buttons 1381 this.disableSubmitButtons(false); 1382 1383 return this; 1384 }, 1385 1386 /** 1387 * Revalidate given field 1388 * It's used when you need to revalidate the field which its value is updated by other plugin 1389 * 1390 * @param {String|jQuery} field The field name of field element 1391 * @returns {BootstrapValidator} 1392 */ 1393 revalidateField: function(field) { 1394 this.updateStatus(field, this.STATUS_NOT_VALIDATED) 1395 .validateField(field); 1396 1397 return this; 1398 }, 1399 1400 /** 1401 * Enable/Disable all validators to given field 1402 * 1403 * @param {String} field The field name 1404 * @param {Boolean} enabled Enable/Disable field validators 1405 * @param {String} [validatorName] The validator name. If null, all validators will be enabled/disabled 1406 * @returns {BootstrapValidator} 1407 */ 1408 enableFieldValidators: function(field, enabled, validatorName) { 1409 var validators = this.options.fields[field].validators; 1410 1411 // Enable/disable particular validator 1412 if (validatorName 1413 && validators 1414 && validators[validatorName] && validators[validatorName].enabled !== enabled) 1415 { 1416 this.options.fields[field].validators[validatorName].enabled = enabled; 1417 this.updateStatus(field, this.STATUS_NOT_VALIDATED, validatorName); 1418 } 1419 // Enable/disable all validators 1420 else if (!validatorName && this.options.fields[field].enabled !== enabled) { 1421 this.options.fields[field].enabled = enabled; 1422 for (var v in validators) { 1423 this.enableFieldValidators(field, enabled, v); 1424 } 1425 } 1426 1427 return this; 1428 }, 1429 1430 /** 1431 * Some validators have option which its value is dynamic. 1432 * For example, the zipCode validator has the country option which might be changed dynamically by a select element. 1433 * 1434 * @param {jQuery|String} field The field name or element 1435 * @param {String|Function} option The option which can be determined by: 1436 * - a string 1437 * - name of field which defines the value 1438 * - name of function which returns the value 1439 * - a function returns the value 1440 * 1441 * The callback function has the format of 1442 * callback: function(value, validator, $field) { 1443 * // value is the value of field 1444 * // validator is the BootstrapValidator instance 1445 * // $field is the field element 1446 * } 1447 * 1448 * @returns {String} 1449 */ 1450 getDynamicOption: function(field, option) { 1451 var $field = ('string' === typeof field) ? this.getFieldElements(field) : field, 1452 value = $field.val(); 1453 1454 // Option can be determined by 1455 // ... a function 1456 if ('function' === typeof option) { 1457 return $.fn.bootstrapValidator.helpers.call(option, [value, this, $field]); 1458 } 1459 // ... value of other field 1460 else if ('string' === typeof option) { 1461 var $f = this.getFieldElements(option); 1462 if ($f.length) { 1463 return $f.val(); 1464 } 1465 // ... return value of callback 1466 else { 1467 return $.fn.bootstrapValidator.helpers.call(option, [value, this, $field]); 1468 } 1469 } 1470 1471 return null; 1472 }, 1473 1474 /** 1475 * Destroy the plugin 1476 * It will remove all error messages, feedback icons and turn off the events 1477 */ 1478 destroy: function() { 1479 var field, fields, $field, validator, $icon, container, group; 1480 for (field in this.options.fields) { 1481 fields = this.getFieldElements(field); 1482 container = this.options.fields[field].container || this.options.container, 1483 group = this.options.fields[field].group || this.options.group; 1484 for (var i = 0; i < fields.length; i++) { 1485 $field = fields.eq(i); 1486 $field 1487 // Remove all error messages 1488 .data('bv.messages') 1489 .find('.help-block[data-bv-validator][data-bv-for="' + field + '"]').remove().end() 1490 .end() 1491 .removeData('bv.messages') 1492 // Remove feedback classes 1493 .parents(group) 1494 .removeClass('has-feedback has-danger has-success') 1495 .end() 1496 // Turn off events 1497 .off('.bv') 1498 .removeAttr('data-bv-field'); 1499 1500 // Remove feedback icons, tooltip/popover container 1501 $icon = $field.parents(group).find('i[data-bv-icon-for="' + field + '"]'); 1502 if ($icon) { 1503 switch (container) { 1504 case 'tooltip': 1505 $icon.tooltip('destroy').remove(); 1506 break; 1507 case 'popover': 1508 $icon.popover('destroy').remove(); 1509 break; 1510 default: 1511 $icon.remove(); 1512 break; 1513 } 1514 } 1515 1516 for (validator in this.options.fields[field].validators) { 1517 if ($field.data('bv.dfs.' + validator)) { 1518 $field.data('bv.dfs.' + validator).reject(); 1519 } 1520 $field.removeData('bv.result.' + validator).removeData('bv.dfs.' + validator); 1521 } 1522 } 1523 } 1524 1525 // Enable submit buttons 1526 this.disableSubmitButtons(false); 1527 1528 this.$form 1529 .removeClass(this.options.elementClass) 1530 .off('.bv') 1531 .removeData('bootstrapValidator') 1532 // Remove generated hidden elements 1533 .find('[data-bv-submit-hidden]').remove(); 1534 } 1535 }; 1536 1537 // Plugin definition 1538 $.fn.bootstrapValidator = function(option) { 1539 var params = arguments; 1540 return this.each(function() { 1541 var $this = $(this), 1542 data = $this.data('bootstrapValidator'), 1543 options = 'object' === typeof option && option; 1544 if (!data) { 1545 data = new BootstrapValidator(this, options); 1546 $this.data('bootstrapValidator', data); 1547 } 1548 1549 // Allow to call plugin method 1550 if ('string' === typeof option) { 1551 data[option].apply(data, Array.prototype.slice.call(params, 1)); 1552 } 1553 }); 1554 }; 1555 1556 // The default options 1557 $.fn.bootstrapValidator.DEFAULT_OPTIONS = { 1558 // The form CSS class 1559 elementClass: 'bv-form', 1560 1561 // Default invalid message
1562 message: 'This value is not valid', 1563 1564 // The CSS selector for indicating the element consists the field 1565 // By default, each field is placed inside the <div class="form-group"></div> 1566 // You should adjust this option if your form group consists of many fields which not all of them need to be validated 1567 group: '.form-group', 1568 1569 //The error messages container. It can be: 1570 // - 'tooltip' if you want to use Bootstrap tooltip to show error messages 1571 // - 'popover' if you want to use Bootstrap popover to show error messages 1572 // - a CSS selector indicating the container 1573 // In the first two cases, since the tooltip/popover should be small enough, the plugin only shows only one error message 1574 // You also can define the message container for particular field 1575 container: null, 1576 1577 // The field will not be live validated if its length is less than this number of characters 1578 threshold: null, 1579 1580 // Indicate fields which won't be validated 1581 // By default, the plugin will not validate the following kind of fields: 1582 // - disabled 1583 // - hidden 1584 // - invisible 1585 // 1586 // The setting consists of jQuery filters. Accept 3 formats: 1587 // - A string. Use a comma to separate filter 1588 // - An array. Each element is a filter 1589 // - An array. Each element can be a callback function 1590 // function($field, validator) { 1591 // $field is jQuery object representing the field element 1592 // validator is the BootstrapValidator instance 1593 // return true or false; 1594 // } 1595 // 1596 // The 3 following settings are equivalent: 1597 // 1598 // 1) ':disabled, :hidden, :not(:visible)' 1599 // 2) [':disabled', ':hidden', ':not(:visible)'] 1600 // 3) [':disabled', ':hidden', function($field) { 1601 // return !$field.is(':visible'); 1602 // }] 1603 excluded: [':disabled', ':hidden', ':not(:visible)'], 1604 1605 // Shows ok/error/loading icons based on the field validity. 1606 // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation). 1607 // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically. 1608 // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later. 1609 // 1610 // Examples: 1611 // - Use Glyphicons icons: 1612 // feedbackIcons: { 1613 // valid: 'glyphicon glyphicon-ok', 1614 // invalid: 'glyphicon glyphicon-remove', 1615 // validating: 'glyphicon glyphicon-refresh' 1616 // } 1617 // - Use FontAwesome icons: 1618 // feedbackIcons: { 1619 // valid: 'fa fa-check', 1620 // invalid: 'fa fa-times', 1621 // validating: 'fa fa-refresh' 1622 // } 1623 feedbackIcons: { 1624 valid: null, 1625 invalid: null, 1626 validating: null 1627 }, 1628 1629 // The submit buttons selector 1630 // These buttons will be disabled to prevent the valid form from multiple submissions 1631 submitButtons: '[type="submit"]', 1632 1633 // Live validating option 1634 // Can be one of 3 values: 1635 // - enabled: The plugin validates fields as soon as they are changed 1636 // - disabled: Disable the live validating. The error messages are only shown after the form is submitted 1637 // - submitted: The live validating is enabled after the form is submitted 1638 live: 'enabled', 1639 1640 // Map the field name with validator rules 1641 fields: null 1642 }; 1643 1644 // Available validators 1645 $.fn.bootstrapValidator.validators = {}; 1646 1647 // i18n 1648 $.fn.bootstrapValidator.i18n = {}; 1649 1650 $.fn.bootstrapValidator.Constructor = BootstrapValidator; 1651 1652 // Helper methods, which can be used in validator class 1653 $.fn.bootstrapValidator.helpers = { 1654 /** 1655 * Execute a callback function 1656 * 1657 * @param {String|Function} functionName Can be 1658 * - name of global function 1659 * - name of namespace function (such as A.B.C) 1660 * - a function 1661 * @param {Array} args The callback arguments 1662 */ 1663 call: function(functionName, args) { 1664 if ('function' === typeof functionName) { 1665 return functionName.apply(this, args); 1666 } else if ('string' === typeof functionName) { 1667 if ('()' === functionName.substring(functionName.length - 2)) { 1668 functionName = functionName.substring(0, functionName.length - 2); 1669 } 1670 var ns = functionName.split('.'), 1671 func = ns.pop(), 1672 context = window; 1673 for (var i = 0; i < ns.length; i++) { 1674 context = context[ns[i]]; 1675 } 1676 return context[func].apply(this, args); 1677 } 1678 }, 1679 1680 /** 1681 * Format a string 1682 * It's used to format the error message 1683 * format('The field must between %s and %s', [10, 20]) = 'The field must between 10 and 20' 1684 * 1685 * @param {String} message 1686 * @param {Array} parameters 1687 * @returns {String} 1688 */ 1689 format: function(message, parameters) { 1690 if (!$.isArray(parameters)) { 1691 parameters = [parameters]; 1692 } 1693 1694 for (var i in parameters) { 1695 message = message.replace('%s', parameters[i]); 1696 } 1697 1698 return message; 1699 }, 1700 1701 /** 1702 * Validate a date 1703 * 1704 * @param {Number} year The full year in 4 digits 1705 * @param {Number} month The month number 1706 * @param {Number} day The day number 1707 * @param {Boolean} [notInFuture] If true, the date must not be in the future 1708 * @returns {Boolean} 1709 */ 1710 date: function(year, month, day, notInFuture) { 1711 if (isNaN(year) || isNaN(month) || isNaN(day)) { 1712 return false;
1713 } 1714 1715 day = parseInt(day, 10); 1716 month = parseInt(month, 10); 1717 year = parseInt(year, 10); 1718 1719 if (year < 1000 || year > 9999 || month <= 0 || month > 12) { 1720 return false; 1721 } 1722 var numDays = [31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]; 1723 // Update the number of days in Feb of leap year 1724 if (year % 400 === 0 || (year % 100 !== 0 && year % 4 === 0)) { 1725 numDays[1] = 29; 1726 } 1727 1728 // Check the day 1729 if (day <= 0 || day > numDays[month - 1]) { 1730 return false; 1731 } 1732 1733 if (notInFuture === true) { 1734 var currentDate = new Date(), 1735 currentYear = currentDate.getFullYear(), 1736 currentMonth = currentDate.getMonth(), 1737 currentDay = currentDate.getDate(); 1738 return (year < currentYear 1739 || (year === currentYear && month - 1 < currentMonth) 1740 || (year === currentYear && month - 1 === currentMonth && day < currentDay)); 1741 } 1742 1743 return true; 1744 }, 1745 1746 /** 1747 * Implement Luhn validation algorithm 1748 * Credit to https://gist.github.com/ShirtlessKirk/2134376 1749 * 1750 * @see http://en.wikipedia.org/wiki/Luhn 1751 * @param {String} value 1752 * @returns {Boolean} 1753 */ 1754 luhn: function(value) { 1755 var length = value.length, 1756 mul = 0, 1757 prodArr = [[0, 1, 2, 3, 4, 5, 6, 7, 8, 9], [0, 2, 4, 6, 8, 1, 3, 5, 7, 9]], 1758 sum = 0; 1759 1760 while (length--) { 1761 sum += prodArr[mul][parseInt(value.charAt(length), 10)]; 1762 mul ^= 1; 1763 } 1764 1765 return (sum % 10 === 0 && sum > 0); 1766 }, 1767 1768 /** 1769 * Implement modulus 11, 10 (ISO 7064) algorithm 1770 * 1771 * @param {String} value 1772 * @returns {Boolean} 1773 */ 1774 mod11And10: function(value) { 1775 var check = 5, 1776 length = value.length; 1777 for (var i = 0; i < length; i++) { 1778 check = (((check || 10) * 2) % 11 + parseInt(value.charAt(i), 10)) % 10; 1779 } 1780 return (check === 1); 1781 }, 1782 1783 /** 1784 * Implements Mod 37, 36 (ISO 7064) algorithm 1785 * Usages: 1786 * mod37And36('A12425GABC1234002M') 1787 * mod37And36('002006673085', '0123456789') 1788 * 1789 * @param {String} value 1790 * @param {String} [alphabet] 1791 * @returns {Boolean} 1792 */ 1793 mod37And36: function(value, alphabet) { 1794 alphabet = alphabet || '0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ'; 1795 var modulus = alphabet.length, 1796 length = value.length, 1797 check = Math.floor(modulus / 2); 1798 for (var i = 0; i < length; i++) { 1799 check = (((check || modulus) * 2) % (modulus + 1) + alphabet.indexOf(value.charAt(i))) % modulus; 1800 } 1801 return (check === 1); 1802 } 1803 }; 1804}(window.jQuery)); 1805;(function($) { 1806 $.fn.bootstrapValidator.i18n.base64 = $.extend($.fn.bootstrapValidator.i18n.base64 || {}, { 1807 'default': 'Please enter a valid base 64 encoded' 1808 }); 1809 1810 $.fn.bootstrapValidator.validators.base64 = { 1811 /** 1812 * Return true if the input value is a base 64 encoded string. 1813 * 1814 * @param {BootstrapValidator} validator The validator plugin instance 1815 * @param {jQuery} $field Field element 1816 * @param {Object} options Can consist of the following keys: 1817 * - message: The invalid message 1818 * @returns {Boolean} 1819 */ 1820 validate: function(validator, $field, options) { 1821 var value = $field.val(); 1822 if (value === '') { 1823 return true; 1824 } 1825 1826 return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(value); 1827 } 1828 }; 1829}(window.jQuery)); 1830;(function($) { 1831 $.fn.bootstrapValidator.i18n.between = $.extend($.fn.bootstrapValidator.i18n.between || {}, { 1832 'default': 'Please enter a value between %s and %s', 1833 notInclusive: 'Please enter a value between %s and %s strictly' 1834 }); 1835 1836 $.fn.bootstrapValidator.validators.between = { 1837 html5Attributes: { 1838 message: 'message', 1839 min: 'min', 1840 max: 'max', 1841 inclusive: 'inclusive' 1842 }, 1843 1844 enableByHtml5: function($field) { 1845 if ('range' === $field.attr('type')) { 1846 return { 1847 min: $field.attr('min'), 1848 max: $field.attr('max') 1849 }; 1850 } 1851 1852 return false;
1853 }, 1854 1855 /** 1856 * Return true if the input value is between (strictly or not) two given numbers 1857 * 1858 * @param {BootstrapValidator} validator The validator plugin instance 1859 * @param {jQuery} $field Field element 1860 * @param {Object} options Can consist of the following keys: 1861 * - min 1862 * - max 1863 * 1864 * The min, max keys define the number which the field value compares to. min, max can be 1865 * - A number 1866 * - Name of field which its value defines the number 1867 * - Name of callback function that returns the number 1868 * - A callback function that returns the number 1869 * 1870 * - inclusive [optional]: Can be true or false. Default is true 1871 * - message: The invalid message 1872 * @returns {Boolean|Object} 1873 */ 1874 validate: function(validator, $field, options) { 1875 var value = $field.val(); 1876 if (value === '') { 1877 return true; 1878 } 1879 1880 var min = $.isNumeric(options.min) ? options.min : validator.getDynamicOption($field, options.min), 1881 max = $.isNumeric(options.max) ? options.max : validator.getDynamicOption($field, options.max); 1882 1883 value = parseFloat(value); 1884 return (options.inclusive === true || options.inclusive === undefined) 1885 ? { 1886 valid: value >= min && value <= max, 1887 message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.between['default'], [min, max]) 1888 } 1889 : { 1890 valid: value > min && value < max, 1891 message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.between.notInclusive, [min, max]) 1892 }; 1893 } 1894 }; 1895}(window.jQuery)); 1896;(function($) { 1897 $.fn.bootstrapValidator.i18n.callback = $.extend($.fn.bootstrapValidator.i18n.callback || {}, { 1898 'default': 'Please enter a valid value' 1899 }); 1900 1901 $.fn.bootstrapValidator.validators.callback = { 1902 html5Attributes: { 1903 message: 'message', 1904 callback: 'callback' 1905 }, 1906 1907 /** 1908 * Return result from the callback method 1909 * 1910 * @param {BootstrapValidator} validator The validator plugin instance 1911 * @param {jQuery} $field Field element 1912 * @param {Object} options Can consist of the following keys: 1913 * - callback: The callback method that passes 2 parameters: 1914 * callback: function(fieldValue, validator, $field) { 1915 * // fieldValue is the value of field 1916 * // validator is instance of BootstrapValidator 1917 * // $field is the field element 1918 * } 1919 * - message: The invalid message 1920 * @returns {Boolean|Deferred} 1921 */ 1922 validate: function(validator, $field, options) { 1923 var value = $field.val(); 1924 1925 if (options.callback) { 1926 var dfd = new $.Deferred(), 1927 response = $.fn.bootstrapValidator.helpers.call(options.callback, [value, validator, $field]); 1928 dfd.resolve($field, 'callback', 'boolean' === typeof response ? response : response.valid, 'object' === typeof response && response.message ? response.message : null); 1929 return dfd; 1930 } 1931 1932 return true; 1933 } 1934 }; 1935}(window.jQuery)); 1936;(function($) { 1937 $.fn.bootstrapValidator.i18n.choice = $.extend($.fn.bootstrapValidator.i18n.choice || {}, { 1938 'default': 'Please enter a valid value', 1939 less: 'Please choose %s options at minimum', 1940 more: 'Please choose %s options at maximum', 1941 between: 'Please choose %s - %s options' 1942 }); 1943 1944 $.fn.bootstrapValidator.validators.choice = { 1945 html5Attributes: { 1946 message: 'message', 1947 min: 'min', 1948 max: 'max' 1949 }, 1950 1951 /** 1952 * Check if the number of checked boxes are less or more than a given number 1953 * 1954 * @param {BootstrapValidator} validator The validator plugin instance 1955 * @param {jQuery} $field Field element 1956 * @param {Object} options Consists of following keys: 1957 * - min 1958 * - max 1959 * 1960 * At least one of two keys is required
1961 * The min, max keys define the number which the field value compares to. min, max can be 1962 * - A number 1963 * - Name of field which its value defines the number 1964 * - Name of callback function that returns the number 1965 * - A callback function that returns the number 1966 * 1967 * - message: The invalid message 1968 * @returns {Object} 1969 */ 1970 validate: function(validator, $field, options) { 1971 var numChoices = $field.is('select') 1972 ? validator.getFieldElements($field.attr('data-bv-field')).find('option').filter(':selected').length 1973 : validator.getFieldElements($field.attr('data-bv-field')).filter(':checked').length, 1974 min = options.min ? ($.isNumeric(options.min) ? options.min : validator.getDynamicOption($field, options.min)) : null, 1975 max = options.max ? ($.isNumeric(options.max) ? options.max : validator.getDynamicOption($field, options.max)) : null, 1976 isValid = true, 1977 message = options.message || $.fn.bootstrapValidator.i18n.choice['default']; 1978 1979 if ((min && numChoices < parseInt(min, 10)) || (max && numChoices > parseInt(max, 10))) { 1980 isValid = false; 1981 } 1982 1983 switch (true) { 1984 case (!!min && !!max): 1985 message = $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.choice.between, [parseInt(min, 10), parseInt(max, 10)]); 1986 break; 1987 1988 case (!!min): 1989 message = $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.choice.less, parseInt(min, 10)); 1990 break; 1991 1992 case (!!max): 1993 message = $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.choice.more, parseInt(max, 10)); 1994 break; 1995 1996 default: 1997 break; 1998 } 1999 2000 return { valid: isValid, message: message }; 2001 } 2002 }; 2003}(window.jQuery)); 2004;(function($) { 2005 $.fn.bootstrapValidator.i18n.creditCard = $.extend($.fn.bootstrapValidator.i18n.creditCard || {}, { 2006 'default': 'Please enter a valid credit card number' 2007 }); 2008 2009 $.fn.bootstrapValidator.validators.creditCard = { 2010 /** 2011 * Return true if the input value is valid credit card number 2012 * Based on https://gist.github.com/DiegoSalazar/4075533 2013 * 2014 * @param {BootstrapValidator} validator The validator plugin instance 2015 * @param {jQuery} $field Field element 2016 * @param {Object} [options] Can consist of the following key: 2017 * - message: The invalid message 2018 * @returns {Boolean} 2019 */ 2020 validate: function(validator, $field, options) { 2021 var value = $field.val(); 2022 if (value === '') { 2023 return true; 2024 } 2025 2026 // Accept only digits, dashes or spaces 2027 if (/[^0-9-\s]+/.test(value)) { 2028 return false; 2029 } 2030 value = value.replace(/\D/g, ''); 2031 2032 if (!$.fn.bootstrapValidator.helpers.luhn(value)) { 2033 return false; 2034 } 2035 2036 // Validate the card number based on prefix (IIN ranges) and length 2037 var cards = { 2038 AMERICAN_EXPRESS: { 2039 length: [15], 2040 prefix: ['34', '37'] 2041 }, 2042 DINERS_CLUB: { 2043 length: [14], 2044 prefix: ['300', '301', '302', '303', '304', '305', '36'] 2045 }, 2046 DINERS_CLUB_US: { 2047 length: [16], 2048 prefix: ['54', '55'] 2049 }, 2050 DISCOVER: { 2051 length: [16], 2052 prefix: ['6011', '622126', '622127', '622128', '622129', '62213', 2053 '62214', '62215', '62216', '62217', '62218', '62219', 2054 '6222', '6223', '6224', '6225', '6226', '6227', '6228', 2055 '62290', '62291', '622920', '622921', '622922', '622923', 2056 '622924', '622925', '644', '645', '646', '647', '648', 2057 '649', '65'] 2058 }, 2059 JCB: { 2060 length: [16], 2061 prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] 2062 }, 2063 LASER: { 2064 length: [16, 17, 18, 19], 2065 prefix: ['6304', '6706', '6771', '6709'] 2066 }, 2067 MAESTRO: { 2068 length: [12, 13, 14, 15, 16, 17, 18, 19], 2069 prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] 2070 }, 2071 MASTERCARD: { 2072 length: [16], 2073 prefix: ['51', '52', '53', '54', '55'] 2074 }, 2075 SOLO: { 2076 length: [16, 18, 19], 2077 prefix: ['6334', '6767'] 2078 }, 2079 UNIONPAY: { 2080 length: [16, 17, 18, 19], 2081 prefix: ['622126', '622127', '622128', '622129', '62213', '62214', 2082 '62215', '62216', '62217', '62218', '62219', '6222', '6223', 2083 '6224', '6225', '6226', '6227', '6228', '62290', '62291', 2084 '622920', '622921', '622922', '622923', '622924', '622925'] 2085 }, 2086 VISA: { 2087 length: [16], 2088 prefix: ['4'] 2089 } 2090 }; 2091 2092 var type, i; 2093 for (type in cards) { 2094 for (i in cards[type].prefix) { 2095 if (value.substr(0, cards[type].prefix[i].length) === cards[type].prefix[i] // Check the prefix 2096 && $.inArray(value.length, cards[type].length) !== -1) // and length 2097 { 2098 return true; 2099 } 2100 } 2101 } 2102 2103 return false;
2104 } 2105 }; 2106}(window.jQuery)); 2107;(function($) { 2108 $.fn.bootstrapValidator.i18n.cusip = $.extend($.fn.bootstrapValidator.i18n.cusip || {}, { 2109 'default': 'Please enter a valid CUSIP number' 2110 }); 2111 2112 $.fn.bootstrapValidator.validators.cusip = { 2113 /** 2114 * Validate a CUSIP 2115 * Examples: 2116 * - Valid: 037833100, 931142103, 14149YAR8, 126650BG6 2117 * - Invalid: 31430F200, 022615AC2 2118 * 2119 * @see http://en.wikipedia.org/wiki/CUSIP 2120 * @param {BootstrapValidator} validator The validator plugin instance 2121 * @param {jQuery} $field Field element 2122 * @param {Object} [options] Can consist of the following keys: 2123 * - message: The invalid message 2124 * @returns {Boolean} 2125 */ 2126 validate: function(validator, $field, options) { 2127 var value = $field.val(); 2128 if (value === '') { 2129 return true; 2130 } 2131 2132 value = value.toUpperCase(); 2133 if (!/^[0-9A-Z]{9}$/.test(value)) { 2134 return false; 2135 } 2136 2137 var converted = $.map(value.split(''), function(item) { 2138 var code = item.charCodeAt(0); 2139 return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) 2140 // Replace A, B, C, ..., Z with 10, 11, ..., 35 2141 ? (code - 'A'.charCodeAt(0) + 10) 2142 : item; 2143 }), 2144 length = converted.length, 2145 sum = 0; 2146 for (var i = 0; i < length - 1; i++) { 2147 var num = parseInt(converted[i], 10); 2148 if (i % 2 !== 0) { 2149 num *= 2; 2150 } 2151 if (num > 9) { 2152 num -= 9; 2153 } 2154 sum += num; 2155 } 2156 2157 sum = (10 - (sum % 10)) % 10; 2158 return sum === converted[length - 1]; 2159 } 2160 }; 2161}(window.jQuery)); 2162;(function($) { 2163 $.fn.bootstrapValidator.i18n.cvv = $.extend($.fn.bootstrapValidator.i18n.cvv || {}, { 2164 'default': 'Please enter a valid CVV number' 2165 }); 2166 2167 $.fn.bootstrapValidator.validators.cvv = { 2168 html5Attributes: { 2169 message: 'message', 2170 ccfield: 'creditCardField' 2171 }, 2172 2173 /** 2174 * Return true if the input value is a valid CVV number. 2175 * 2176 * @param {BootstrapValidator} validator The validator plugin instance 2177 * @param {jQuery} $field Field element 2178 * @param {Object} options Can consist of the following keys: 2179 * - creditCardField: The credit card number field. It can be null 2180 * - message: The invalid message 2181 * @returns {Boolean} 2182 */ 2183 validate: function(validator, $field, options) { 2184 var value = $field.val(); 2185 if (value === '') { 2186 return true; 2187 } 2188 2189 if (!/^[0-9]{3,4}$/.test(value)) { 2190 return false; 2191 } 2192 2193 if (!options.creditCardField) { 2194 return true; 2195 } 2196 2197 // Get the credit card number 2198 var creditCard = validator.getFieldElements(options.creditCardField).val(); 2199 if (creditCard === '') { 2200 return true; 2201 } 2202 2203 creditCard = creditCard.replace(/\D/g, ''); 2204 2205 // Supported credit card types 2206 var cards = { 2207 AMERICAN_EXPRESS: { 2208 length: [15], 2209 prefix: ['34', '37'] 2210 }, 2211 DINERS_CLUB: { 2212 length: [14], 2213 prefix: ['300', '301', '302', '303', '304', '305', '36'] 2214 }, 2215 DINERS_CLUB_US: { 2216 length: [16], 2217 prefix: ['54', '55'] 2218 }, 2219 DISCOVER: { 2220 length: [16], 2221 prefix: ['6011', '622126', '622127', '622128', '622129', '62213', 2222 '62214', '62215', '62216', '62217', '62218', '62219', 2223 '6222', '6223', '6224', '6225', '6226', '6227', '6228', 2224 '62290', '62291', '622920', '622921', '622922', '622923', 2225 '622924', '622925', '644', '645', '646', '647', '648', 2226 '649', '65'] 2227 }, 2228 JCB: { 2229 length: [16], 2230 prefix: ['3528', '3529', '353', '354', '355', '356', '357', '358'] 2231 }, 2232 LASER: { 2233 length: [16, 17, 18, 19], 2234 prefix: ['6304', '6706', '6771', '6709'] 2235 }, 2236 MAESTRO: { 2237 length: [12, 13, 14, 15, 16, 17, 18, 19], 2238 prefix: ['5018', '5020', '5038', '6304', '6759', '6761', '6762', '6763', '6764', '6765', '6766'] 2239 }, 2240 MASTERCARD: { 2241 length: [16], 2242 prefix: ['51', '52', '53', '54', '55'] 2243 }, 2244 SOLO: { 2245 length: [16, 18, 19], 2246 prefix: ['6334', '6767'] 2247 }, 2248 UNIONPAY: { 2249 length: [16, 17, 18, 19], 2250 prefix: ['622126', '622127', '622128', '622129', '62213', '62214', 2251 '62215', '62216', '62217', '62218', '62219', '6222', '6223', 2252 '6224', '6225', '6226', '6227', '6228', '62290', '62291', 2253 '622920', '622921', '622922', '622923', '622924', '622925'] 2254 }, 2255 VISA: { 2256 length: [16], 2257 prefix: ['4'] 2258 } 2259 }; 2260 var type, i, creditCardType = null; 2261 for (type in cards) { 2262 for (i in cards[type].prefix) { 2263 if (creditCard.substr(0, cards[type].prefix[i].length) === cards[type].prefix[i] // Check the prefix 2264 && $.inArray(creditCard.length, cards[type].length) !== -1) // and length 2265 { 2266 creditCardType = type; 2267 break; 2268 } 2269 } 2270 } 2271 2272 return (creditCardType === null) 2273 ? false
2274 : (('AMERICAN_EXPRESS' === creditCardType) ? (value.length === 4) : (value.length === 3)); 2275 } 2276 }; 2277}(window.jQuery)); 2278;(function($) { 2279 $.fn.bootstrapValidator.i18n.date = $.extend($.fn.bootstrapValidator.i18n.date || {}, { 2280 'default': 'Please enter a valid date' 2281 }); 2282 2283 $.fn.bootstrapValidator.validators.date = { 2284 html5Attributes: { 2285 message: 'message', 2286 format: 'format', 2287 separator: 'separator' 2288 }, 2289 2290 /** 2291 * Return true if the input value is valid date 2292 * 2293 * @param {BootstrapValidator} validator The validator plugin instance 2294 * @param {jQuery} $field Field element 2295 * @param {Object} options Can consist of the following keys: 2296 * - message: The invalid message 2297 * - separator: Use to separate the date, month, and year. 2298 * By default, it is / 2299 * - format: The date format. Default is MM/DD/YYYY 2300 * The format can be: 2301 * 2302 * i) date: Consist of DD, MM, YYYY parts which are separated by the separator option 2303 * ii) date and time: 2304 * The time can consist of h, m, s parts which are separated by : 2305 * ii) date, time and A (indicating AM or PM) 2306 * @returns {Boolean} 2307 */ 2308 validate: function(validator, $field, options) { 2309 var value = $field.val(); 2310 if (value === '') { 2311 return true; 2312 } 2313 2314 options.format = options.format || 'MM/DD/YYYY'; 2315 2316 var formats = options.format.split(' '), 2317 dateFormat = formats[0], 2318 timeFormat = (formats.length > 1) ? formats[1] : null, 2319 amOrPm = (formats.length > 2) ? formats[2] : null, 2320 sections = value.split(' '), 2321 date = sections[0], 2322 time = (sections.length > 1) ? sections[1] : null; 2323 2324 if (formats.length !== sections.length) { 2325 return false; 2326 } 2327 2328 // Determine the separator 2329 var separator = options.separator; 2330 if (!separator) { 2331 separator = (date.indexOf('/') !== -1) ? '/' : ((date.indexOf('-') !== -1) ? '-' : null); 2332 } 2333 if (separator === null || date.indexOf(separator) === -1) { 2334 return false; 2335 } 2336 2337 // Determine the date 2338 date = date.split(separator); 2339 dateFormat = dateFormat.split(separator); 2340 if (date.length !== dateFormat.length) { 2341 return false; 2342 } 2343 2344 var year = date[$.inArray('YYYY', dateFormat)], 2345 month = date[$.inArray('MM', dateFormat)], 2346 day = date[$.inArray('DD', dateFormat)]; 2347 2348 if (!year || !month || !day) { 2349 return false; 2350 } 2351 2352 // Determine the time 2353 var minutes = null, hours = null, seconds = null; 2354 if (timeFormat) { 2355 timeFormat = timeFormat.split(':'); 2356 time = time.split(':'); 2357 2358 if (timeFormat.length !== time.length) { 2359 return false; 2360 } 2361 2362 hours = time.length > 0 ? time[0] : null; 2363 minutes = time.length > 1 ? time[1] : null; 2364 seconds = time.length > 2 ? time[2] : null; 2365 2366 // Validate seconds 2367 if (seconds) { 2368 seconds = parseInt(seconds, 10); 2369 if (isNaN(seconds) || seconds < 0 || seconds > 60) { 2370 return false; 2371 } 2372 } 2373 2374 // Validate hours 2375 if (hours) { 2376 hours = parseInt(hours, 10); 2377 if (isNaN(hours) || hours < 0 || hours >= 24 || (amOrPm && hours > 12)) { 2378 return false; 2379 } 2380 } 2381 2382 // Validate minutes 2383 if (minutes) { 2384 minutes = parseInt(minutes, 10); 2385 if (isNaN(minutes) || minutes < 0 || minutes > 59) { 2386 return false;
2387 } 2388 } 2389 } 2390 2391 // Validate day, month, and year 2392 return $.fn.bootstrapValidator.helpers.date(year, month, day); 2393 } 2394 }; 2395}(window.jQuery)); 2396;(function($) { 2397 $.fn.bootstrapValidator.i18n.different = $.extend($.fn.bootstrapValidator.i18n.different || {}, { 2398 'default': 'Please enter a different value' 2399 }); 2400 2401 $.fn.bootstrapValidator.validators.different = { 2402 html5Attributes: { 2403 message: 'message', 2404 field: 'field' 2405 }, 2406 2407 /** 2408 * Return true if the input value is different with given field's value 2409 * 2410 * @param {BootstrapValidator} validator The validator plugin instance 2411 * @param {jQuery} $field Field element 2412 * @param {Object} options Consists of the following key: 2413 * - field: The name of field that will be used to compare with current one 2414 * - message: The invalid message 2415 * @returns {Boolean} 2416 */ 2417 validate: function(validator, $field, options) { 2418 var value = $field.val(); 2419 if (value === '') { 2420 return true; 2421 } 2422 2423 var compareWith = validator.getFieldElements(options.field); 2424 if (compareWith === null) { 2425 return true; 2426 } 2427 2428 if (value !== compareWith.val()) { 2429 validator.updateStatus(options.field, validator.STATUS_VALID, 'different'); 2430 return true; 2431 } else { 2432 return false; 2433 } 2434 } 2435 }; 2436}(window.jQuery)); 2437;(function($) { 2438 $.fn.bootstrapValidator.i18n.digits = $.extend($.fn.bootstrapValidator.i18n.digits || {}, { 2439 'default': 'Please enter only digits' 2440 }); 2441 2442 $.fn.bootstrapValidator.validators.digits = { 2443 /** 2444 * Return true if the input value contains digits only 2445 * 2446 * @param {BootstrapValidator} validator Validate plugin instance 2447 * @param {jQuery} $field Field element 2448 * @param {Object} [options] 2449 * @returns {Boolean} 2450 */ 2451 validate: function(validator, $field, options) { 2452 var value = $field.val(); 2453 if (value === '') { 2454 return true; 2455 } 2456 2457 return /^\d+$/.test(value); 2458 } 2459 }; 2460}(window.jQuery)); 2461;(function($) { 2462 $.fn.bootstrapValidator.i18n.ean = $.extend($.fn.bootstrapValidator.i18n.ean || {}, { 2463 'default': 'Please enter a valid EAN number' 2464 }); 2465 2466 $.fn.bootstrapValidator.validators.ean = { 2467 /** 2468 * Validate EAN (International Article Number) 2469 * Examples: 2470 * - Valid: 73513537, 9780471117094, 4006381333931 2471 * - Invalid: 73513536 2472 * 2473 * @see http://en.wikipedia.org/wiki/European_Article_Number 2474 * @param {BootstrapValidator} validator The validator plugin instance 2475 * @param {jQuery} $field Field element 2476 * @param {Object} options Can consist of the following keys: 2477 * - message: The invalid message 2478 * @returns {Boolean} 2479 */ 2480 validate: function(validator, $field, options) { 2481 var value = $field.val(); 2482 if (value === '') { 2483 return true; 2484 } 2485 2486 if (!/^(\d{8}|\d{12}|\d{13})$/.test(value)) { 2487 return false; 2488 } 2489 2490 var length = value.length, 2491 sum = 0, 2492 weight = (length === 8) ? [3, 1] : [1, 3]; 2493 for (var i = 0; i < length - 1; i++) { 2494 sum += parseInt(value.charAt(i), 10) * weight[i % 2]; 2495 } 2496 sum = (10 - sum % 10) % 10; 2497 return (sum + '' === value.charAt(length - 1)); 2498 } 2499 }; 2500}(window.jQuery)); 2501;(function($) { 2502 $.fn.bootstrapValidator.i18n.emailAddress = $.extend($.fn.bootstrapValidator.i18n.emailAddress || {}, { 2503 'default': 'Please enter a valid email address' 2504 }); 2505 2506 $.fn.bootstrapValidator.validators.emailAddress = { 2507 enableByHtml5: function($field) { 2508 return ('email' === $field.attr('type')); 2509 }, 2510 2511 /** 2512 * Return true if and only if the input value is a valid email address 2513 * 2514 * @param {BootstrapValidator} validator Validate plugin instance 2515 * @param {jQuery} $field Field element 2516 * @param {Object} [options] 2517 * @returns {Boolean} 2518 */
2519 validate: function(validator, $field, options) { 2520 var value = $field.val(); 2521 if (value === '') { 2522 return true; 2523 } 2524 2525 // Email address regular expression 2526 // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript 2527 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,}))$/; 2528 return emailRegExp.test(value); 2529 } 2530 }; 2531}(window.jQuery)); 2532;(function($) { 2533 $.fn.bootstrapValidator.i18n.file = $.extend($.fn.bootstrapValidator.i18n.file || {}, { 2534 'default': 'Please choose a valid file' 2535 }); 2536 2537 $.fn.bootstrapValidator.validators.file = { 2538 html5Attributes: { 2539 extension: 'extension', 2540 maxsize: 'maxSize', 2541 message: 'message', 2542 type: 'type' 2543 }, 2544 2545 /** 2546 * Validate upload file. Use HTML 5 API if the browser supports 2547 * 2548 * @param {BootstrapValidator} validator The validator plugin instance 2549 * @param {jQuery} $field Field element 2550 * @param {Object} options Can consist of the following keys: 2551 * - extension: The allowed extensions, separated by a comma 2552 * - maxSize: The maximum size in bytes 2553 * - message: The invalid message 2554 * - type: The allowed MIME type, separated by a comma 2555 * @returns {Boolean} 2556 */ 2557 validate: function(validator, $field, options) { 2558 var value = $field.val(); 2559 if (value === '') { 2560 return true; 2561 } 2562 2563 var ext, 2564 extensions = options.extension ? options.extension.toLowerCase().split(',') : null, 2565 types = options.type ? options.type.toLowerCase().split(',') : null, 2566 html5 = (window.File && window.FileList && window.FileReader); 2567 2568 if (html5) { 2569 // Get FileList instance 2570 var files = $field.get(0).files, 2571 total = files.length; 2572 for (var i = 0; i < total; i++) { 2573 // Check file size 2574 if (options.maxSize && files[i].size > parseInt(options.maxSize, 10)) { 2575 return false; 2576 } 2577 2578 // Check file extension 2579 ext = files[i].name.substr(files[i].name.lastIndexOf('.') + 1); 2580 if (extensions && $.inArray(ext.toLowerCase(), extensions) === -1) { 2581 return false; 2582 } 2583 2584 // Check file type 2585 if (types && $.inArray(files[i].type.toLowerCase(), types) === -1) { 2586 return false; 2587 } 2588 } 2589 } else { 2590 // Check file extension 2591 ext = value.substr(value.lastIndexOf('.') + 1); 2592 if (extensions && $.inArray(ext.toLowerCase(), extensions) === -1) { 2593 return false; 2594 } 2595 } 2596 2597 return true; 2598 } 2599 }; 2600}(window.jQuery)); 2601;(function($) { 2602 $.fn.bootstrapValidator.i18n.greaterThan = $.extend($.fn.bootstrapValidator.i18n.greaterThan || {}, { 2603 'default': 'Please enter a value greater than or equal to %s', 2604 notInclusive: 'Please enter a value greater than %s' 2605 }); 2606 2607 $.fn.bootstrapValidator.validators.greaterThan = { 2608 html5Attributes: { 2609 message: 'message', 2610 value: 'value', 2611 inclusive: 'inclusive' 2612 }, 2613 2614 enableByHtml5: function($field) { 2615 var min = $field.attr('min'); 2616 if (min) { 2617 return { 2618 value: min 2619 }; 2620 } 2621 2622 return false; 2623 }, 2624 2625 /** 2626 * Return true if the input value is greater than or equals to given number 2627 * 2628 * @param {BootstrapValidator} validator Validate plugin instance 2629 * @param {jQuery} $field Field element 2630 * @param {Object} options Can consist of the following keys: 2631 * - value: Define the number to compare with. It can be 2632 * - A number 2633 * - Name of field which its value defines the number 2634 * - Name of callback function that returns the number 2635 * - A callback function that returns the number 2636 * 2637 * - inclusive [optional]: Can be true or false. Default is true 2638 * - message: The invalid message 2639 * @returns {Boolean|Object} 2640 */
2641 validate: function(validator, $field, options) { 2642 var value = $field.val(); 2643 if (value === '') { 2644 return true; 2645 } 2646 2647 var compareTo = $.isNumeric(options.value) ? options.value : validator.getDynamicOption($field, options.value); 2648 2649 value = parseFloat(value); 2650 return (options.inclusive === true || options.inclusive === undefined) 2651 ? { 2652 valid: value >= compareTo, 2653 message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.greaterThan['default'], compareTo) 2654 } 2655 : { 2656 valid: value > compareTo, 2657 message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.greaterThan.notInclusive, compareTo) 2658 }; 2659 } 2660 }; 2661}(window.jQuery)); 2662;(function($) { 2663 $.fn.bootstrapValidator.i18n.grid = $.extend($.fn.bootstrapValidator.i18n.grid || {}, { 2664 'default': 'Please enter a valid GRId number' 2665 }); 2666 2667 $.fn.bootstrapValidator.validators.grid = { 2668 /** 2669 * Validate GRId (Global Release Identifier) 2670 * Examples: 2671 * - Valid: A12425GABC1234002M, A1-2425G-ABC1234002-M, A1 2425G ABC1234002 M, Grid:A1-2425G-ABC1234002-M 2672 * - Invalid: A1-2425G-ABC1234002-Q 2673 * 2674 * @see http://en.wikipedia.org/wiki/Global_Release_Identifier 2675 * @param {BootstrapValidator} validator The validator plugin instance 2676 * @param {jQuery} $field Field element 2677 * @param {Object} options Can consist of the following keys: 2678 * - message: The invalid message 2679 * @returns {Boolean} 2680 */ 2681 validate: function(validator, $field, options) { 2682 var value = $field.val(); 2683 if (value === '') { 2684 return true; 2685 } 2686 2687 value = value.toUpperCase(); 2688 if (!/^[GRID:]*([0-9A-Z]{2})[-\s]*([0-9A-Z]{5})[-\s]*([0-9A-Z]{10})[-\s]*([0-9A-Z]{1})$/g.test(value)) { 2689 return false; 2690 } 2691 value = value.replace(/\s/g, '').replace(/-/g, ''); 2692 if ('GRID:' === value.substr(0, 5)) { 2693 value = value.substr(5); 2694 } 2695 return $.fn.bootstrapValidator.helpers.mod37And36(value); 2696 } 2697 }; 2698}(window.jQuery)); 2699;(function($) { 2700 $.fn.bootstrapValidator.i18n.hex = $.extend($.fn.bootstrapValidator.i18n.hex || {}, { 2701 'default': 'Please enter a valid hexadecimal number' 2702 }); 2703 2704 $.fn.bootstrapValidator.validators.hex = { 2705 /** 2706 * Return true if and only if the input value is a valid hexadecimal number 2707 * 2708 * @param {BootstrapValidator} validator The validator plugin instance 2709 * @param {jQuery} $field Field element 2710 * @param {Object} options Consist of key: 2711 * - message: The invalid message 2712 * @returns {Boolean} 2713 */ 2714 validate: function(validator, $field, options) { 2715 var value = $field.val(); 2716 if (value === '') { 2717 return true; 2718 } 2719 2720 return /^[0-9a-fA-F]+$/.test(value); 2721 } 2722 }; 2723}(window.jQuery)); 2724;(function($) { 2725 $.fn.bootstrapValidator.i18n.hexColor = $.extend($.fn.bootstrapValidator.i18n.hexColor || {}, { 2726 'default': 'Please enter a valid hex color' 2727 }); 2728 2729 $.fn.bootstrapValidator.validators.hexColor = { 2730 enableByHtml5: function($field) { 2731 return ('color' === $field.attr('type')); 2732 }, 2733 2734 /** 2735 * Return true if the input value is a valid hex color 2736 * 2737 * @param {BootstrapValidator} validator The validator plugin instance 2738 * @param {jQuery} $field Field element 2739 * @param {Object} options Can consist of the following keys: 2740 * - message: The invalid message 2741 * @returns {Boolean} 2742 */ 2743 validate: function(validator, $field, options) { 2744 var value = $field.val(); 2745 if (value === '') { 2746 return true; 2747 } 2748 return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value); 2749 } 2750 }; 2751}(window.jQuery)); 2752;(function($) { 2753 $.fn.bootstrapValidator.i18n.iban = $.extend($.fn.bootstrapValidator.i18n.iban || {}, { 2754 'default': 'Please enter a valid IBAN number', 2755 countryNotSupported: 'The country code %s is not supported', 2756 country: 'Please enter a valid IBAN number in %s', 2757 countries: { 2758 AD: 'Andorra', 2759 AE: 'United Arab Emirates', 2760 AL: 'Albania', 2761 AO: 'Angola', 2762 AT: 'Austria', 2763 AZ: 'Azerbaijan', 2764 BA: 'Bosnia and Herzegovina', 2765 BE: 'Belgium', 2766 BF: 'Burkina Faso', 2767 BG: 'Bulgaria', 2768 BH: 'Bahrain', 2769 BI: 'Burundi', 2770 BJ: 'Benin', 2771 BR: 'Brazil', 2772 CH: 'Switzerland', 2773 CI: 'Ivory Coast', 2774 CM: 'Cameroon', 2775 CR: 'Costa Rica', 2776 CV: 'Cape Verde', 2777 CY: 'Cyprus', 2778 CZ: 'Czech Republic', 2779 DE: 'Germany', 2780 DK: 'Denmark', 2781 DO: 'Dominican Republic', 2782 DZ: 'Algeria', 2783 EE: 'Estonia', 2784 ES: 'Spain', 2785 FI: 'Finland', 2786 FO: 'Faroe Islands', 2787 FR: 'France', 2788 GB: 'United Kingdom', 2789 GE: 'Georgia', 2790 GI: 'Gibraltar', 2791 GL: 'Greenland', 2792 GR: 'Greece', 2793 GT: 'Guatemala', 2794 HR: 'Croatia', 2795 HU: 'Hungary', 2796 IE: 'Ireland', 2797 IL: 'Israel', 2798 IR: 'Iran', 2799 IS: 'Iceland', 2800 IT: 'Italy', 2801 JO: 'Jordan', 2802 KW: 'Kuwait',
2803 KZ: 'Kazakhstan', 2804 LB: 'Lebanon', 2805 LI: 'Liechtenstein', 2806 LT: 'Lithuania', 2807 LU: 'Luxembourg', 2808 LV: 'Latvia', 2809 MC: 'Monaco', 2810 MD: 'Moldova', 2811 ME: 'Montenegro', 2812 MG: 'Madagascar', 2813 MK: 'Macedonia', 2814 ML: 'Mali', 2815 MR: 'Mauritania', 2816 MT: 'Malta', 2817 MU: 'Mauritius', 2818 MZ: 'Mozambique', 2819 NL: 'Netherlands', 2820 NO: 'Norway', 2821 PK: 'Pakistan', 2822 PL: 'Poland', 2823 PS: 'Palestinian', 2824 PT: 'Portugal', 2825 QA: 'Qatar', 2826 RO: 'Romania', 2827 RS: 'Serbia', 2828 SA: 'Saudi Arabia', 2829 SE: 'Sweden', 2830 SI: 'Slovenia', 2831 SK: 'Slovakia', 2832 SM: 'San Marino', 2833 SN: 'Senegal', 2834 TN: 'Tunisia', 2835 TR: 'Turkey', 2836 VG: 'Virgin Islands, British' 2837 } 2838 }); 2839 2840 $.fn.bootstrapValidator.validators.iban = { 2841 html5Attributes: { 2842 message: 'message', 2843 country: 'country' 2844 }, 2845 2846 // http://www.swift.com/dsp/resources/documents/IBAN_Registry.pdf 2847 // http://en.wikipedia.org/wiki/International_Bank_Account_Number#IBAN_formats_by_country 2848 REGEX: { 2849 'AD': 'AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}', // Andorra 2850 'AE': 'AE[0-9]{2}[0-9]{3}[0-9]{16}', // United Arab Emirates 2851 'AL': 'AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}', // Albania 2852 'AO': 'AO[0-9]{2}[0-9]{21}', // Angola 2853 'AT': 'AT[0-9]{2}[0-9]{5}[0-9]{11}', // Austria 2854 'AZ': 'AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}', // Azerbaijan 2855 'BA': 'BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}', // Bosnia and Herzegovina 2856 'BE': 'BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}', // Belgium 2857 'BF': 'BF[0-9]{2}[0-9]{23}', // Burkina Faso 2858 'BG': 'BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}', // Bulgaria 2859 'BH': 'BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}', // Bahrain 2860 'BI': 'BI[0-9]{2}[0-9]{12}', // Burundi 2861 'BJ': 'BJ[0-9]{2}[A-Z]{1}[0-9]{23}', // Benin 2862 'BR': 'BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z][A-Z0-9]', // Brazil 2863 'CH': 'CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}', // Switzerland 2864 'CI': 'CI[0-9]{2}[A-Z]{1}[0-9]{23}', // Ivory Coast 2865 'CM': 'CM[0-9]{2}[0-9]{23}', // Cameroon 2866 'CR': 'CR[0-9]{2}[0-9]{3}[0-9]{14}', // Costa Rica 2867 'CV': 'CV[0-9]{2}[0-9]{21}', // Cape Verde 2868 'CY': 'CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}', // Cyprus 2869 'CZ': 'CZ[0-9]{2}[0-9]{20}', // Czech Republic 2870 'DE': 'DE[0-9]{2}[0-9]{8}[0-9]{10}', // Germany 2871 'DK': 'DK[0-9]{2}[0-9]{14}', // Denmark 2872 'DO': 'DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}', // Dominican Republic 2873 'DZ': 'DZ[0-9]{2}[0-9]{20}', // Algeria 2874 'EE': 'EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}', // Estonia 2875 'ES': 'ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}', // Spain 2876 'FI': 'FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}', // Finland 2877 'FO': 'FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', // Faroe Islands 2878 'FR': 'FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', // France 2879 'GB': 'GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', // United Kingdom 2880 'GE': 'GE[0-9]{2}[A-Z]{2}[0-9]{16}', // Georgia 2881 'GI': 'GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}', // Gibraltar 2882 'GL': 'GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}', // Greenland 2883 'GR': 'GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}', // Greece 2884 'GT': 'GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}', // Guatemala 2885 'HR': 'HR[0-9]{2}[0-9]{7}
2885[0-9]{10}', // Croatia 2886 'HU': 'HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}', // Hungary 2887 'IE': 'IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}', // Ireland 2888 'IL': 'IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}', // Israel 2889 'IR': 'IR[0-9]{2}[0-9]{22}', // Iran 2890 'IS': 'IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}', // Iceland 2891 'IT': 'IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', // Italy 2892 'JO': 'JO[0-9]{2}[A-Z]{4}[0-9]{4}[0]{8}[A-Z0-9]{10}', // Jordan 2893 'KW': 'KW[0-9]{2}[A-Z]{4}[0-9]{22}', // Kuwait 2894 'KZ': 'KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}', // Kazakhstan 2895 'LB': 'LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}', // Lebanon 2896 'LI': 'LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}', // Liechtenstein 2897 'LT': 'LT[0-9]{2}[0-9]{5}[0-9]{11}', // Lithuania 2898 'LU': 'LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}', // Luxembourg 2899 'LV': 'LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}', // Latvia 2900 'MC': 'MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}', // Monaco 2901 'MD': 'MD[0-9]{2}[A-Z0-9]{20}', // Moldova 2902 'ME': 'ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Montenegro 2903 'MG': 'MG[0-9]{2}[0-9]{23}', // Madagascar 2904 'MK': 'MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}', // Macedonia 2905 'ML': 'ML[0-9]{2}[A-Z]{1}[0-9]{23}', // Mali 2906 'MR': 'MR13[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}', // Mauritania 2907 'MT': 'MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}', // Malta 2908 'MU': 'MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}',// Mauritius 2909 'MZ': 'MZ[0-9]{2}[0-9]{21}', // Mozambique 2910 'NL': 'NL[0-9]{2}[A-Z]{4}[0-9]{10}', // Netherlands 2911 'NO': 'NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}', // Norway 2912 'PK': 'PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', // Pakistan 2913 'PL': 'PL[0-9]{2}[0-9]{8}[0-9]{16}', // Poland 2914 'PS': 'PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', // Palestinian 2915 'PT': 'PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}', // Portugal 2916 'QA': 'QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}', // Qatar 2917 'RO': 'RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}', // Romania 2918 'RS': 'RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Serbia 2919 'SA': 'SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}', // Saudi Arabia 2920 'SE': 'SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}', // Sweden 2921 'SI': 'SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}', // Slovenia 2922 'SK': 'SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}', // Slovakia 2923 'SM': 'SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}', // San Marino 2924 'SN': 'SN[0-9]{2}[A-Z]{1}[0-9]{23}', // Senegal 2925 'TN': 'TN59[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}', // Tunisia 2926 'TR': 'TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}', // Turkey 2927 'VG': 'VG[0-9]{2}[A-Z]{4}[0-9]{16}' // Virgin Islands, British 2928 }, 2929 2930 /** 2931 * Validate an International Bank Account Number (IBAN) 2932 * To test it, take the sample IBAN from 2933 * http://www.nordea.com/Our+services/International+products+and+services/Cash+Management/IBAN+countries/908462.html 2934 * 2935 * @param {BootstrapValidator} validator The validator plugin instance 2936 * @param {jQuery} $field Field element 2937 * @param {Object} options Can consist of the following keys: 2938 * - message: The invalid message 2939 * - country: The ISO 3166-1 country code. It can be 2940 * - A country code 2941 * - Name of field which its value defines the country code 2942 * - Name of callback function that returns the country code 2943 * - A callback function that returns the country code 2944 * @returns {Boolean|Object} 2945 */
2946 validate: function(validator, $field, options) { 2947 var value = $field.val(); 2948 if (value === '') { 2949 return true; 2950 } 2951 2952 value = value.replace(/[^a-zA-Z0-9]/g, '').toUpperCase(); 2953 var country = options.country; 2954 if (!country) { 2955 country = value.substr(0, 2); 2956 } else if (typeof country !== 'string' || !this.REGEX[country]) { 2957 // Determine the country code 2958 country = validator.getDynamicOption($field, country); 2959 } 2960 2961 if (!this.REGEX[country]) { 2962 return { 2963 valid: false, 2964 message: $.fn.bootstrapValidator.helpers.format($.fn.bootstrapValidator.i18n.iban.countryNotSupported, country) 2965 }; 2966 } 2967 2968 if (!(new RegExp('^' + this.REGEX[country] + '$')).test(value)) { 2969 return { 2970 valid: false, 2971 message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.iban.country, $.fn.bootstrapValidator.i18n.iban.countries[country]) 2972 }; 2973 } 2974 2975 value = value.substr(4) + value.substr(0, 4); 2976 value = $.map(value.split(''), function(n) { 2977 var code = n.charCodeAt(0); 2978 return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0)) 2979 // Replace A, B, C, ..., Z with 10, 11, ..., 35 2980 ? (code - 'A'.charCodeAt(0) + 10) 2981 : n; 2982 }); 2983 value = value.join(''); 2984 2985 var temp = parseInt(value.substr(0, 1), 10), 2986 length = value.length; 2987 for (var i = 1; i < length; ++i) { 2988 temp = (temp * 10 + parseInt(value.substr(i, 1), 10)) % 97; 2989 } 2990 2991 return { 2992 valid: (temp === 1), 2993 message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.iban.country, $.fn.bootstrapValidator.i18n.iban.countries[country]) 2994 }; 2995 } 2996 }; 2997}(window.jQuery)); 2998;(function($) { 2999 $.fn.bootstrapValidator.i18n.id = $.extend($.fn.bootstrapValidator.i18n.id || {}, { 3000 'default': 'Please enter a valid identification number', 3001 countryNotSupported: 'The country code %s is not supported', 3002 country: 'Please enter a valid %s identification number', 3003 countries: { 3004 BA: 'Bosnia and Herzegovina', 3005 BG: 'Bulgarian', 3006 BR: 'Brazilian', 3007 CH: 'Swiss', 3008 CL: 'Chilean', 3009 CZ: 'Czech', 3010 DK: 'Danish', 3011 EE: 'Estonian', 3012 ES: 'Spanish', 3013 FI: 'Finnish', 3014 HR: 'Croatian', 3015 IE: 'Irish', 3016 IS: 'Iceland', 3017 LT: 'Lithuanian', 3018 LV: 'Latvian', 3019 ME: 'Montenegro', 3020 MK: 'Macedonian', 3021 NL: 'Dutch', 3022 RO: 'Romanian', 3023 RS: 'Serbian', 3024 SE: 'Swedish', 3025 SI: 'Slovenian', 3026 SK: 'Slovak', 3027 SM: 'San Marino', 3028 ZA: 'South African' 3029 } 3030 }); 3031 3032 $.fn.bootstrapValidator.validators.id = { 3033 html5Attributes: { 3034 message: 'message', 3035 country: 'country' 3036 }, 3037 3038 // Supported country codes 3039 COUNTRY_CODES: [ 3040 'BA', 'BG', 'BR', 'CH', 'CL', 'CZ', 'DK', 'EE', 'ES', 'FI', 'HR', 'IE', 'IS', 'LT', 'LV', 'ME', 'MK', 'NL', 3041 'RO', 'RS', 'SE', 'SI', 'SK', 'SM', 'ZA' 3042 ], 3043 3044 /** 3045 * Validate identification number in different countries 3046 * 3047 * @see http://en.wikipedia.org/wiki/National_identification_number 3048 * @param {BootstrapValidator} validator The validator plugin instance 3049 * @param {jQuery} $field Field element 3050 * @param {Object} options Consist of key: 3051 * - message: The invalid message 3052 * - country: The ISO 3166-1 country code. It can be 3053 * - One of country code defined in COUNTRY_CODES 3054 * - Name of field which its value defines the country code 3055 * - Name of callback function that returns the country code 3056 * - A callback function that returns the country code 3057 * @returns {Boolean|Object} 3058 */
3059 validate: function(validator, $field, options) { 3060 var value = $field.val(); 3061 if (value === '') { 3062 return true; 3063 } 3064 3065 var country = options.country; 3066 if (!country) { 3067 country = value.substr(0, 2); 3068 } else if (typeof country !== 'string' || $.inArray(country.toUpperCase(), this.COUNTRY_CODES) === -1) { 3069 // Determine the country code 3070 country = validator.getDynamicOption($field, country); 3071 } 3072 3073 if ($.inArray(country, this.COUNTRY_CODES) === -1) { 3074 return { valid: false, message: $.fn.bootstrapValidator.helpers.format($.fn.bootstrapValidator.i18n.id.countryNotSupported, country) }; 3075 } 3076 3077 var method = ['_', country.toLowerCase()].join(''); 3078 return this[method](value) 3079 ? true 3080 : { 3081 valid: false, 3082 message: $.fn.bootstrapValidator.helpers.format(
3082options.message || $.fn.bootstrapValidator.i18n.id.country, $.fn.bootstrapValidator.i18n.id.countries[country.toUpperCase()]) 3083 }; 3084 }, 3085 3086 /** 3087 * Validate Unique Master Citizen Number which uses in 3088 * - Bosnia and Herzegovina (country code: BA) 3089 * - Macedonia (MK) 3090 * - Montenegro (ME) 3091 * - Serbia (RS) 3092 * - Slovenia (SI) 3093 * 3094 * @see http://en.wikipedia.org/wiki/Unique_Master_Citizen_Number 3095 * @param {String} value The ID 3096 * @param {String} countryCode The ISO country code, can be BA, MK, ME, RS, SI 3097 * @returns {Boolean} 3098 */ 3099 _validateJMBG: function(value, countryCode) { 3100 if (!/^\d{13}$/.test(value)) { 3101 return false; 3102 } 3103 var day = parseInt(value.substr(0, 2), 10), 3104 month = parseInt(value.substr(2, 2), 10), 3105 year = parseInt(value.substr(4, 3), 10), 3106 rr = parseInt(value.substr(7, 2), 10), 3107 k = parseInt(value.substr(12, 1), 10); 3108 3109 // Validate date of birth 3110 // FIXME: Validate the year of birth 3111 if (day > 31 || month > 12) { 3112 return false; 3113 } 3114 3115 // Validate checksum 3116 var sum = 0; 3117 for (var i = 0; i < 6; i++) { 3118 sum += (7 - i) * (parseInt(value.charAt(i), 10) + parseInt(value.charAt(i + 6), 10)); 3119 } 3120 sum = 11 - sum % 11; 3121 if (sum === 10 || sum === 11) { 3122 sum = 0; 3123 } 3124 if (sum !== k) { 3125 return false; 3126 } 3127 3128 // Validate political region 3129 // rr is the political region of birth, which can be in ranges: 3130 // 10-19: Bosnia and Herzegovina 3131 // 20-29: Montenegro 3132 // 30-39: Croatia (not used anymore) 3133 // 41-49: Macedonia 3134 // 50-59: Slovenia (only 50 is used) 3135 // 70-79: Central Serbia 3136 // 80-89: Serbian province of Vojvodina 3137 // 90-99: Kosovo 3138 switch (countryCode.toUpperCase()) { 3139 case 'BA': 3140 return (10 <= rr && rr <= 19); 3141 case 'MK': 3142 return (41 <= rr && rr <= 49); 3143 case 'ME': 3144 return (20 <= rr && rr <= 29); 3145 case 'RS': 3146 return (70 <= rr && rr <= 99); 3147 case 'SI': 3148 return (50 <= rr && rr <= 59); 3149 default: 3150 return true; 3151 } 3152 }, 3153 3154 _ba: function(value) { 3155 return this._validateJMBG(value, 'BA'); 3156 }, 3157 _mk: function(value) { 3158 return this._validateJMBG(value, 'MK'); 3159 }, 3160 _me: function(value) { 3161 return this._validateJMBG(value, 'ME'); 3162 }, 3163 _rs: function(value) { 3164 return this._validateJMBG(value, 'RS'); 3165 }, 3166 3167 /** 3168 * Examples: 0101006500006 3169 */ 3170 _si: function(value) { 3171 return this._validateJMBG(value, 'SI'); 3172 }, 3173 3174 /** 3175 * Validate Bulgarian national identification number (EGN) 3176 * Examples: 3177 * - Valid: 7523169263, 8032056031, 803205 603 1, 8001010008, 7501020018, 7552010005, 7542011030 3178 * - Invalid: 8019010008 3179 * 3180 * @see http://en.wikipedia.org/wiki/Uniform_civil_number 3181 * @param {String} value The ID 3182 * @returns {Boolean} 3183 */ 3184 _bg: function(value) { 3185 if (!/^\d{10}$/.test(value) && !/^\d{6}\s\d{3}\s\d{1}$/.test(value)) { 3186 return false; 3187 } 3188 value = value.replace(/\s/g, ''); 3189 // Check the birth date 3190 var year = parseInt(value.substr(0, 2), 10) + 1900, 3191 month = parseInt(value.substr(2, 2), 10), 3192 day = parseInt(value.substr(4, 2), 10); 3193 if (month > 40) { 3194 year += 100; 3195 month -= 40; 3196 } else if (month > 20) { 3197 year -= 100; 3198 month -= 20; 3199 } 3200 3201 if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { 3202 return false;
3203 } 3204 3205 var sum = 0, 3206 weight = [2, 4, 8, 5, 10, 9, 7, 3, 6]; 3207 for (var i = 0; i < 9; i++) { 3208 sum += parseInt(value.charAt(i), 10) * weight[i]; 3209 } 3210 sum = (sum % 11) % 10; 3211 return (sum + '' === value.substr(9, 1)); 3212 }, 3213 3214 /** 3215 * Validate Brazilian national identification number (CPF) 3216 * Examples: 3217 * - Valid: 39053344705, 390.533.447-05, 111.444.777-35 3218 * - Invalid: 231.002.999-00 3219 * 3220 * @see http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas 3221 * @param {String} value The ID 3222 * @returns {Boolean} 3223 */ 3224 _br: function(value) { 3225 if (/^1{11}|2{11}|3{11}|4{11}|5{11}|6{11}|7{11}|8{11}|9{11}|0{11}$/.test(value)) { 3226 return false; 3227 } 3228 if (!/^\d{11}$/.test(value) && !/^\d{3}\.\d{3}\.\d{3}-\d{2}$/.test(value)) { 3229 return false; 3230 } 3231 value = value.replace(/\./g, '').replace(/-/g, ''); 3232 3233 var d1 = 0; 3234 for (var i = 0; i < 9; i++) { 3235 d1 += (10 - i) * parseInt(value.charAt(i), 10); 3236 } 3237 d1 = 11 - d1 % 11; 3238 if (d1 === 10 || d1 === 11) { 3239 d1 = 0; 3240 } 3241 if (d1 + '' !== value.charAt(9)) { 3242 return false; 3243 } 3244 3245 var d2 = 0; 3246 for (i = 0; i < 10; i++) { 3247 d2 += (11 - i) * parseInt(value.charAt(i), 10); 3248 } 3249 d2 = 11 - d2 % 11; 3250 if (d2 === 10 || d2 === 11) { 3251 d2 = 0; 3252 } 3253 3254 return (d2 + '' === value.charAt(10)); 3255 }, 3256 3257 /** 3258 * Validate Swiss Social Security Number (AHV-Nr/No AVS) 3259 * Examples: 3260 * - Valid: 756.1234.5678.95, 7561234567895 3261 * 3262 * @see http://en.wikipedia.org/wiki/National_identification_number#Switzerland 3263 * @see http://www.bsv.admin.ch/themen/ahv/00011/02185/index.html?lang=de 3264 * @param {String} value The ID 3265 * @returns {Boolean} 3266 */ 3267 _ch: function(value) { 3268 if (!/^756[\.]{0,1}[0-9]{4}[\.]{0,1}[0-9]{4}[\.]{0,1}[0-9]{2}$/.test(value)) { 3269 return false; 3270 } 3271 value = value.replace(/\D/g, '').substr(3); 3272 var length = value.length, 3273 sum = 0, 3274 weight = (length === 8) ? [3, 1] : [1, 3]; 3275 for (var i = 0; i < length - 1; i++) { 3276 sum += parseInt(value.charAt(i), 10) * weight[i % 2]; 3277 } 3278 sum = 10 - sum % 10; 3279 return (sum + '' === value.charAt(length - 1)); 3280 }, 3281 3282 /** 3283 * Validate Chilean national identification number (RUN/RUT) 3284 * Examples: 3285 * - Valid: 76086428-5, 22060449-7, 12531909-2 3286 * 3287 * @see http://en.wikipedia.org/wiki/National_identification_number#Chile 3288 * @see https://palena.sii.cl/cvc/dte/ee_empresas_emisoras.html for samples 3289 * @param {String} value The ID 3290 * @returns {Boolean} 3291 */ 3292 _cl: function(value) { 3293 if (!/^\d{7,8}[-]{0,1}[0-9K]$/i.test(value)) { 3294 return false; 3295 } 3296 value = value.replace(/\-/g, ''); 3297 while (value.length < 9) { 3298 value = '0' + value; 3299 } 3300 var sum = 0, 3301 weight = [3, 2, 7, 6, 5, 4, 3, 2]; 3302 for (var i = 0; i < 8; i++) { 3303 sum += parseInt(value.charAt(i), 10) * weight[i]; 3304 } 3305 sum = 11 - sum % 11; 3306 if (sum === 11) { 3307 sum = 0; 3308 } else if (sum === 10) { 3309 sum = 'K'; 3310 } 3311 return sum + '' === value.charAt(8).toUpperCase(); 3312 }, 3313 3314 /** 3315 * Validate Czech national identification number (RC) 3316 * Examples: 3317 * - Valid: 7103192745, 991231123 3318 * - Invalid: 1103492745, 590312123 3319 * 3320 * @param {String} value The ID 3321 * @returns {Boolean} 3322 */ 3323 _cz: function(value) { 3324 if (!/^\d{9,10}$/.test(value)) { 3325 return false;
3326 } 3327 var year = 1900 + parseInt(value.substr(0, 2), 10), 3328 month = parseInt(value.substr(2, 2), 10) % 50 % 20, 3329 day = parseInt(value.substr(4, 2), 10); 3330 if (value.length === 9) { 3331 if (year >= 1980) { 3332 year -= 100; 3333 } 3334 if (year > 1953) { 3335 return false; 3336 } 3337 } else if (year < 1954) { 3338 year += 100; 3339 } 3340 3341 if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { 3342 return false; 3343 } 3344 3345 // Check that the birth date is not in the future 3346 if (value.length === 10) { 3347 var check = parseInt(value.substr(0, 9), 10) % 11; 3348 if (year < 1985) { 3349 check = check % 10; 3350 } 3351 return (check + '' === value.substr(9, 1)); 3352 } 3353 3354 return true; 3355 }, 3356 3357 /** 3358 * Validate Danish Personal Identification number (CPR) 3359 * Examples: 3360 * - Valid: 2110625629, 211062-5629 3361 * - Invalid: 511062-5629 3362 * 3363 * @see https://en.wikipedia.org/wiki/Personal_identification_number_(Denmark) 3364 * @param {String} value The ID 3365 * @returns {Boolean} 3366 */ 3367 _dk: function(value) { 3368 if (!/^[0-9]{6}[-]{0,1}[0-9]{4}$/.test(value)) { 3369 return false; 3370 } 3371 value = value.replace(/-/g, ''); 3372 var day = parseInt(value.substr(0, 2), 10), 3373 month = parseInt(value.substr(2, 2), 10), 3374 year = parseInt(value.substr(4, 2), 10); 3375 3376 switch (true) { 3377 case ('5678'.indexOf(value.charAt(6)) !== -1 && year >= 58): 3378 year += 1800; 3379 break; 3380 case ('0123'.indexOf(value.charAt(6)) !== -1): 3381 case ('49'.indexOf(value.charAt(6)) !== -1 && year >= 37): 3382 year += 1900; 3383 break; 3384 default: 3385 year += 2000; 3386 break; 3387 } 3388 3389 return $.fn.bootstrapValidator.helpers.date(year, month, day); 3390 }, 3391 3392 /** 3393 * Validate Estonian Personal Identification Code (isikukood) 3394 * Examples: 3395 * - Valid: 37605030299 3396 * 3397 * @see http://et.wikipedia.org/wiki/Isikukood 3398 * @param {String} value The ID 3399 * @returns {Boolean} 3400 */ 3401 _ee: function(value) { 3402 // Use the same format as Lithuanian Personal Code 3403 return this._lt(value); 3404 }, 3405 3406 /** 3407 * Validate Spanish personal identity code (DNI) 3408 * Support i) DNI (for Spanish citizens) and ii) NIE (for foreign people) 3409 * 3410 * Examples: 3411 * - Valid: i) 54362315K, 54362315-K; ii) X2482300W, X-2482300W, X-2482300-W 3412 * - Invalid: i) 54362315Z; ii) X-2482300A 3413 * 3414 * @see https://en.wikipedia.org/wiki/National_identification_number#Spain 3415 * @param {String} value The ID 3416 * @returns {Boolean} 3417 */ 3418 _es: function(value) { 3419 if (!/^[0-9A-Z]{8}[-]{0,1}[0-9A-Z]$/.test(value) // DNI 3420 && !/^[XYZ][-]{0,1}[0-9]{7}[-]{0,1}[0-9A-Z]$/.test(value)) { // NIE 3421 return false; 3422 } 3423 3424 value = value.replace(/-/g, ''); 3425 var index = 'XYZ'.indexOf(value.charAt(0)); 3426 if (index !== -1) { 3427 // It is NIE number 3428 value = index + value.substr(1) + ''; 3429 } 3430 3431 var check = parseInt(value.substr(0, 8), 10); 3432 check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; 3433 return (check === value.substr(8, 1)); 3434 }, 3435 3436 /** 3437 * Validate Finnish Personal Identity Code (HETU) 3438 * Examples: 3439 * - Valid: 311280-888Y, 131052-308T 3440 * - Invalid: 131052-308U, 310252-308Y 3441 * 3442 * @param {String} value The ID 3443 * @returns {Boolean} 3444 */ 3445 _fi: function(value) { 3446 if (!/^[0-9]{6}[-+A][0-9]{3}[0-9ABCDEFHJKLMNPRSTUVWXY]$/.test(value)) { 3447 return false;
3448 } 3449 var day = parseInt(value.substr(0, 2), 10), 3450 month = parseInt(value.substr(2, 2), 10), 3451 year = parseInt(value.substr(4, 2), 10), 3452 centuries = { 3453 '+': 1800, 3454 '-': 1900, 3455 'A': 2000 3456 }; 3457 year = centuries[value.charAt(6)] + year; 3458 3459 if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { 3460 return false; 3461 } 3462 3463 var individual = parseInt(value.substr(7, 3), 10); 3464 if (individual < 2) { 3465 return false; 3466 } 3467 var n = value.substr(0, 6) + value.substr(7, 3) + ''; 3468 n = parseInt(n, 10); 3469 return '0123456789ABCDEFHJKLMNPRSTUVWXY'.charAt(n % 31) === value.charAt(10); 3470 }, 3471 3472 /** 3473 * Validate Croatian personal identification number (OIB) 3474 * Examples: 3475 * - Valid: 33392005961 3476 * - Invalid: 33392005962 3477 * 3478 * @param {String} value The ID 3479 * @returns {Boolean} 3480 */ 3481 _hr: function(value) { 3482 if (!/^[0-9]{11}$/.test(value)) { 3483 return false; 3484 } 3485 return $.fn.bootstrapValidator.helpers.mod11And10(value); 3486 }, 3487 3488 /** 3489 * Validate Irish Personal Public Service Number (PPS) 3490 * Examples: 3491 * - Valid: 6433435F, 6433435FT, 6433435FW, 6433435OA, 6433435IH, 1234567TW, 1234567FA 3492 * - Invalid: 6433435E, 6433435VH 3493 * 3494 * @see https://en.wikipedia.org/wiki/Personal_Public_Service_Number 3495 * @param {String} value The ID 3496 * @returns {Boolean} 3497 */ 3498 _ie: function(value) { 3499 if (!/^\d{7}[A-W][AHWTX]?$/.test(value)) { 3500 return false; 3501 } 3502 3503 var getCheckDigit = function(value) { 3504 while (value.length < 7) { 3505 value = '0' + value; 3506 } 3507 var alphabet = 'WABCDEFGHIJKLMNOPQRSTUV', 3508 sum = 0; 3509 for (var i = 0; i < 7; i++) { 3510 sum += parseInt(value.charAt(i), 10) * (8 - i); 3511 } 3512 sum += 9 * alphabet.indexOf(value.substr(7)); 3513 return alphabet[sum % 23]; 3514 }; 3515 3516 // 2013 format 3517 if (value.length === 9 && ('A' === value.charAt(8) || 'H' === value.charAt(8))) { 3518 return value.charAt(7) === getCheckDigit(value.substr(0, 7) + value.substr(8) + ''); 3519 } 3520 // The old format 3521 else { 3522 return value.charAt(7) === getCheckDigit(value.substr(0, 7)); 3523 } 3524 }, 3525 3526 /** 3527 * Validate Iceland national identification number (Kennitala) 3528 * Examples: 3529 * - Valid: 120174-3399, 1201743399, 0902862349 3530 * 3531 * @see http://en.wikipedia.org/wiki/Kennitala 3532 * @param {String} value The ID 3533 * @returns {Boolean} 3534 */ 3535 _is: function(value) { 3536 if (!/^[0-9]{6}[-]{0,1}[0-9]{4}$/.test(value)) { 3537 return false; 3538 } 3539 value = value.replace(/-/g, ''); 3540 var day = parseInt(value.substr(0, 2), 10), 3541 month = parseInt(value.substr(2, 2), 10), 3542 year = parseInt(value.substr(4, 2), 10), 3543 century = parseInt(value.charAt(9), 10); 3544 3545 year = (century === 9) ? (1900 + year) : ((20 + century) * 100 + year); 3546 if (!$.fn.bootstrapValidator.helpers.date(year, month, day, true)) { 3547 return false; 3548 } 3549 // Validate the check digit 3550 var sum = 0, 3551 weight = [3, 2, 7, 6, 5, 4, 3, 2]; 3552 for (var i = 0; i < 8; i++) { 3553 sum += parseInt(value.charAt(i), 10) * weight[i]; 3554 } 3555 sum = 11 - sum % 11; 3556 return (sum + '' === value.charAt(8)); 3557 }, 3558 3559 /** 3560 * Validate Lithuanian Personal Code (Asmens kodas) 3561 * Examples: 3562 * - Valid: 38703181745 3563 * - Invalid: 38703181746, 78703181745, 38703421745 3564 * 3565 * @see http://en.wikipedia.org/wiki/National_identification_number#Lithuania 3566 * @see http://www.adomas.org/midi2007/pcode.html 3567 * @param {String} value The ID 3568 * @returns {Boolean} 3569 */ 3570 _lt: function(value) { 3571 if (!/^[0-9]{11}$/.test(value)) { 3572 return false;
3573 } 3574 var gender = parseInt(value.charAt(0), 10), 3575 year = parseInt(value.substr(1, 2), 10), 3576 month = parseInt(value.substr(3, 2), 10), 3577 day = parseInt(value.substr(5, 2), 10), 3578 century = (gender % 2 === 0) ? (17 + gender / 2) : (17 + (gender + 1) / 2); 3579 year = century * 100 + year; 3580 if (!$.fn.bootstrapValidator.helpers.date(year, month, day, true)) { 3581 return false; 3582 } 3583 3584 // Validate the check digit 3585 var sum = 0, 3586 weight = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1]; 3587 for (var i = 0; i < 10; i++) { 3588 sum += parseInt(value.charAt(i), 10) * weight[i]; 3589 } 3590 sum = sum % 11; 3591 if (sum !== 10) { 3592 return sum + '' === value.charAt(10); 3593 } 3594 3595 // Re-calculate the check digit 3596 sum = 0; 3597 weight = [3, 4, 5, 6, 7, 8, 9, 1, 2, 3]; 3598 for (i = 0; i < 10; i++) { 3599 sum += parseInt(value.charAt(i), 10) * weight[i]; 3600 } 3601 sum = sum % 11; 3602 if (sum === 10) { 3603 sum = 0; 3604 } 3605 return (sum + '' === value.charAt(10)); 3606 }, 3607 3608 /** 3609 * Validate Latvian Personal Code (Personas kods) 3610 * Examples: 3611 * - Valid: 161175-19997, 16117519997 3612 * - Invalid: 161375-19997 3613 * 3614 * @see http://laacz.lv/2006/11/25/pk-parbaudes-algoritms/ 3615 * @param {String} value The ID 3616 * @returns {Boolean} 3617 */ 3618 _lv: function(value) { 3619 if (!/^[0-9]{6}[-]{0,1}[0-9]{5}$/.test(value)) { 3620 return false; 3621 } 3622 value = value.replace(/\D/g, ''); 3623 // Check birth date 3624 var day = parseInt(value.substr(0, 2), 10), 3625 month = parseInt(value.substr(2, 2), 10), 3626 year = parseInt(value.substr(4, 2), 10); 3627 year = year + 1800 + parseInt(value.charAt(6), 10) * 100; 3628 3629 if (!$.fn.bootstrapValidator.helpers.date(year, month, day, true)) { 3630 return false; 3631 } 3632 3633 // Check personal code 3634 var sum = 0, 3635 weight = [10, 5, 8, 4, 2, 1, 6, 3, 7, 9]; 3636 for (var i = 0; i < 10; i++) { 3637 sum += parseInt(value.charAt(i), 10) * weight[i]; 3638 } 3639 sum = (sum + 1) % 11 % 10; 3640 return (sum + '' === value.charAt(10)); 3641 }, 3642 3643 /** 3644 * Validate Dutch national identification number (BSN) 3645 * Examples: 3646 * - Valid: 111222333, 941331490, 9413.31.490 3647 * - Invalid: 111252333 3648 * 3649 * @see https://nl.wikipedia.org/wiki/Burgerservicenummer 3650 * @param {String} value The ID 3651 * @returns {Boolean} 3652 */ 3653 _nl: function(value) { 3654 while (value.length < 9) { 3655 value = '0' + value; 3656 } 3657 if (!/^[0-9]{4}[.]{0,1}[0-9]{2}[.]{0,1}[0-9]{3}$/.test(value)) { 3658 return false; 3659 } 3660 value = value.replace(/\./g, ''); 3661 if (parseInt(value, 10) === 0) { 3662 return false; 3663 } 3664 var sum = 0, 3665 length = value.length; 3666 for (var i = 0; i < length - 1; i++) { 3667 sum += (9 - i) * parseInt(value.charAt(i), 10); 3668 } 3669 sum = sum % 11; 3670 if (sum === 10) { 3671 sum = 0; 3672 } 3673 return (sum + '' === value.charAt(length - 1)); 3674 }, 3675 3676 /** 3677 * Validate Romanian numerical personal code (CNP) 3678 * Examples: 3679 * - Valid: 1630615123457, 1800101221144 3680 * - Invalid: 8800101221144, 1632215123457, 1630615123458 3681 * 3682 * @see http://en.wikipedia.org/wiki/National_identification_number#Romania 3683 * @param {String} value The ID 3684 * @returns {Boolean} 3685 */ 3686 _ro: function(value) { 3687 if (!/^[0-9]{13}$/.test(value)) { 3688 return false;
3689 } 3690 var gender = parseInt(value.charAt(0), 10); 3691 if (gender === 0 || gender === 7 || gender === 8) { 3692 return false; 3693 } 3694 3695 // Determine the date of birth 3696 var year = parseInt(value.substr(1, 2), 10), 3697 month = parseInt(value.substr(3, 2), 10), 3698 day = parseInt(value.substr(5, 2), 10), 3699 // The year of date is determined base on the gender 3700 centuries = { 3701 '1': 1900, // Male born between 1900 and 1999 3702 '2': 1900, // Female born between 1900 and 1999 3703 '3': 1800, // Male born between 1800 and 1899 3704 '4': 1800, // Female born between 1800 and 1899 3705 '5': 2000, // Male born after 2000 3706 '6': 2000 // Female born after 2000 3707 }; 3708 if (day > 31 && month > 12) { 3709 return false; 3710 } 3711 if (gender !== 9) { 3712 year = centuries[gender + ''] + year; 3713 if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { 3714 return false; 3715 } 3716 } 3717 3718 // Validate the check digit 3719 var sum = 0, 3720 weight = [2, 7, 9, 1, 4, 6, 3, 5, 8, 2, 7, 9], 3721 length = value.length; 3722 for (var i = 0; i < length - 1; i++) { 3723 sum += parseInt(value.charAt(i), 10) * weight[i]; 3724 } 3725 sum = sum % 11; 3726 if (sum === 10) { 3727 sum = 1; 3728 } 3729 return (sum + '' === value.charAt(length - 1)); 3730 }, 3731 3732 /** 3733 * Validate Swedish personal identity number (personnummer) 3734 * Examples: 3735 * - Valid: 8112289874, 811228-9874, 811228+9874 3736 * - Invalid: 811228-9873 3737 * 3738 * @see http://en.wikipedia.org/wiki/Personal_identity_number_(Sweden) 3739 * @param {String} value The ID 3740 * @returns {Boolean} 3741 */ 3742 _se: function(value) { 3743 if (!/^[0-9]{10}$/.test(value) && !/^[0-9]{6}[-|+][0-9]{4}$/.test(value)) { 3744 return false; 3745 } 3746 value = value.replace(/[^0-9]/g, ''); 3747 3748 var year = parseInt(value.substr(0, 2), 10) + 1900, 3749 month = parseInt(value.substr(2, 2), 10), 3750 day = parseInt(value.substr(4, 2), 10); 3751 if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { 3752 return false; 3753 } 3754 3755 // Validate the last check digit 3756 return $.fn.bootstrapValidator.helpers.luhn(value); 3757 }, 3758 3759 /** 3760 * Validate Slovak national identifier number (RC) 3761 * Examples: 3762 * - Valid: 7103192745, 991231123 3763 * - Invalid: 7103192746, 1103492745 3764 * 3765 * @param {String} value The ID 3766 * @returns {Boolean} 3767 */ 3768 _sk: function(value) { 3769 // Slovakia uses the same format as Czech Republic 3770 return this._cz(value); 3771 }, 3772 3773 /** 3774 * Validate San Marino citizen number 3775 * 3776 * @see http://en.wikipedia.org/wiki/National_identification_number#San_Marino 3777 * @param {String} value The ID 3778 * @returns {Boolean} 3779 */ 3780 _sm: function(value) { 3781 return /^\d{5}$/.test(value); 3782 }, 3783 3784 /** 3785 * Validate South African ID 3786 * Example: 3787 * - Valid: 8001015009087 3788 * - Invalid: 8001015009287, 8001015009086 3789 * 3790 * @see http://en.wikipedia.org/wiki/National_identification_number#South_Africa 3791 * @param {String} value The ID 3792 * @returns {Boolean} 3793 */ 3794 _za: function(value) { 3795 if (!/^[0-9]{10}[0|1][8|9][0-9]$/.test(value)) { 3796 return false; 3797 } 3798 var year = parseInt(value.substr(0, 2), 10), 3799 currentYear = new Date().getFullYear() % 100, 3800 month = parseInt(value.substr(2, 2), 10), 3801 day = parseInt(value.substr(4, 2), 10); 3802 year = (year >= currentYear) ? (year + 1900) : (year + 2000); 3803 3804 if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { 3805 return false;
3806 } 3807 3808 // Validate the last check digit 3809 return $.fn.bootstrapValidator.helpers.luhn(value); 3810 } 3811 }; 3812}(window.jQuery)); 3813;(function($) { 3814 $.fn.bootstrapValidator.i18n.identical = $.extend($.fn.bootstrapValidator.i18n.identical || {}, { 3815 'default': 'Please enter the same value' 3816 }); 3817 3818 $.fn.bootstrapValidator.validators.identical = { 3819 html5Attributes: { 3820 message: 'message', 3821 field: 'field' 3822 }, 3823 3824 /** 3825 * Check if input value equals to value of particular one 3826 * 3827 * @param {BootstrapValidator} validator The validator plugin instance 3828 * @param {jQuery} $field Field element 3829 * @param {Object} options Consists of the following key: 3830 * - field: The name of field that will be used to compare with current one 3831 * @returns {Boolean} 3832 */ 3833 validate: function(validator, $field, options) { 3834 var value = $field.val(); 3835 if (value === '') { 3836 return true; 3837 } 3838 3839 var compareWith = validator.getFieldElements(options.field); 3840 if (compareWith === null) { 3841 return true; 3842 } 3843 3844 if (value === compareWith.val()) { 3845 validator.updateStatus(options.field, validator.STATUS_VALID, 'identical'); 3846 return true; 3847 } else { 3848 return false; 3849 } 3850 } 3851 }; 3852}(window.jQuery)); 3853;(function($) { 3854 $.fn.bootstrapValidator.i18n.imei = $.extend($.fn.bootstrapValidator.i18n.imei || {}, { 3855 'default': 'Please enter a valid IMEI number' 3856 }); 3857 3858 $.fn.bootstrapValidator.validators.imei = { 3859 /** 3860 * Validate IMEI (International Mobile Station Equipment Identity) 3861 * Examples: 3862 * - Valid: 35-209900-176148-1, 35-209900-176148-23, 3568680000414120, 490154203237518 3863 * - Invalid: 490154203237517 3864 * 3865 * @see http://en.wikipedia.org/wiki/International_Mobile_Station_Equipment_Identity 3866 * @param {BootstrapValidator} validator The validator plugin instance 3867 * @param {jQuery} $field Field element 3868 * @param {Object} options Can consist of the following keys: 3869 * - message: The invalid message 3870 * @returns {Boolean} 3871 */ 3872 validate: function(validator, $field, options) { 3873 var value = $field.val(); 3874 if (value === '') { 3875 return true; 3876 } 3877 3878 switch (true) { 3879 case /^\d{15}$/.test(value): 3880 case /^\d{2}-\d{6}-\d{6}-\d{1}$/.test(value): 3881 case /^\d{2}\s\d{6}\s\d{6}\s\d{1}$/.test(value): 3882 value = value.replace(/[^0-9]/g, ''); 3883 return $.fn.bootstrapValidator.helpers.luhn(value); 3884 3885 case /^\d{14}$/.test(value): 3886 case /^\d{16}$/.test(value): 3887 case /^\d{2}-\d{6}-\d{6}(|-\d{2})$/.test(value): 3888 case /^\d{2}\s\d{6}\s\d{6}(|\s\d{2})$/.test(value): 3889 return true; 3890 3891 default: 3892 return false; 3893 } 3894 } 3895 }; 3896}(window.jQuery)); 3897;(function($) { 3898 $.fn.bootstrapValidator.i18n.integer = $.extend($.fn.bootstrapValidator.i18n.integer || {}, { 3899 'default': 'Please enter a valid number' 3900 }); 3901 3902 $.fn.bootstrapValidator.validators.integer = { 3903 enableByHtml5: function($field) { 3904 return ('number' === $field.attr('type')) && ($field.attr('step') === undefined || $field.attr('step') % 1 === 0); 3905 }, 3906 3907 /** 3908 * Return true if the input value is an integer 3909 * 3910 * @param {BootstrapValidator} validator The validator plugin instance 3911 * @param {jQuery} $field Field element 3912 * @param {Object} options Can consist of the following key: 3913 * - message: The invalid message 3914 * @returns {Boolean} 3915 */ 3916 validate: function(validator, $field, options) { 3917 var value = $field.val(); 3918 if (value === '') { 3919 return true; 3920 } 3921 return /^(?:-?(?:0|[1-9][0-9]*))$/.test(value); 3922 } 3923 }; 3924}(window.jQuery)); 3925;(function($) { 3926 $.fn.bootstrapValidator.i18n.ip = $.extend($.fn.bootstrapValidator.i18n.ip || {}, { 3927 'default': 'Please enter a valid IP address', 3928 ipv4: 'Please enter a valid IPv4 address', 3929 ipv6: 'Please enter a valid IPv6 address' 3930 }); 3931 3932 $.fn.bootstrapValidator.validators.ip = { 3933 html5Attributes: { 3934 message: 'message', 3935 ipv4: 'ipv4', 3936 ipv6: 'ipv6' 3937 }, 3938 3939 /** 3940 * Return true if the input value is a IP address. 3941 * 3942 * @param {BootstrapValidator} validator The validator plugin instance 3943 * @param {jQuery} $field Field element 3944 * @param {Object} options Can consist of the following keys: 3945 * - ipv4: Enable IPv4 validator, default to true 3946 * - ipv6: Enable IPv6 validator, default to true 3947 * - message: The invalid message 3948 * @returns {Boolean|Object} 3949 */
3950 validate: function(validator, $field, options) { 3951 var value = $field.val(); 3952 if (value === '') { 3953 return true; 3954 } 3955 options = $.extend({}, { ipv4: true, ipv6: true }, options); 3956 3957 if (options.ipv4) { 3958 return { 3959 valid: /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/.test(value), 3960 message: options.message || $.fn.bootstrapValidator.i18n.ip.ipv4 3961 }; 3962 } else if (options.ipv6) { 3963 return { 3964 valid: /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/.test(value), 3965 message: options.message || $.fn.bootstrapValidator.i18n.ip.ipv6 3966 }; 3967 } 3968 3969 return false; 3970 } 3971 }; 3972}(window.jQuery)); 3973;(function($) { 3974 $.fn.bootstrapValidator.i18n.isbn = $.extend($.fn.bootstrapValidator.i18n.isbn || {}, { 3975 'default': 'Please enter a valid ISBN number' 3976 }); 3977 3978 $.fn.bootstrapValidator.validators.isbn = { 3979 /** 3980 * Return true if the input value is a valid ISBN 10 or ISBN 13 number 3981 * Examples: 3982 * - Valid: 3983 * 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 3984 * ISBN 13: 978-0-306-40615-7 3985 * - Invalid: 3986 * ISBN 10: 99921-58-10-6 3987 * ISBN 13: 978-0-306-40615-6 3988 * 3989 * @see http://en.wikipedia.org/wiki/International_Standard_Book_Number 3990 * @param {BootstrapValidator} validator The validator plugin instance 3991 * @param {jQuery} $field Field element 3992 * @param {Object} [options] Can consist of the following keys: 3993 * - message: The invalid message 3994 * @returns {Boolean} 3995 */ 3996 validate: function(validator, $field, options) { 3997 var value = $field.val(); 3998 if (value === '') { 3999 return true; 4000 } 4001 4002 // http://en.wikipedia.org/wiki/International_Standard_Book_Number#Overview 4003 // Groups are separated by a hyphen or a space 4004 var type; 4005 switch (true) { 4006 case /^\d{9}[\dX]$/.test(value): 4007 case (value.length === 13 && /^(\d+)-(\d+)-(\d+)-([\dX])$/.test(value)): 4008 case (value.length === 13 && /^(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(value)): 4009 type = 'ISBN10'; 4010 break; 4011 case /^(978|979)\d{9}[\dX]$/.test(value): 4012 case (value.length === 17 && /^(978|979)-(\d+)-(\d+)-(\d+)-([\dX])$/.test(value)): 4013 case (value.length === 17 && /^(978|979)\s(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(value)): 4014 type = 'ISBN13'; 4015 break; 4016 default: 4017 return false; 4018 } 4019 4020 // Replace all special characters except digits and X 4021 value = value.replace(/[^0-9X]/gi, ''); 4022 var chars = value.split(''), 4023 length = chars.length, 4024 sum = 0, 4025 i, 4026 checksum; 4027 4028 switch (type) { 4029 case 'ISBN10': 4030 sum = 0; 4031 for (i = 0; i < length - 1; i++) { 4032 sum += parseInt(chars[i], 10) * (10 - i); 4033 } 4034 checksum = 11 - (sum % 11); 4035 if (checksum === 11) { 4036 checksum = 0; 4037 } else if (checksum === 10) { 4038 checksum = 'X'; 4039 } 4040 return (checksum + '' === chars[length - 1]); 4041 4042 case 'ISBN13': 4043 sum = 0; 4044 for (i = 0; i < length - 1; i++) { 4045 sum += ((i % 2 === 0) ? parseInt(chars[i], 10) : (parseInt(chars[i], 10) * 3)); 4046 } 4047 checksum = 10 - (sum % 10); 4048 if (checksum === 10) { 4049 checksum = '0'; 4050 } 4051 return (checksum + '' === chars[length - 1]); 4052 4053 default: 4054 return false;
4055 } 4056 } 4057 }; 4058}(window.jQuery)); 4059;(function($) { 4060 $.fn.bootstrapValidator.i18n.isin = $.extend($.fn.bootstrapValidator.i18n.isin || {}, { 4061 'default': 'Please enter a valid ISIN number' 4062 }); 4063 4064 $.fn.bootstrapValidator.validators.isin = { 4065 // Available country codes 4066 // See http://isin.net/country-codes/ 4067 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', 4068 4069 /** 4070 * Validate an ISIN (International Securities Identification Number) 4071 * Examples: 4072 * - Valid: US0378331005, AU0000XVGZA3, GB0002634946 4073 * - Invalid: US0378331004, AA0000XVGZA3 4074 * 4075 * @see http://en.wikipedia.org/wiki/International_Securities_Identifying_Number 4076 * @param {BootstrapValidator} validator The validator plugin instance 4077 * @param {jQuery} $field Field element 4078 * @param {Object} options Can consist of the following keys: 4079 * - message: The invalid message 4080 * @returns {Boolean} 4081 */ 4082 validate: function(validator, $field, options) { 4083 var value = $field.val(); 4084 if (value === '') { 4085 return true; 4086 } 4087 4088 value = value.toUpperCase(); 4089 var regex = new RegExp('^(' + this.COUNTRY_CODES + ')[0-9A-Z]{10}$'); 4090 if (!regex.test(value)) { 4091 return false; 4092 } 4093 4094 var converted = '', 4095 length = value.length; 4096 // Convert letters to number 4097 for (var i = 0; i < length - 1; i++) { 4098 var c = value.charCodeAt(i); 4099 converted += ((c > 57) ? (c - 55).toString() : value.charAt(i)); 4100 } 4101 4102 var digits = '', 4103 n = converted.length, 4104 group = (n % 2 !== 0) ? 0 : 1; 4105 for (i = 0; i < n; i++) { 4106 digits += (parseInt(converted[i], 10) * ((i % 2) === group ? 2 : 1) + ''); 4107 } 4108 4109 var sum = 0; 4110 for (i = 0; i < digits.length; i++) { 4111 sum += parseInt(digits.charAt(i), 10); 4112 } 4113 sum = (10 - (sum % 10)) % 10; 4114 return sum + '' === value.charAt(length - 1); 4115 } 4116 }; 4117}(window.jQuery)); 4118;(function($) { 4119 $.fn.bootstrapValidator.i18n.ismn = $.extend($.fn.bootstrapValidator.i18n.ismn || {}, { 4120 'default': 'Please enter a valid ISMN number' 4121 }); 4122 4123 $.fn.bootstrapValidator.validators.ismn = { 4124 /** 4125 * Validate ISMN (International Standard Music Number) 4126 * Examples: 4127 * - Valid: M230671187, 979-0-0601-1561-5, 979 0 3452 4680 5, 9790060115615 4128 * - Invalid: 9790060115614 4129 * 4130 * @see http://en.wikipedia.org/wiki/International_Standard_Music_Number 4131 * @param {BootstrapValidator} validator The validator plugin instance 4132 * @param {jQuery} $field Field element 4133 * @param {Object} options Can consist of the following keys: 4134 * - message: The invalid message 4135 * @returns {Boolean} 4136 */ 4137 validate: function(validator, $field, options) { 4138 var value = $field.val(); 4139 if (value === '') { 4140 return true; 4141 } 4142 4143 // Groups are separated by a hyphen or a space 4144 var type; 4145 switch (true) { 4146 case /^M\d{9}$/.test(value): 4147 case /^M-\d{4}-\d{4}-\d{1}$/.test(value): 4148 case /^M\s\d{4}\s\d{4}\s\d{1}$/.test(value): 4149 type = 'ISMN10'; 4150 break; 4151 case /^9790\d{9}$/.test(value): 4152 case /^979-0-\d{4}-\d{4}-\d{1}$/.test(value): 4153 case /^979\s0\s\d{4}\s\d{4}\s\d{1}$/.test(value): 4154 type = 'ISMN13'; 4155 break; 4156 default: 4157 return false;
4158 } 4159 4160 if ('ISMN10' === type) { 4161 value = '9790' + value.substr(1); 4162 } 4163 4164 // Replace all special characters except digits 4165 value = value.replace(/[^0-9]/gi, ''); 4166 var length = value.length, 4167 sum = 0, 4168 weight = [1, 3]; 4169 for (var i = 0; i < length - 1; i++) { 4170 sum += parseInt(value.charAt(i), 10) * weight[i % 2]; 4171 } 4172 sum = 10 - sum % 10; 4173 return (sum + '' === value.charAt(length - 1)); 4174 } 4175 }; 4176}(window.jQuery)); 4177;(function($) { 4178 $.fn.bootstrapValidator.i18n.issn = $.extend($.fn.bootstrapValidator.i18n.issn || {}, { 4179 'default': 'Please enter a valid ISSN number' 4180 }); 4181 4182 $.fn.bootstrapValidator.validators.issn = { 4183 /** 4184 * Validate ISSN (International Standard Serial Number) 4185 * Examples: 4186 * - Valid: 0378-5955, 0024-9319, 0032-1478 4187 * - Invalid: 0032-147X 4188 * 4189 * @see http://en.wikipedia.org/wiki/International_Standard_Serial_Number 4190 * @param {BootstrapValidator} validator The validator plugin instance 4191 * @param {jQuery} $field Field element 4192 * @param {Object} options Can consist of the following keys: 4193 * - message: The invalid message 4194 * @returns {Boolean} 4195 */ 4196 validate: function(validator, $field, options) { 4197 var value = $field.val(); 4198 if (value === '') { 4199 return true; 4200 } 4201 4202 // Groups are separated by a hyphen or a space 4203 if (!/^\d{4}\-\d{3}[\dX]$/.test(value)) { 4204 return false; 4205 } 4206 4207 // Replace all special characters except digits and X 4208 value = value.replace(/[^0-9X]/gi, ''); 4209 var chars = value.split(''), 4210 length = chars.length, 4211 sum = 0; 4212 4213 if (chars[7] === 'X') { 4214 chars[7] = 10; 4215 } 4216 for (var i = 0; i < length; i++) { 4217 sum += parseInt(chars[i], 10) * (8 - i); 4218 } 4219 return (sum % 11 === 0); 4220 } 4221 }; 4222}(window.jQuery)); 4223;(function($) { 4224 $.fn.bootstrapValidator.i18n.lessThan = $.extend($.fn.bootstrapValidator.i18n.lessThan || {}, { 4225 'default': 'Please enter a value less than or equal to %s', 4226 notInclusive: 'Please enter a value less than %s' 4227 }); 4228 4229 $.fn.bootstrapValidator.validators.lessThan = { 4230 html5Attributes: { 4231 message: 'message', 4232 value: 'value', 4233 inclusive: 'inclusive' 4234 }, 4235 4236 enableByHtml5: function($field) { 4237 var max = $field.attr('max'); 4238 if (max) { 4239 return { 4240 value: max 4241 }; 4242 } 4243 4244 return false; 4245 }, 4246 4247 /** 4248 * Return true if the input value is less than or equal to given number 4249 * 4250 * @param {BootstrapValidator} validator The validator plugin instance 4251 * @param {jQuery} $field Field element 4252 * @param {Object} options Can consist of the following keys: 4253 * - value: The number used to compare to. It can be 4254 * - A number 4255 * - Name of field which its value defines the number 4256 * - Name of callback function that returns the number 4257 * - A callback function that returns the number 4258 * 4259 * - inclusive [optional]: Can be true or false. Default is true 4260 * - message: The invalid message 4261 * @returns {Boolean|Object} 4262 */ 4263 validate: function(validator, $field, options) { 4264 var value = $field.val(); 4265 if (value === '') { 4266 return true; 4267 } 4268 4269 var compareTo = $.isNumeric(options.value) ? options.value : validator.getDynamicOption($field, options.value); 4270 4271 value = parseFloat(value); 4272 return (options.inclusive === true || options.inclusive === undefined) 4273 ? { 4274 valid: value <= compareTo,
4275 message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.lessThan['default'], compareTo) 4276 } 4277 : { 4278 valid: value < compareTo, 4279 message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.lessThan.notInclusive, compareTo) 4280 }; 4281 } 4282 }; 4283}(window.jQuery)); 4284;(function($) { 4285 $.fn.bootstrapValidator.i18n.mac = $.extend($.fn.bootstrapValidator.i18n.mac || {}, { 4286 'default': 'Please enter a valid MAC address' 4287 }); 4288 4289 $.fn.bootstrapValidator.validators.mac = { 4290 /** 4291 * Return true if the input value is a MAC address. 4292 * 4293 * @param {BootstrapValidator} validator The validator plugin instance 4294 * @param {jQuery} $field Field element 4295 * @param {Object} options Can consist of the following keys: 4296 * - message: The invalid message 4297 * @returns {Boolean} 4298 */ 4299 validate: function(validator, $field, options) { 4300 var value = $field.val(); 4301 if (value === '') { 4302 return true; 4303 } 4304 4305 return /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value); 4306 } 4307 }; 4308}(window.jQuery)); 4309;(function($) { 4310 $.fn.bootstrapValidator.i18n.notEmpty = $.extend($.fn.bootstrapValidator.i18n.notEmpty || {}, { 4311 'default': 'Please enter a value' 4312 }); 4313 4314 $.fn.bootstrapValidator.validators.notEmpty = { 4315 enableByHtml5: function($field) { 4316 var required = $field.attr('required') + ''; 4317 return ('required' === required || 'true' === required); 4318 }, 4319 4320 /** 4321 * Check if input value is empty or not 4322 * 4323 * @param {BootstrapValidator} validator The validator plugin instance 4324 * @param {jQuery} $field Field element 4325 * @param {Object} options 4326 * @returns {Boolean} 4327 */ 4328 validate: function(validator, $field, options) { 4329 var type = $field.attr('type'); 4330 if ('radio' === type || 'checkbox' === type) { 4331 return validator 4332 .getFieldElements($field.attr('data-bv-field')) 4333 .filter(':checked') 4334 .length > 0; 4335 } 4336 4337 return $.trim($field.val()) !== ''; 4338 } 4339 }; 4340}(window.jQuery)); 4341;(function($) { 4342 $.fn.bootstrapValidator.i18n.numeric = $.extend($.fn.bootstrapValidator.i18n.numeric || {}, { 4343 'default': 'Please enter a valid float number' 4344 }); 4345 4346 $.fn.bootstrapValidator.validators.numeric = { 4347 html5Attributes: { 4348 message: 'message', 4349 separator: 'separator' 4350 }, 4351 4352 enableByHtml5: function($field) { 4353 return ('number' === $field.attr('type')) && ($field.attr('step') !== undefined) && ($field.attr('step') % 1 !== 0); 4354 }, 4355 4356 /** 4357 * Validate decimal number 4358 * 4359 * @param {BootstrapValidator} validator The validator plugin instance 4360 * @param {jQuery} $field Field element 4361 * @param {Object} options Consist of key: 4362 * - message: The invalid message 4363 * - separator: The decimal separator. Can be "." (default), "," 4364 * @returns {Boolean} 4365 */ 4366 validate: function(validator, $field, options) { 4367 var value = $field.val(); 4368 if (value === '') { 4369 return true; 4370 } 4371 var separator = options.separator || '.'; 4372 if (separator !== '.') { 4373 value = value.replace(separator, '.'); 4374 } 4375 4376 return !isNaN(parseFloat(value)) && isFinite(value); 4377 } 4378 }; 4379}(window.jQuery)); 4380;(function($) { 4381 $.fn.bootstrapValidator.i18n.phone = $.extend($.fn.bootstrapValidator.i18n.phone || {}, { 4382 'default': 'Please enter a valid phone number', 4383 countryNotSupported: 'The country code %s is not supported', 4384 country: 'Please enter a valid phone number in %s', 4385 countries: { 4386 GB: 'United Kingdom', 4387 US: 'USA' 4388 } 4389 }); 4390 4391 $.fn.bootstrapValidator.validators.phone = { 4392 html5Attributes: { 4393 message: 'message', 4394 country: 'country' 4395 }, 4396 4397 // The supported countries 4398 COUNTRY_CODES: ['GB', 'US'], 4399 4400 /** 4401 * Return true if the input value contains a valid phone number for the country 4402 * selected in the options 4403 * 4404 * @param {BootstrapValidator} validator Validate plugin instance 4405 * @param {jQuery} $field Field element 4406 * @param {Object} options Consist of key: 4407 * - message: The invalid message 4408 * - country: The ISO-3166 country code. It can be 4409 * - A country code 4410 * - Name of field which its value defines the country code 4411 * - Name of callback function that returns the country code 4412 * - A callback function that returns the country code 4413 * 4414 * Currently it only supports United State (US) or United Kingdom (GB) countries 4415 * @returns {Boolean|Object} 4416 */
4417 validate: function(validator, $field, options) { 4418 var value = $field.val(); 4419 if (value === '') { 4420 return true; 4421 } 4422 4423 var country = options.country; 4424 if (typeof country !== 'string' || $.inArray(country, this.COUNTRY_CODES) === -1) { 4425 // Try to determine the country 4426 country = validator.getDynamicOption($field, country); 4427 } 4428 4429 if (!country || $.inArray(country.toUpperCase(), this.COUNTRY_CODES) === -1) { 4430 return { 4431 valid: false, 4432 message: $.fn.bootstrapValidator.helpers.format($.fn.bootstrapValidator.i18n.phone.countryNotSupported, country) 4433 }; 4434 } 4435 4436 var isValid = true; 4437 switch (country.toUpperCase()) { 4438 case 'GB': 4439 // http://aa-asterisk.org.uk/index.php/Regular_Expressions_for_Validating_and_Formatting_GB_Telephone_Numbers#Match_GB_telephone_number_in_any_format 4440 // Test: http://regexr.com/38uhv 4441 value = $.trim(value); 4442 isValid = (/^\(?(?:(?:0(?:0|11)\)?[\s-]?\(?|\+)44\)?[\s-]?\(?(?:0\)?[\s-]?\(?)?|0)(?:\d{2}\)?[\s-]?\d{4}[\s-]?\d{4}|\d{3}\)?[\s-]?\d{3}[\s-]?\d{3,4}|\d{4}\)?[\s-]?(?:\d{5}|\d{3}[\s-]?\d{3})|\d{5}\)?[\s-]?\d{4,5}|8(?:00[\s-]?11[\s-]?11|45[\s-]?46[\s-]?4\d))(?:(?:[\s-]?(?:x|ext\.?\s?|\#)\d+)?)$/).test(value); 4443 break; 4444 4445 case 'US': 4446 /* falls through */ 4447 default: 4448 // Make sure US phone numbers have 10 digits 4449 // May start with 1, +1, or 1-; should discard 4450 // Area code may be delimited with (), & sections may be delimited with . or - 4451 // Test: http://regexr.com/38mqi 4452 value = value.replace(/\D/g, ''); 4453 isValid = (/^(?:(1\-?)|(\+1 ?))?\(?(\d{3})[\)\-\.]?(\d{3})[\-\.]?(\d{4})$/).test(value) && (value.length === 10); 4454 break; 4455 } 4456 4457 return { 4458 valid: isValid, 4459 message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.phone.country, $.fn.bootstrapValidator.i18n.phone.countries[country]) 4460 }; 4461 } 4462 }; 4463}(window.jQuery)); 4464;(function($) { 4465 $.fn.bootstrapValidator.i18n.regexp = $.extend($.fn.bootstrapValidator.i18n.regexp || {}, { 4466 'default': 'Please enter a value matching the pattern' 4467 }); 4468 4469 $.fn.bootstrapValidator.validators.regexp = { 4470 html5Attributes: { 4471 message: 'message', 4472 regexp: 'regexp' 4473 }, 4474 4475 enableByHtml5: function($field) { 4476 var pattern = $field.attr('pattern'); 4477 if (pattern) { 4478 return { 4479 regexp: pattern 4480 }; 4481 } 4482 4483 return false; 4484 }, 4485 4486 /** 4487 * Check if the element value matches given regular expression 4488 * 4489 * @param {BootstrapValidator} validator The validator plugin instance 4490 * @param {jQuery} $field Field element 4491 * @param {Object} options Consists of the following key: 4492 * - regexp: The regular expression you need to check 4493 * @returns {Boolean} 4494 */ 4495 validate: function(validator, $field, options) { 4496 var value = $field.val(); 4497 if (value === '') { 4498 return true; 4499 } 4500 4501 var regexp = ('string' === typeof options.regexp) ? new RegExp(options.regexp) : options.regexp; 4502 return regexp.test(value); 4503 } 4504 }; 4505}(window.jQuery)); 4506;(function($) { 4507 $.fn.bootstrapValidator.i18n.remote = $.extend($.fn.bootstrapValidator.i18n.remote || {}, { 4508 'default': 'Please enter a valid value' 4509 }); 4510 4511 $.fn.bootstrapValidator.validators.remote = { 4512 html5Attributes: { 4513 message: 'message', 4514 url: 'url', 4515 name: 'name' 4516 }, 4517 4518 /** 4519 * Request a remote server to check the input value 4520 * 4521 * @param {BootstrapValidator} validator Plugin instance 4522 * @param {jQuery} $field Field element 4523 * @param {Object} options Can consist of the following keys: 4524 * - url {String|Function} 4525 * - type {String} [optional] Can be GET or POST (default) 4526 * - data {Object|Function} [optional]: By default, it will take the value 4527 * { 4528 * <fieldName>: <fieldValue> 4529 * } 4530 * - name {String} [optional]: Override the field name for the request. 4531 * - message: The invalid message 4532 * @returns {Boolean|Deferred} 4533 */
4534 validate: function(validator, $field, options) { 4535 var value = $field.val(); 4536 if (value === '') { 4537 return true; 4538 } 4539 4540 var name = $field.attr('data-bv-field'), 4541 data = options.data || {}, 4542 url = options.url, 4543 type = options.type || 'POST'; 4544 4545 // Support dynamic data 4546 if ('function' === typeof data) { 4547 data = data.call(this, validator); 4548 } 4549 4550 // Support dynamic url 4551 if ('function' === typeof url) { 4552 url = url.call(this, validator); 4553 } 4554 4555 data[options.name || name] = value; 4556 4557 var dfd = new $.Deferred(); 4558 var xhr = $.ajax({ 4559 type: type, 4560 url: url, 4561 dataType: 'json', 4562 data: data 4563 }); 4564 xhr.then(function(response) { 4565 dfd.resolve($field, 'remote', response.valid === true || response.valid === 'true', response.message ? response.message : null); 4566 }); 4567 4568 dfd.fail(function() { 4569 xhr.abort(); 4570 }); 4571 4572 return dfd; 4573 } 4574 }; 4575}(window.jQuery)); 4576;(function($) { 4577 $.fn.bootstrapValidator.i18n.rtn = $.extend($.fn.bootstrapValidator.i18n.rtn || {}, { 4578 'default': 'Please enter a valid RTN number' 4579 }); 4580 4581 $.fn.bootstrapValidator.validators.rtn = { 4582 /** 4583 * Validate a RTN (Routing transit number) 4584 * Examples: 4585 * - Valid: 021200025, 789456124 4586 * 4587 * @see http://en.wikipedia.org/wiki/Routing_transit_number 4588 * @param {BootstrapValidator} validator The validator plugin instance 4589 * @param {jQuery} $field Field element 4590 * @param {Object} options Can consist of the following keys: 4591 * - message: The invalid message 4592 * @returns {Boolean} 4593 */ 4594 validate: function(validator, $field, options) { 4595 var value = $field.val(); 4596 if (value === '') { 4597 return true; 4598 } 4599 4600 if (!/^\d{9}$/.test(value)) { 4601 return false; 4602 } 4603 4604 var sum = 0; 4605 for (var i = 0; i < value.length; i += 3) { 4606 sum += parseInt(value.charAt(i), 10) * 3 4607 + parseInt(value.charAt(i + 1), 10) * 7 4608 + parseInt(value.charAt(i + 2), 10); 4609 } 4610 return (sum !== 0 && sum % 10 === 0); 4611 } 4612 }; 4613}(window.jQuery)); 4614;(function($) { 4615 $.fn.bootstrapValidator.i18n.sedol = $.extend($.fn.bootstrapValidator.i18n.sedol || {}, { 4616 'default': 'Please enter a valid SEDOL number' 4617 }); 4618 4619 $.fn.bootstrapValidator.validators.sedol = { 4620 /** 4621 * Validate a SEDOL (Stock Exchange Daily Official List) 4622 * Examples: 4623 * - Valid: 0263494, B0WNLY7 4624 * 4625 * @see http://en.wikipedia.org/wiki/SEDOL 4626 * @param {BootstrapValidator} validator The validator plugin instance 4627 * @param {jQuery} $field Field element 4628 * @param {Object} options Can consist of the following keys: 4629 * - message: The invalid message 4630 * @returns {Boolean} 4631 */ 4632 validate: function(validator, $field, options) { 4633 var value = $field.val(); 4634 if (value === '') { 4635 return true; 4636 } 4637 4638 value = value.toUpperCase(); 4639 if (!/^[0-9A-Z]{7}$/.test(value)) { 4640 return false; 4641 } 4642 4643 var sum = 0, 4644 weight = [1, 3, 1, 7, 3, 9, 1], 4645 length = value.length; 4646 for (var i = 0; i < length - 1; i++) { 4647 sum += weight[i] * parseInt(value.charAt(i), 36); 4648 } 4649 sum = (10 - sum % 10) % 10; 4650 return sum + '' === value.charAt(length - 1); 4651 } 4652 }; 4653}(window.jQuery)); 4654;(function($) { 4655 $.fn.bootstrapValidator.i18n.siren = $.extend($.fn.bootstrapValidator.i18n.siren || {}, { 4656 'default': 'Please enter a valid SIREN number' 4657 }); 4658 4659 $.fn.bootstrapValidator.validators.siren = { 4660 /** 4661 * Check if a string is a siren number 4662 * 4663 * @param {BootstrapValidator} validator The validator plugin instance 4664 * @param {jQuery} $field Field element 4665 * @param {Object} options Consist of key: 4666 * - message: The invalid message 4667 * @returns {Boolean} 4668 */
4669 validate: function(validator, $field, options) { 4670 var value = $field.val(); 4671 if (value === '') { 4672 return true; 4673 } 4674 4675 if (!/^\d{9}$/.test(value)) { 4676 return false; 4677 } 4678 return $.fn.bootstrapValidator.helpers.luhn(value); 4679 } 4680 }; 4681}(window.jQuery)); 4682;(function($) { 4683 $.fn.bootstrapValidator.i18n.siret = $.extend($.fn.bootstrapValidator.i18n.siret || {}, { 4684 'default': 'Please enter a valid SIRET number' 4685 }); 4686 4687 $.fn.bootstrapValidator.validators.siret = { 4688 /** 4689 * Check if a string is a siret number 4690 * 4691 * @param {BootstrapValidator} validator The validator plugin instance 4692 * @param {jQuery} $field Field element 4693 * @param {Object} options Consist of key: 4694 * - message: The invalid message 4695 * @returns {Boolean} 4696 */ 4697 validate: function(validator, $field, options) { 4698 var value = $field.val(); 4699 if (value === '') { 4700 return true; 4701 } 4702 4703 var sum = 0, 4704 length = value.length, 4705 tmp; 4706 for (var i = 0; i < length; i++) { 4707 tmp = parseInt(value.charAt(i), 10); 4708 if ((i % 2) === 0) { 4709 tmp = tmp * 2; 4710 if (tmp > 9) { 4711 tmp -= 9; 4712 } 4713 } 4714 sum += tmp; 4715 } 4716 return (sum % 10 === 0); 4717 } 4718 }; 4719}(window.jQuery)); 4720;(function($) { 4721 $.fn.bootstrapValidator.i18n.step = $.extend($.fn.bootstrapValidator.i18n.step || {}, { 4722 'default': 'Please enter a valid step of %s' 4723 }); 4724 4725 $.fn.bootstrapValidator.validators.step = { 4726 html5Attributes: { 4727 message: 'message', 4728 base: 'baseValue', 4729 step: 'step' 4730 }, 4731 4732 /** 4733 * Return true if the input value is valid step one 4734 * 4735 * @param {BootstrapValidator} validator The validator plugin instance 4736 * @param {jQuery} $field Field element 4737 * @param {Object} options Can consist of the following keys: 4738 * - baseValue: The base value 4739 * - step: The step 4740 * - message: The invalid message 4741 * @returns {Boolean|Object} 4742 */ 4743 validate: function(validator, $field, options) { 4744 var value = $field.val(); 4745 if (value === '') { 4746 return true; 4747 } 4748 4749 options = $.extend({}, { baseValue: 0, step: 1 }, options); 4750 value = parseFloat(value); 4751 if (!$.isNumeric(value)) { 4752 return false; 4753 } 4754 4755 var round = function(x, precision) { 4756 var m = Math.pow(10, precision); 4757 x = x * m; 4758 var sign = (x > 0) | -(x < 0), 4759 isHalf = (x % 1 === 0.5 * sign); 4760 if (isHalf) { 4761 return (Math.floor(x) + (sign > 0)) / m; 4762 } else { 4763 return Math.round(x) / m; 4764 } 4765 }, 4766 floatMod = function(x, y) { 4767 if (y === 0.0) { 4768 return 1.0; 4769 } 4770 var dotX = (x + '').split('.'), 4771 dotY = (y + '').split('.'), 4772 precision = ((dotX.length === 1) ? 0 : dotX[1].length) + ((dotY.length === 1) ? 0 : dotY[1].length); 4773 return round(x - y * Math.floor(x / y), precision); 4774 }; 4775 4776 var mod = floatMod(value - options.baseValue, options.step); 4777 return { 4778 valid: mod === 0.0 || mod === options.step, 4779 message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.step['default'], [options.step]) 4780 }; 4781 } 4782 }; 4783}(window.jQuery)); 4784;(function($) { 4785 $.fn.bootstrapValidator.i18n.stringCase = $.extend($.fn.bootstrapValidator.i18n.stringCase || {}, { 4786 'default': 'Please enter only lowercase characters', 4787 upper: 'Please enter only uppercase characters' 4788 }); 4789 4790 $.fn.bootstrapValidator.validators.stringCase = { 4791 html5Attributes: { 4792 message: 'message', 4793 'case': 'case' 4794 }, 4795 4796 /** 4797 * Check if a string is a lower or upper case one 4798 * 4799 * @param {BootstrapValidator} validator The validator plugin instance 4800 * @param {jQuery} $field Field element 4801 * @param {Object} options Consist of key: 4802 * - message: The invalid message 4803 * - case: Can be 'lower' (default) or 'upper' 4804 * @returns {Object} 4805 */
4806 validate: function(validator, $field, options) { 4807 var value = $field.val(); 4808 if (value === '') { 4809 return true; 4810 } 4811 4812 var stringCase = (options['case'] || 'lower').toLowerCase(); 4813 return { 4814 valid: ('upper' === stringCase) ? value === value.toUpperCase() : value === value.toLowerCase(), 4815 message: options.message || (('upper' === stringCase) ? $.fn.bootstrapValidator.i18n.stringCase.upper : $.fn.bootstrapValidator.i18n.stringCase['default']) 4816 }; 4817 } 4818 }; 4819}(window.jQuery)); 4820;(function($) { 4821 $.fn.bootstrapValidator.i18n.stringLength = $.extend($.fn.bootstrapValidator.i18n.stringLength || {}, { 4822 'default': 'Please enter a value with valid length', 4823 less: 'Please enter less than %s characters', 4824 more: 'Please enter more than %s characters', 4825 between: 'Please enter value between %s and %s characters long' 4826 }); 4827 4828 $.fn.bootstrapValidator.validators.stringLength = { 4829 html5Attributes: { 4830 message: 'message', 4831 min: 'min', 4832 max: 'max' 4833 }, 4834 4835 enableByHtml5: function($field) { 4836 var maxLength = $field.attr('maxlength'); 4837 if (maxLength) { 4838 return { 4839 max: parseInt(maxLength, 10) 4840 }; 4841 } 4842 4843 return false; 4844 }, 4845 4846 /** 4847 * Check if the length of element value is less or more than given number 4848 * 4849 * @param {BootstrapValidator} validator The validator plugin instance 4850 * @param {jQuery} $field Field element 4851 * @param {Object} options Consists of following keys: 4852 * - min 4853 * - max 4854 * At least one of two keys is required 4855 * The min, max keys define the number which the field value compares to. min, max can be 4856 * - A number 4857 * - Name of field which its value defines the number 4858 * - Name of callback function that returns the number 4859 * - A callback function that returns the number 4860 * 4861 * - message: The invalid message 4862 * @returns {Object} 4863 */ 4864 validate: function(validator, $field, options) { 4865 var value = $field.val(); 4866 if (value === '') { 4867 return true; 4868 } 4869 4870 var min = $.isNumeric(options.min) ? options.min : validator.getDynamicOption($field, options.min), 4871 max = $.isNumeric(options.max) ? options.max : validator.getDynamicOption($field, options.max), 4872 length = value.length, 4873 isValid = true, 4874 message = options.message || $.fn.bootstrapValidator.i18n.stringLength['default']; 4875 4876 if ((min && length < parseInt(min, 10)) || (max && length > parseInt(max, 10))) { 4877 isValid = false; 4878 } 4879 4880 switch (true) { 4881 case (!!min && !!max): 4882 message = $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.stringLength.between, [parseInt(min, 10), parseInt(max, 10)]); 4883 break; 4884 4885 case (!!min): 4886 message = $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.stringLength.more, parseInt(min, 10)); 4887 break; 4888 4889 case (!!max): 4890 message = $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.stringLength.less, parseInt(max, 10)); 4891 break; 4892 4893 default: 4894 break; 4895 } 4896 4897 return { valid: isValid, message: message }; 4898 } 4899 }; 4900}(window.jQuery)); 4901;(function($) { 4902 $.fn.bootstrapValidator.i18n.uri = $.extend($.fn.bootstrapValidator.i18n.uri || {}, { 4903 'default': 'Please enter a valid URI' 4904 }); 4905 4906 $.fn.bootstrapValidator.validators.uri = { 4907 html5Attributes: { 4908 message: 'message', 4909 allowlocal: 'allowLocal' 4910 }, 4911 4912 enableByHtml5: function($field) { 4913 return ('url' === $field.attr('type')); 4914 }, 4915 4916 /** 4917 * Return true if the input value is a valid URL 4918 * 4919 * @param {BootstrapValidator} validator The validator plugin instance 4920 * @param {jQuery} $field Field element 4921 * @param {Object} options 4922 * - message: The error message 4923 * - allowLocal: Allow the private and local network IP. Default to false 4924 * @returns {Boolean} 4925 */
4926 validate: function(validator, $field, options) { 4927 var value = $field.val(); 4928 if (value === '') { 4929 return true; 4930 } 4931 4932 // Credit to https://gist.github.com/dperini/729294 4933 // 4934 // Regular Expression for URL validation 4935 // 4936 // Author: Diego Perini 4937 // Updated: 2010/12/05 4938 // 4939 // the regular expression composed & commented 4940 // could be easily tweaked for RFC compliance, 4941 // it was expressly modified to fit & satisfy 4942 // these test for an URL shortener: 4943 // 4944 // http://mathiasbynens.be/demo/url-regex 4945 // 4946 // Notes on possible differences from a standard/generic validation: 4947 // 4948 // - utf-8 char class take in consideration the full Unicode range 4949 // - TLDs have been made mandatory so single names like "localhost" fails 4950 // - protocols have been restricted to ftp, http and https only as requested 4951 // 4952 // Changes: 4953 // 4954 // - IP address dotted notation validation, range: 1.0.0.0 - 223.255.255.255 4955 // first and last IP address of each class is considered invali
4955d 4956 // (since they are broadcast/network addresses) 4957 // 4958 // - Added exclusion of private, reserved and/or local networks ranges 4959 // 4960 var allowLocal = options.allowLocal === true || options.allowLocal === 'true', 4961 urlExp = new RegExp( 4962 "^" + 4963 // protocol identifier 4964 "(?:(?:https?|ftp)://)" + 4965 // user:pass authentication 4966 "(?:\\S+(?::\\S*)?@)?" + 4967 "(?:" + 4968 // IP address exclusion 4969 // private & local networks 4970 (allowLocal 4971 ? '' 4972 : ("(?!(?:10|127)(?:\\.\\d{1,3}){3})" + 4973 "(?!(?:169\\.254|192\\.168)(?:\\.\\d{1,3}){2})" + 4974 "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})")) + 4975 // IP address dotted notation octets 4976 // excludes loopback network 0.0.0.0 4977 // excludes reserved space >= 224.0.0.0 4978 // excludes network & broadcast addresses 4979 // (first & last IP address of each class) 4980 "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" + 4981 "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" + 4982 "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" + 4983 "|" + 4984 // host name 4985 "(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)" + 4986 // domain name 4987 "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*" + 4988 // TLD identifier 4989 "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" + 4990 ")" + 4991 // port number 4992 "(?::\\d{2,5})?" + 4993 // resource path 4994 "(?:/[^\\s]*)?" + 4995 "$", "i" 4996 ); 4997 4998 return urlExp.test(value); 4999 } 5000 }; 5001}(window.jQuery)); 5002;(function($) { 5003 $.fn.bootstrapValidator.i18n.uuid = $.extend($.fn.bootstrapValidator.i18n.uuid || {}, { 5004 'default': 'Please enter a valid UUID number', 5005 version: 'Please enter a valid UUID version %s number' 5006 }); 5007 5008 $.fn.bootstrapValidator.validators.uuid = { 5009 html5Attributes: { 5010 message: 'message', 5011 version: 'version' 5012 }, 5013 5014 /** 5015 * Return true if and only if the input value is a valid UUID string 5016 * 5017 * @see http://en.wikipedia.org/wiki/Universally_unique_identifier 5018 * @param {BootstrapValidator} validator The validator plugin instance 5019 * @param {jQuery} $field Field element 5020 * @param {Object} options Consist of key: 5021 * - message: The invalid message 5022 * - version: Can be 3, 4, 5, null 5023 * @returns {Boolean|Object} 5024 */ 5025 validate: function(validator, $field, options) { 5026 var value = $field.val(); 5027 if (value === '') { 5028 return true; 5029 } 5030 5031 // See the format at http://en.wikipedia.org/wiki/Universally_unique_identifier#Variants_and_versions 5032 var patterns = { 5033 '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i, 5034 '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, 5035 '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i, 5036 all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i 5037 }, 5038 version = options.version ? (options.version + '') : 'all'; 5039 return { 5040 valid: (null === patterns[version]) ? true : patterns[version].test(value), 5041 message: options.version 5042 ? $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.uuid.version, options.version) 5043 : (options.message || $.fn.bootstrapValidator.i18n.uuid['default']) 5044 }; 5045 } 5046 }; 5047}(window.jQuery)); 5048;(function($) { 5049 $.fn.bootstrapValidator.i18n.vat = $.extend($.fn.bootstrapValidator.i18n.vat || {}, { 5050 'default': 'Please enter a valid VAT number', 5051 countryNotSupported: 'The country code %s is not supported', 5052 country: 'Please enter a valid %s VAT number', 5053 countries: { 5054 AT: 'Austrian', 5055 BE: 'Belgian', 5056 BG: 'Bulgarian', 5057 CH: 'Swiss', 5058 CY: 'Cypriot', 5059 CZ: 'Czech', 5060 DE: 'German', 5061 DK: 'Danish', 5062 EE: 'Estonian', 5063 ES: 'Spanish', 5064 FI: 'Finnish', 5065 FR: 'French', 5066 GB: 'United Kingdom', 5067 GR: 'Greek', 5068 EL: 'Greek', 5069 HU: 'Hungarian', 5070 HR: 'Croatian', 5071 IE: 'Irish', 5072 IT: 'Italian', 5073 LT: 'Lithuanian', 5074 LU: 'Luxembourg', 5075 LV: 'Latvian', 5076 MT: 'Maltese', 5077 NL: 'Dutch',
5078 NO: 'Norwegian', 5079 PL: 'Polish', 5080 PT: 'Portuguese', 5081 RO: 'Romanian', 5082 RU: 'Russian', 5083 RS: 'Serbian', 5084 SE: 'Swedish', 5085 SI: 'Slovenian', 5086 SK: 'Slovak' 5087 } 5088 }); 5089 5090 $.fn.bootstrapValidator.validators.vat = { 5091 html5Attributes: { 5092 message: 'message', 5093 country: 'country' 5094 }, 5095 5096 // Supported country codes 5097 COUNTRY_CODES: [ 5098 'AT', 'BE', 'BG', 'HR', 'CY', 'CZ', 'DK', 'EE', 'FI', 'FR', 'DE', 'GR', 'EL', 'HU', 'IE', 'IT', 5099 'LV', 'LT', 'LU', 'MT', 'NL', 'NO', 'PL', 'PT', 'RO', 'RU', 'RS', 'SK', 'SI', 'ES', 'SE', 'CH', 'GB' 5100 ], 5101 5102 /** 5103 * Validate an European VAT number 5104 * 5105 * @param {BootstrapValidator} validator The validator plugin instance 5106 * @param {jQuery} $field Field element 5107 * @param {Object} options Consist of key: 5108 * - message: The invalid message 5109 * - country: The ISO 3166-1 country code. It can be 5110 * - One of country code defined in COUNTRY_CODES 5111 * - Name of field which its value defines the country code 5112 * - Name of callback function that returns the country code 5113 * - A callback function that returns the country code 5114 * @returns {Boolean|Object} 5115 */ 5116 validate: function(validator, $field, options) { 5117 var value = $field.val(); 5118 if (value === '') { 5119 return true; 5120 } 5121 5122 var country = options.country; 5123 if (!country) { 5124 country = value.substr(0, 2); 5125 } else if (typeof country !== 'string' || $.inArray(country.toUpperCase(), this.COUNTRY_CODES) === -1) { 5126 // Determine the country code 5127 country = validator.getDynamicOption($field, country); 5128 } 5129 5130 if ($.inArray(country, this.COUNTRY_CODES) === -1) { 5131 return { 5132 valid: false, 5133 message: $.fn.bootstrapValidator.helpers.format($.fn.bootstrapValidator.i18n.vat.countryNotSupported, country) 5134 }; 5135 } 5136 5137 var method = ['_', country.toLowerCase()].join(''); 5138 return this[method](value) 5139 ? true 5140 : { 5141 valid: false, 5142 message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.vat.country, $.fn.bootstrapValidator.i18n.vat.countries[country.toUpperCase()]) 5143 }; 5144 }, 5145 5146 // VAT validators 5147 5148 /** 5149 * Validate Austrian VAT number 5150 * Example: 5151 * - Valid: ATU13585627 5152 * - Invalid: ATU13585626 5153 * 5154 * @param {String} value VAT number 5155 * @returns {Boolean} 5156 */ 5157 _at: function(value) { 5158 if (!/^ATU[0-9]{8}$/.test(value)) { 5159 return false; 5160 } 5161 5162 value = value.substr(3); 5163 var sum = 0, 5164 weight = [1, 2, 1, 2, 1, 2, 1], 5165 temp = 0; 5166 5167 for (var i = 0; i < 7; i++) { 5168 temp = parseInt(value.charAt(i), 10) * weight[i]; 5169 if (temp > 9) { 5170 temp = Math.floor(temp / 10) + temp % 10; 5171 } 5172 sum += temp; 5173 } 5174 5175 sum = 10 - (sum + 4) % 10; 5176 if (sum === 10) { 5177 sum = 0; 5178 } 5179 5180 return (sum + '' === value.substr(7, 1)); 5181 }, 5182 5183 /** 5184 * Validate Belgian VAT number 5185 * Example: 5186 * - Valid: BE0428759497 5187 * - Invalid: BE431150351 5188 * 5189 * @param {String} value VAT number 5190 * @returns {Boolean} 5191 */ 5192 _be: function(value) { 5193 if (!/^BE[0]{0,1}[0-9]{9}$/.test(value)) { 5194 return false; 5195 } 5196 5197 value = value.substr(2); 5198 if (value.length === 9) { 5199 value = '0' + value; 5200 } 5201 5202 if (value.substr(1, 1) === '0') { 5203 return false;
5204 } 5205 5206 var sum = parseInt(value.substr(0, 8), 10) + parseInt(value.substr(8, 2), 10); 5207 return (sum % 97 === 0); 5208 }, 5209 5210 /** 5211 * Validate Bulgarian VAT number 5212 * Example: 5213 * - Valid: BG175074752, 5214 * BG7523169263, BG8032056031, 5215 * BG7542011030, 5216 * BG7111042925 5217 * - Invalid: BG175074753, BG7552A10004, BG7111042922 5218 * 5219 * @param {String} value VAT number 5220 * @returns {Boolean} 5221 */ 5222 _bg: function(value) { 5223 if (!/^BG[0-9]{9,10}$/.test(value)) { 5224 return false; 5225 } 5226 5227 value = value.substr(2); 5228 var sum = 0, i = 0; 5229 5230 // Legal entities 5231 if (value.length === 9) { 5232 for (i = 0; i < 8; i++) { 5233 sum += parseInt(value.charAt(i), 10) * (i + 1); 5234 } 5235 sum = sum % 11; 5236 if (sum === 10) { 5237 sum = 0; 5238 for (i = 0; i < 8; i++) { 5239 sum += parseInt(value.charAt(i), 10) * (i + 3); 5240 } 5241 } 5242 sum = sum % 10; 5243 return (sum + '' === value.substr(8)); 5244 } 5245 // Physical persons, foreigners and others 5246 else if (value.length === 10) { 5247 // Validate Bulgarian national identification numbers 5248 var egn = function(value) { 5249 // Check the birth date 5250 var year = parseInt(value.substr(0, 2), 10) + 1900, 5251 month = parseInt(value.substr(2, 2), 10), 5252 day = parseInt(value.substr(4, 2), 10); 5253 if (month > 40) { 5254 year += 100; 5255 month -= 40; 5256 } else if (month > 20) { 5257 year -= 100; 5258 month -= 20; 5259 } 5260 5261 if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { 5262 return false; 5263 } 5264 5265 var sum = 0, 5266 weight = [2, 4, 8, 5, 10, 9, 7, 3, 6]; 5267 for (var i = 0; i < 9; i++) { 5268 sum += parseInt(value.charAt(i), 10) * weight[i]; 5269 } 5270 sum = (sum % 11) % 10; 5271 return (sum + '' === value.substr(9, 1)); 5272 }, 5273 // Validate Bulgarian personal number of a foreigner 5274 pnf = function(value) { 5275 var sum = 0, 5276 weight = [21, 19, 17, 13, 11, 9, 7, 3, 1]; 5277 for (var i = 0; i < 9; i++) { 5278 sum += parseInt(value.charAt(i), 10) * weight[i]; 5279 } 5280 sum = sum % 10; 5281 return (sum + '' === value.substr(9, 1)); 5282 }, 5283 // Finally, consider it as a VAT number 5284 vat = function(value) { 5285 var sum = 0, 5286 weight = [4, 3, 2, 7, 6, 5, 4, 3, 2]; 5287 for (var i = 0; i < 9; i++) { 5288 sum += parseInt(value.charAt(i), 10) * weight[i]; 5289 } 5290 sum = 11 - sum % 11; 5291 if (sum === 10) { 5292 return false; 5293 } 5294 if (sum === 11) { 5295 sum = 0; 5296 } 5297 return (sum + '' === value.substr(9, 1)); 5298 }; 5299 return (egn(value) || pnf(value) || vat(value)); 5300 } 5301 5302 return false; 5303 }, 5304 5305 /** 5306 * Validate Swiss VAT number 5307 * 5308 * @param {String} value VAT number 5309 * @returns {Boolean} 5310 */ 5311 _ch: function(value) { 5312 if (!/^CHE[0-9]{9}(MWST)?$/.test(value)) { 5313 return false;
5314 } 5315 5316 value = value.substr(3); 5317 var sum = 0, 5318 weight = [5, 4, 3, 2, 7, 6, 5, 4]; 5319 for (var i = 0; i < 8; i++) { 5320 sum += parseInt(value.charAt(i), 10) * weight[i]; 5321 } 5322 5323 sum = 11 - sum % 11; 5324 if (sum === 10) { 5325 return false; 5326 } 5327 if (sum === 11) { 5328 sum = 0; 5329 } 5330 5331 return (sum + '' === value.substr(8, 1)); 5332 }, 5333 5334 /** 5335 * Validate Cypriot VAT number 5336 * Examples: 5337 * - Valid: CY10259033P 5338 * - Invalid: CY10259033Z 5339 * 5340 * @param {String} value VAT number 5341 * @returns {Boolean} 5342 */ 5343 _cy: function(value) { 5344 if (!/^CY[0-5|9]{1}[0-9]{7}[A-Z]{1}$/.test(value)) { 5345 return false; 5346 } 5347 5348 value = value.substr(2); 5349 5350 // Do not allow to start with "12" 5351 if (value.substr(0, 2) === '12') { 5352 return false; 5353 } 5354 5355 // Extract the next digit and multiply by the counter. 5356 var sum = 0, 5357 translation = { 5358 '0': 1, '1': 0, '2': 5, '3': 7, '4': 9, 5359 '5': 13, '6': 15, '7': 17, '8': 19, '9': 21 5360 }; 5361 for (var i = 0; i < 8; i++) { 5362 var temp = parseInt(value.charAt(i), 10); 5363 if (i % 2 === 0) { 5364 temp = translation[temp + '']; 5365 } 5366 sum += temp; 5367 } 5368 5369 sum = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'[sum % 26]; 5370 return (sum + '' === value.substr(8, 1)); 5371 }, 5372 5373 /** 5374 * Validate Czech Republic VAT number 5375 * Can be: 5376 * i) Legal entities (8 digit numbers) 5377 * ii) Individuals with a RC (the 9 or 10 digit Czech birth number) 5378 * iii) Individuals without a RC (9 digit numbers beginning with 6) 5379 * 5380 * Examples: 5381 * - Valid: i) CZ25123891; ii) CZ7103192745, CZ991231123; iii) CZ640903926 5382 * - Invalid: i) CZ25123890; ii) CZ1103492745, CZ590312123 5383 * 5384 * @param {String} value VAT number 5385 * @returns {Boolean} 5386 */ 5387 _cz: function(value) { 5388 if (!/^CZ[0-9]{8,10}$/.test(value)) { 5389 return false; 5390 } 5391 5392 value = value.substr(2); 5393 5394 var sum = 0, 5395 i = 0; 5396 if (value.length === 8) { 5397 // Do not allow to start with '9' 5398 if (value.charAt(0) + '' === '9') { 5399 return false; 5400 } 5401 5402 sum = 0; 5403 for (i = 0; i < 7; i++) { 5404 sum += parseInt(value.charAt(i), 10) * (8 - i); 5405 } 5406 sum = 11 - sum % 11; 5407 if (sum === 10) { 5408 sum = 0; 5409 } 5410 if (sum === 11) { 5411 sum = 1; 5412 } 5413 5414 return (sum + '' === value.substr(7, 1)); 5415 } else if (value.length === 9 && (value.charAt(0) + '' === '6')) { 5416 sum = 0; 5417 // Skip the first (which is 6) 5418 for (i = 0; i < 7; i++) { 5419 sum += parseInt(value.charAt(i + 1), 10) * (8 - i); 5420 } 5421 sum = 11 - sum % 11; 5422 if (sum === 10) { 5423 sum = 0; 5424 } 5425 if (sum === 11) { 5426 sum = 1; 5427 } 5428 sum = [8, 7, 6, 5, 4, 3, 2, 1, 0, 9, 10][sum - 1]; 5429 return (sum + '' === value.substr(8, 1)); 5430 } else if (value.length === 9 || value.length === 10) { 5431 // Validate Czech birth number (Rodné ÄÃslo), which is also national identifier 5432 var year = 1900 + parseInt(value.substr(0, 2), 10), 5433 month = parseInt(value.substr(2, 2), 10) % 50 % 20, 5434 day = parseInt(value.substr(4, 2), 10); 5435 if (value.length === 9) { 5436 if (year >= 1980) { 5437 year -= 100; 5438 } 5439 if (year > 1953) { 5440 return false;
5441 } 5442 } else if (year < 1954) { 5443 year += 100; 5444 } 5445 5446 if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { 5447 return false; 5448 } 5449 5450 // Check that the birth date is not in the future 5451 if (value.length === 10) { 5452 var check = parseInt(value.substr(0, 9), 10) % 11; 5453 if (year < 1985) { 5454 check = check % 10; 5455 } 5456 return (check + '' === value.substr(9, 1)); 5457 } 5458 5459 return true; 5460 } 5461 5462 return false; 5463 }, 5464 5465 /** 5466 * Validate German VAT number 5467 * Examples: 5468 * - Valid: DE136695976 5469 * - Invalid: DE136695978 5470 * 5471 * @param {String} value VAT number 5472 * @returns {Boolean} 5473 */ 5474 _de: function(value) { 5475 if (!/^DE[0-9]{9}$/.test(value)) { 5476 return false; 5477 } 5478 5479 value = value.substr(2); 5480 return $.fn.bootstrapValidator.helpers.mod11And10(value); 5481 }, 5482 5483 /** 5484 * Validate Danish VAT number 5485 * Example: 5486 * - Valid: DK13585628 5487 * - Invalid: DK13585627 5488 * 5489 * @param {String} value VAT number 5490 * @returns {Boolean} 5491 */ 5492 _dk: function(value) { 5493 if (!/^DK[0-9]{8}$/.test(value)) { 5494 return false; 5495 } 5496 5497 value = value.substr(2); 5498 var sum = 0, 5499 weight = [2, 7, 6, 5, 4, 3, 2, 1]; 5500 for (var i = 0; i < 8; i++) { 5501 sum += parseInt(value.charAt(i), 10) * weight[i]; 5502 } 5503 5504 return (sum % 11 === 0); 5505 }, 5506 5507 /** 5508 * Validate Estonian VAT number 5509 * Examples: 5510 * - Valid: EE100931558, EE100594102 5511 * - Invalid: EE100594103 5512 * 5513 * @param {String} value VAT number 5514 * @returns {Boolean} 5515 */ 5516 _ee: function(value) { 5517 if (!/^EE[0-9]{9}$/.test(value)) { 5518 return false; 5519 } 5520 5521 value = value.substr(2); 5522 var sum = 0, 5523 weight = [3, 7, 1, 3, 7, 1, 3, 7, 1]; 5524 5525 for (var i = 0; i < 9; i++) { 5526 sum += parseInt(value.charAt(i), 10) * weight[i]; 5527 } 5528 5529 return (sum % 10 === 0); 5530 }, 5531 5532 /** 5533 * Validate Spanish VAT number (NIF - Número de Identificación Fiscal) 5534 * Can be: 5535 * i) DNI (Documento nacional de identidad), for Spaniards 5536 * ii) NIE (Número de Identificación de Extranjeros), for foreigners 5537 * iii) CIF (Certificado de Identificación Fiscal), for legal entities and others 5538 * 5539 * Examples: 5540 * - Valid: i) ES54362315K; ii) ESX2482300W, ESX5253868R; iii) ESM1234567L, ESJ99216582, ESB58378431, ESB64717838 5541 * - Invalid: i) ES54362315Z; ii) ESX2482300A; iii) ESJ99216583 5542 * 5543 * @param {String} value VAT number 5544 * @returns {Boolean} 5545 */ 5546 _es: function(value) { 5547 if (!/^ES[0-9A-Z][0-9]{7}[0-9A-Z]$/.test(value)) { 5548 return false; 5549 } 5550 5551 value = value.substr(2); 5552 var dni = function(value) { 5553 var check = parseInt(value.substr(0, 8), 10); 5554 check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; 5555 return (check + '' === value.substr(8, 1)); 5556 }, 5557 nie = function(value) { 5558 var check = ['XYZ'.indexOf(value.charAt(0)), value.substr(1)].join(''); 5559 check = parseInt(check, 10); 5560 check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; 5561 return (check + '' === value.substr(8, 1)); 5562 }, 5563 cif = function(value) { 5564 var first = value.charAt(0), check; 5565 if ('KLM'.indexOf(first) !== -1) { 5566 // K: Spanish younger than 14 year old 5567 // L: Spanish living outside Spain without DNI 5568 // M: Granted the tax to foreigners who have no NIE 5569 check = parseInt(value.substr(1, 8), 10); 5570 check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; 5571 return (check + '' === value.substr(8, 1)); 5572 } else if ('ABCDEFGHJNPQRSUVW'.indexOf(first) !== -1) { 5573 var sum = 0, 5574 weight = [2, 1, 2, 1, 2, 1, 2], 5575 temp = 0; 5576 5577 for (var i = 0; i < 7; i++) { 5578 temp = parseInt(value.charAt(i + 1), 10) * weight[i]; 5579 if (temp > 9) { 5580 temp = Math.floor(temp / 10) + temp % 10; 5581 } 5582 sum += temp; 5583 } 5584 sum = 10 - sum % 10; 5585 return (sum + '' === value.substr(8, 1) || 'JABCDEFGHI'[sum] === value.substr(8, 1)); 5586 } 5587 5588 return false;
5589 }; 5590 5591 var first = value.charAt(0); 5592 if (/^[0-9]$/.test(first)) { 5593 return dni(value); 5594 } else if (/^[XYZ]$/.test(first)) { 5595 return nie(value); 5596 } else { 5597 return cif(value); 5598 } 5599 }, 5600 5601 /** 5602 * Validate Finnish VAT number 5603 * Examples: 5604 * - Valid: FI20774740 5605 * - Invalid: FI20774741 5606 * 5607 * @param {String} value VAT number 5608 * @returns {Boolean} 5609 */ 5610 _fi: function(value) { 5611 if (!/^FI[0-9]{8}$/.test(value)) { 5612 return false; 5613 } 5614 5615 value = value.substr(2); 5616 var sum = 0, 5617 weight = [7, 9, 10, 5, 8, 4, 2, 1]; 5618 5619 for (var i = 0; i < 8; i++) { 5620 sum += parseInt(value.charAt(i), 10) * weight[i]; 5621 } 5622 5623 return (sum % 11 === 0); 5624 }, 5625 5626 /** 5627 * Validate French VAT number (TVA - taxe sur la valeur ajoutée) 5628 * It's constructed by a SIREN number, prefixed by two characters. 5629 * 5630 * Examples: 5631 * - Valid: FR40303265045, FR23334175221, FRK7399859412, FR4Z123456782 5632 * - Invalid: FR84323140391 5633 * 5634 * @param {String} value VAT number 5635 * @returns {Boolean} 5636 */ 5637 _fr: function(value) { 5638 if (!/^FR[0-9A-Z]{2}[0-9]{9}$/.test(value)) { 5639 return false; 5640 } 5641 5642 value = value.substr(2); 5643 5644 if (!$.fn.bootstrapValidator.helpers.luhn(value.substr(2))) { 5645 return false; 5646 } 5647 5648 if (/^[0-9]{2}$/.test(value.substr(0, 2))) { 5649 // First two characters are digits 5650 return value.substr(0, 2) === (parseInt(value.substr(2) + '12', 10) % 97 + ''); 5651 } else { 5652 // The first characters cann't be O and I 5653 var alphabet = '0123456789ABCDEFGHJKLMNPQRSTUVWXYZ', 5654 check; 5655 // First one is digit 5656 if (/^[0-9]{1}$/.test(value.charAt(0))) { 5657 check = alphabet.indexOf(value.charAt(0)) * 24 + alphabet.indexOf(value.charAt(1)) - 10; 5658 } else { 5659 check = alphabet.indexOf(value.charAt(0)) * 34 + alphabet.indexOf(value.charAt(1)) - 100; 5660 } 5661 return ((parseInt(value.substr(2), 10) + 1 + Math.floor(check / 11)) % 11) === (check % 11); 5662 } 5663 }, 5664 5665 /** 5666 * Validate United Kingdom VAT number 5667 * Example: 5668 * - Valid: GB980780684 5669 * - Invalid: GB802311781 5670 * 5671 * @param {String} value VAT number 5672 * @returns {Boolean} 5673 */ 5674 _gb: function(value) { 5675 if (!/^GB[0-9]{9}$/.test(value) /* Standard */ 5676 && !/^GB[0-9]{12}$/.test(value) /* Branches */ 5677 && !/^GBGD[0-9]{3}$/.test(value) /* Government department */ 5678 && !/^GBHA[0-9]{3}$/.test(value) /* Health authority */ 5679 && !/^GB(GD|HA)8888[0-9]{5}$/.test(value)) 5680 { 5681 return false; 5682 } 5683 5684 value = value.substr(2); 5685 var length = value.length; 5686 if (length === 5) { 5687 var firstTwo = value.substr(0, 2), 5688 lastThree = parseInt(value.substr(2), 10); 5689 return ('GD' === firstTwo && lastThree < 500) || ('HA' === firstTwo && lastThree >= 500); 5690 } else if (length === 11 && ('GD8888' === value.substr(0, 6) || 'HA8888' === value.substr(0, 6))) { 5691 if (('GD' === value.substr(0, 2) && parseInt(value.substr(6, 3), 10) >= 500) 5692 || ('HA' === value.substr(0, 2) && parseInt(value.substr(6, 3), 10) < 500)) 5693 { 5694 return false; 5695 } 5696 return (parseInt(value.substr(6, 3), 10) % 97 === parseInt(value.substr(9, 2), 10)); 5697 } else if (length === 9 || length === 12) { 5698 var sum = 0, 5699 weight = [8, 7, 6, 5, 4, 3, 2, 10, 1]; 5700 for (var i = 0; i < 9; i++) { 5701 sum += parseInt(value.charAt(i), 10) * weight[i]; 5702 } 5703 sum = sum % 97; 5704 5705 if (parseInt(value.substr(0, 3), 10) >= 100) { 5706 return (sum === 0 || sum === 42 || sum === 55); 5707 } else { 5708 return (sum === 0); 5709 } 5710 } 5711 5712 return true; 5713 }, 5714 5715 /** 5716 * Validate Greek VAT number 5717 * Examples: 5718 * - Valid: GR023456780, EL094259216 5719 * - Invalid: EL123456781 5720 * 5721 * @param {String} value VAT number 5722 * @returns {Boolean} 5723 */ 5724 _gr: function(value) { 5725 if (!/^GR[0-9]{9}$/.test(value)) { 5726 return false;
5727 } 5728 5729 value = value.substr(2); 5730 if (value.length === 8) { 5731 value = '0' + value; 5732 } 5733 5734 var sum = 0, 5735 weight = [256, 128, 64, 32, 16, 8, 4, 2]; 5736 for (var i = 0; i < 8; i++) { 5737 sum += parseInt(value.charAt(i), 10) * weight[i]; 5738 } 5739 sum = (sum % 11) % 10; 5740 5741 return (sum + '' === value.substr(8, 1)); 5742 }, 5743 5744 // EL is traditionally prefix of Greek VAT numbers 5745 _el: function(value) { 5746 if (!/^EL[0-9]{9}$/.test(value)) { 5747 return false; 5748 } 5749 5750 value = 'GR' + value.substr(2); 5751 return this._gr(value); 5752 }, 5753 5754 /** 5755 * Validate Hungarian VAT number 5756 * Examples: 5757 * - Valid: HU12892312 5758 * - Invalid: HU12892313 5759 * 5760 * @param {String} value VAT number 5761 * @returns {Boolean} 5762 */ 5763 _hu: function(value) { 5764 if (!/^HU[0-9]{8}$/.test(value)) { 5765 return false; 5766 } 5767 5768 value = value.substr(2); 5769 var sum = 0, 5770 weight = [9, 7, 3, 1, 9, 7, 3, 1]; 5771 5772 for (var i = 0; i < 8; i++) { 5773 sum += parseInt(value.charAt(i), 10) * weight[i]; 5774 } 5775 5776 return (sum % 10 === 0); 5777 }, 5778 5779 /** 5780 * Validate Croatian VAT number 5781 * Examples: 5782 * - Valid: HR33392005961 5783 * - Invalid: HR33392005962 5784 * 5785 * @param {String} value VAT number 5786 * @returns {Boolean} 5787 */ 5788 _hr: function(value) { 5789 if (!/^HR[0-9]{11}$/.test(value)) { 5790 return false; 5791 } 5792 5793 value = value.substr(2); 5794 return $.fn.bootstrapValidator.helpers.mod11And10(value); 5795 }, 5796 5797 /** 5798 * Validate Irish VAT number 5799 * Examples: 5800 * - Valid: IE6433435F, IE6433435OA, IE8D79739I 5801 * - Invalid: IE8D79738J 5802 * 5803 * @param {String} value VAT number 5804 * @returns {Boolean} 5805 */ 5806 _ie: function(value) { 5807 if (!/^IE[0-9]{1}[0-9A-Z\*\+]{1}[0-9]{5}[A-Z]{1,2}$/.test(value)) { 5808 return false; 5809 } 5810 5811 value = value.substr(2); 5812 var getCheckDigit = function(value) { 5813 while (value.length < 7) { 5814 value = '0' + value; 5815 } 5816 var alphabet = 'WABCDEFGHIJKLMNOPQRSTUV', 5817 sum = 0; 5818 for (var i = 0; i < 7; i++) { 5819 sum += parseInt(value.charAt(i), 10) * (8 - i); 5820 } 5821 sum += 9 * alphabet.indexOf(value.substr(7)); 5822 return alphabet[sum % 23]; 5823 }; 5824 5825 // The first 7 characters are digits 5826 if (/^[0-9]+$/.test(value.substr(0, 7))) { 5827 // New system 5828 return value.charAt(7) === getCheckDigit(value.substr(0, 7) + value.substr(8) + ''); 5829 } else if ('ABCDEFGHIJKLMNOPQRSTUVWXYZ+*'.indexOf(value.charAt(1)) !== -1) { 5830 // Old system 5831 return value.charAt(7) === getCheckDigit(value.substr(2, 5) + value.substr(0, 1) + ''); 5832 } 5833 5834 return true; 5835 }, 5836 5837 /** 5838 * Validate Italian VAT number, which consists of 11 digits. 5839 * - First 7 digits are a company identifier 5840 * - Next 3 are the province of residence 5841 * - The last one is a check digit 5842 * 5843 * Examples: 5844 * - Valid: IT00743110157 5845 * - Invalid: IT00743110158 5846 * 5847 * @param {String} value VAT number 5848 * @returns {Boolean} 5849 */ 5850 _it: function(value) { 5851 if (!/^IT[0-9]{11}$/.test(value)) { 5852 return false; 5853 } 5854 5855 value = value.substr(2); 5856 if (parseInt(value.substr(0, 7), 10) === 0) { 5857 return false; 5858 } 5859 5860 var lastThree = parseInt(value.substr(7, 3), 10); 5861 if ((lastThree < 1) || (lastThree > 201) && lastThree !== 999 && lastThree !== 888) { 5862 return false;
5863 } 5864 5865 return $.fn.bootstrapValidator.helpers.luhn(value); 5866 }, 5867 5868 /** 5869 * Validate Lithuanian VAT number 5870 * It can be: 5871 * - 9 digits, for legal entities 5872 * - 12 digits, for temporarily registered taxpayers 5873 * 5874 * Examples: 5875 * - Valid: LT119511515, LT100001919017, LT100004801610 5876 * - Invalid: LT100001919018 5877 * 5878 * @param {String} value VAT number 5879 * @returns {Boolean} 5880 */ 5881 _lt: function(value) { 5882 if (!/^LT([0-9]{7}1[0-9]{1}|[0-9]{10}1[0-9]{1})$/.test(value)) { 5883 return false; 5884 } 5885 5886 value = value.substr(2); 5887 var length = value.length, 5888 sum = 0, 5889 i; 5890 for (i = 0; i < length - 1; i++) { 5891 sum += parseInt(value.charAt(i), 10) * (1 + i % 9); 5892 } 5893 var check = sum % 11; 5894 if (check === 10) { 5895 sum = 0; 5896 for (i = 0; i < length - 1; i++) { 5897 sum += parseInt(value.charAt(i), 10) * (1 + (i + 2) % 9); 5898 } 5899 } 5900 check = check % 11 % 10; 5901 return (check + '' === value.charAt(length - 1)); 5902 }, 5903 5904 /** 5905 * Validate Luxembourg VAT number 5906 * Examples: 5907 * - Valid: LU15027442 5908 * - Invalid: LU15027443 5909 * 5910 * @param {String} value VAT number 5911 * @returns {Boolean} 5912 */ 5913 _lu: function(value) { 5914 if (!/^LU[0-9]{8}$/.test(value)) { 5915 return false; 5916 } 5917 5918 value = value.substr(2); 5919 return ((parseInt(value.substr(0, 6), 10) % 89) + '' === value.substr(6, 2)); 5920 }, 5921 5922 /** 5923 * Validate Latvian VAT number 5924 * Examples: 5925 * - Valid: LV40003521600, LV16117519997 5926 * - Invalid: LV40003521601, LV16137519997 5927 * 5928 * @param {String} value VAT number 5929 * @returns {Boolean} 5930 */ 5931 _lv: function(value) { 5932 if (!/^LV[0-9]{11}$/.test(value)) { 5933 return false; 5934 } 5935 5936 value = value.substr(2); 5937 var first = parseInt(value.charAt(0), 10), 5938 sum = 0, 5939 weight = [], 5940 i, 5941 length = value.length; 5942 if (first > 3) { 5943 // Legal entity 5944 sum = 0; 5945 weight = [9, 1, 4, 8, 3, 10, 2, 5, 7, 6, 1]; 5946 for (i = 0; i < length; i++) { 5947 sum += parseInt(value.charAt(i), 10) * weight[i]; 5948 } 5949 sum = sum % 11; 5950 return (sum === 3); 5951 } else { 5952 // Check birth date 5953 var day = parseInt(value.substr(0, 2), 10), 5954 month = parseInt(value.substr(2, 2), 10), 5955 year = parseInt(value.substr(4, 2), 10); 5956 year = year + 1800 + parseInt(value.charAt(6), 10) * 100; 5957 5958 if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { 5959 return false; 5960 } 5961 5962 // Check personal code 5963 sum = 0; 5964 weight = [10, 5, 8, 4, 2, 1, 6, 3, 7, 9]; 5965 for (i = 0; i < length - 1; i++) { 5966 sum += parseInt(value.charAt(i), 10) * weight[i]; 5967 } 5968 sum = (sum + 1) % 11 % 10; 5969 return (sum + '' === value.charAt(length - 1)); 5970 } 5971 }, 5972 5973 /** 5974 * Validate Maltese VAT number 5975 * Examples: 5976 * - Valid: MT11679112 5977 * - Invalid: MT11679113 5978 * 5979 * @param {String} value VAT number 5980 * @returns {Boolean} 5981 */ 5982 _mt: function(value) { 5983 if (!/^MT[0-9]{8}$/.test(value)) { 5984 return false; 5985 } 5986 5987 value = value.substr(2); 5988 var sum = 0, 5989 weight = [3, 4, 6, 7, 8, 9, 10, 1]; 5990 5991 for (var i = 0; i < 8; i++) { 5992 sum += parseInt(value.charAt(i), 10) * weight[i]; 5993 } 5994 5995 return (sum % 37 === 0); 5996 }, 5997 5998 /** 5999 * Validate Dutch VAT number 6000 * Examples: 6001 * - Valid: NL004495445B01 6002 * - Invalid: NL123456789B90 6003 * 6004 * @param {String} value VAT number 6005 * @returns {Boolean} 6006 */ 6007 _nl: function(value) { 6008 if (!/^NL[0-9]{9}B[0-9]{2}$/.test(value)) { 6009 return false;
6010 } 6011 value = value.substr(2); 6012 var sum = 0, 6013 weight = [9, 8, 7, 6, 5, 4, 3, 2]; 6014 for (var i = 0; i < 8; i++) { 6015 sum += parseInt(value.charAt(i), 10) * weight[i]; 6016 } 6017 6018 sum = sum % 11; 6019 if (sum > 9) { 6020 sum = 0; 6021 } 6022 return (sum + '' === value.substr(8, 1)); 6023 }, 6024 6025 /** 6026 * Validate Norwegian VAT number 6027 * 6028 * @see http://www.brreg.no/english/coordination/number.html 6029 * @param {String} value VAT number 6030 * @returns {Boolean} 6031 */ 6032 _no: function(value) { 6033 if (!/^NO[0-9]{9}$/.test(value)) { 6034 return false; 6035 } 6036 value = value.substr(2); 6037 var sum = 0, 6038 weight = [3, 2, 7, 6, 5, 4, 3, 2]; 6039 for (var i = 0; i < 8; i++) { 6040 sum += parseInt(value.charAt(i), 10) * weight[i]; 6041 } 6042 6043 sum = 11 - sum % 11; 6044 if (sum === 11) { 6045 sum = 0; 6046 } 6047 return (sum + '' === value.substr(8, 1)); 6048 }, 6049 6050 /** 6051 * Validate Polish VAT number 6052 * Examples: 6053 * - Valid: PL8567346215 6054 * - Invalid: PL8567346216 6055 * 6056 * @param {String} value VAT number 6057 * @returns {Boolean} 6058 */ 6059 _pl: function(value) { 6060 if (!/^PL[0-9]{10}$/.test(value)) { 6061 return false; 6062 } 6063 6064 value = value.substr(2); 6065 var sum = 0, 6066 weight = [6, 5, 7, 2, 3, 4, 5, 6, 7, -1]; 6067 6068 for (var i = 0; i < 10; i++) { 6069 sum += parseInt(value.charAt(i), 10) * weight[i]; 6070 } 6071 6072 return (sum % 11 === 0); 6073 }, 6074 6075 /** 6076 * Validate Portuguese VAT number 6077 * Examples: 6078 * - Valid: PT501964843 6079 * - Invalid: PT501964842 6080 * 6081 * @param {String} value VAT number 6082 * @returns {Boolean} 6083 */ 6084 _pt: function(value) { 6085 if (!/^PT[0-9]{9}$/.test(value)) { 6086 return false; 6087 } 6088 6089 value = value.substr(2); 6090 var sum = 0, 6091 weight = [9, 8, 7, 6, 5, 4, 3, 2]; 6092 6093 for (var i = 0; i < 8; i++) { 6094 sum += parseInt(value.charAt(i), 10) * weight[i]; 6095 } 6096 sum = 11 - sum % 11; 6097 if (sum > 9) { 6098 sum = 0; 6099 } 6100 return (sum + '' === value.substr(8, 1)); 6101 }, 6102 6103 /** 6104 * Validate Romanian VAT number 6105 * Examples: 6106 * - Valid: RO18547290 6107 * - Invalid: RO18547291 6108 * 6109 * @param {String} value VAT number 6110 * @returns {Boolean} 6111 */ 6112 _ro: function(value) { 6113 if (!/^RO[1-9][0-9]{1,9}$/.test(value)) { 6114 return false; 6115 } 6116 value = value.substr(2); 6117 6118 var length = value.length, 6119 weight = [7, 5, 3, 2, 1, 7, 5, 3, 2].slice(10 - length), 6120 sum = 0; 6121 for (var i = 0; i < length - 1; i++) { 6122 sum += parseInt(value.charAt(i), 10) * weight[i]; 6123 } 6124 6125 sum = (10 * sum) % 11 % 10; 6126 return (sum + '' === value.substr(length - 1, 1)); 6127 }, 6128 6129 /** 6130 * Validate Russian VAT number (Taxpayer Identification Number - INN) 6131 * 6132 * @param {String} value VAT number 6133 * @returns {Boolean} 6134 */ 6135 _ru: function(value) { 6136 if (!/^RU([0-9]{9}|[0-9]{12})$/.test(value)) { 6137 return false; 6138 } 6139 6140 value = value.substr(2); 6141 var i = 0; 6142 if (value.length === 10) { 6143 var sum = 0, 6144 weight = [2, 4, 10, 3, 5, 9, 4, 6, 8, 0]; 6145 for (i = 0; i < 10; i++) { 6146 sum += parseInt(value.charAt(i), 10) * weight[i]; 6147 } 6148 sum = sum % 11; 6149 if (sum > 9) { 6150 sum = sum % 10; 6151 } 6152 6153 return (sum + '' === value.substr(9, 1)); 6154 } else if (value.length === 12) { 6155 var sum1 = 0, 6156 weight1 = [7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0], 6157 sum2 = 0, 6158 weight2 = [3, 7, 2, 4, 10, 3, 5, 9, 4, 6, 8, 0]; 6159 6160 for (i = 0; i < 11; i++) { 6161 sum1 += parseInt(value.charAt(i), 10) * weight1[i]; 6162 sum2 += parseInt(value.charAt(i), 10) * weight2[i]; 6163 } 6164 sum1 = sum1 % 11; 6165 if (sum1 > 9) { 6166 sum1 = sum1 % 10; 6167 } 6168 sum2 = sum2 % 11; 6169 if (sum2 > 9) { 6170 sum2 = sum2 % 10; 6171 } 6172 6173 return (sum1 + '' === value.substr(10, 1) && sum2 + '' === value.substr(11, 1)); 6174 } 6175 6176 return false;
6177 }, 6178 6179 /** 6180 * Validate Serbian VAT number 6181 * 6182 * @param {String} value VAT number 6183 * @returns {Boolean} 6184 */ 6185 _rs: function(value) { 6186 if (!/^RS[0-9]{9}$/.test(value)) { 6187 return false; 6188 } 6189 6190 value = value.substr(2); 6191 var sum = 10, 6192 temp = 0; 6193 for (var i = 0; i < 8; i++) { 6194 temp = (parseInt(value.charAt(i), 10) + sum) % 10; 6195 if (temp === 0) { 6196 temp = 10; 6197 } 6198 sum = (2 * temp) % 11; 6199 } 6200 6201 return ((sum + parseInt(value.substr(8, 1), 10)) % 10 === 1); 6202 }, 6203 6204 /** 6205 * Validate Swedish VAT number 6206 * Examples: 6207 * - Valid: SE123456789701 6208 * - Invalid: SE123456789101 6209 * 6210 * @param {String} value VAT number 6211 * @returns {Boolean} 6212 */ 6213 _se: function(value) { 6214 if (!/^SE[0-9]{10}01$/.test(value)) { 6215 return false; 6216 } 6217 6218 value = value.substr(2, 10); 6219 return $.fn.bootstrapValidator.helpers.luhn(value); 6220 }, 6221 6222 /** 6223 * Validate Slovenian VAT number 6224 * Examples: 6225 * - Valid: SI50223054 6226 * - Invalid: SI50223055 6227 * 6228 * @param {String} value VAT number 6229 * @returns {Boolean} 6230 */ 6231 _si: function(value) { 6232 if (!/^SI[0-9]{8}$/.test(value)) { 6233 return false; 6234 } 6235 6236 value = value.substr(2); 6237 var sum = 0, 6238 weight = [8, 7, 6, 5, 4, 3, 2]; 6239 6240 for (var i = 0; i < 7; i++) { 6241 sum += parseInt(value.charAt(i), 10) * weight[i]; 6242 } 6243 sum = 11 - sum % 11; 6244 if (sum === 10) { 6245 sum = 0; 6246 } 6247 return (sum + '' === value.substr(7, 1)); 6248 }, 6249 6250 /** 6251 * Validate Slovak VAT number 6252 * Examples: 6253 * - Valid: SK2022749619 6254 * - Invalid: SK2022749618 6255 * 6256 * @param {String} value VAT number 6257 * @returns {Boolean} 6258 */ 6259 _sk: function(value) { 6260 if (!/^SK[1-9][0-9][(2-4)|(6-9)][0-9]{7}$/.test(value)) { 6261 return false; 6262 } 6263 6264 return (parseInt(value.substr(2), 10) % 11 === 0); 6265 } 6266 }; 6267}(window.jQuery)); 6268;(function($) { 6269 $.fn.bootstrapValidator.i18n.vin = $.extend($.fn.bootstrapValidator.i18n.vin || {}, { 6270 'default': 'Please enter a valid VIN number' 6271 }); 6272 6273 $.fn.bootstrapValidator.validators.vin = { 6274 /** 6275 * Validate an US VIN (Vehicle Identification Number) 6276 * 6277 * @param {BootstrapValidator} validator The validator plugin instance 6278 * @param {jQuery} $field Field element 6279 * @param {Object} options Consist of key: 6280 * - message: The invalid message 6281 * @returns {Boolean} 6282 */ 6283 validate: function(validator, $field, options) { 6284 var value = $field.val(); 6285 if (value === '') { 6286 return true; 6287 } 6288 6289 // Don't accept I, O, Q characters 6290 if (!/^[a-hj-npr-z0-9]{8}[0-9xX][a-hj-npr-z0-9]{8}$/i.test(value)) { 6291 return false; 6292 } 6293 6294 value = value.toUpperCase(); 6295 var chars = { 6296 A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8, 6297 J: 1, K: 2, L: 3, M: 4, N: 5, P: 7, R: 9, 6298 S: 2, T: 3, U: 4, V: 5, W: 6, X: 7, Y: 8, Z: 9, 6299 '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '0': 0 6300 }, 6301 weights = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2], 6302 sum = 0, 6303 length = value.length; 6304 for (var i = 0; i < length; i++) { 6305 sum += chars[value.charAt(i) + ''] * weights[i]; 6306 } 6307 6308 var reminder = sum % 11; 6309 if (reminder === 10) { 6310 reminder = 'X'; 6311 } 6312 6313 return (reminder + '') === value.charAt(8); 6314 } 6315 }; 6316}(window.jQuery)); 6317;(function($) { 6318 $.fn.bootstrapValidator.i18n.zipCode = $.extend($.fn.bootstrapValidator.i18n.zipCode || {}, { 6319 'default': 'Please enter a valid zip code', 6320 countryNotSupported: 'The country code %s is not supported', 6321 country: 'Please enter a valid %s', 6322 countries: { 6323 'CA': 'Canadian postal code', 6324 'DK': 'Danish postal code', 6325 'GB': 'United Kingdom postal code', 6326 'IT': 'Italian postal code',
6327 'NL': 'Dutch postal code', 6328 'SE': 'Swiss postal code', 6329 'SG': 'Singapore postal code', 6330 'US': 'US zip code' 6331 } 6332 }); 6333 6334 $.fn.bootstrapValidator.validators.zipCode = { 6335 html5Attributes: { 6336 message: 'message', 6337 country: 'country' 6338 }, 6339 6340 COUNTRY_CODES: ['CA', 'DK', 'GB', 'IT', 'NL', 'SE', 'SG', 'US'], 6341 6342 /** 6343 * Return true if and only if the input value is a valid country zip code 6344 * 6345 * @param {BootstrapValidator} validator The validator plugin instance 6346 * @param {jQuery} $field Field element 6347 * @param {Object} options Consist of key: 6348 * - message: The invalid message 6349 * - country: The country 6350 * 6351 * The country can be defined by: 6352 * - An ISO 3166 country code 6353 * Currently it supports the following countries: 6354 * - US (United States) 6355 * - CA (Canada) 6356 * - DK (Denmark) 6357 * - GB (United Kingdom) 6358 * - IT (Italy) 6359 * - NL (Netherlands) 6360 * - SE (Sweden) 6361 * - SG (Singapore) 6362 * 6363 * - Name of field which its value defines the country code 6364 * - Name of callback function that returns the country code 6365 * - A callback function that returns the country code 6366 * 6367 * callback: function(value, validator, $field) { 6368 * // value is the value of field 6369 * // validator is the BootstrapValidator instance 6370 * // $field is jQuery element representing the field 6371 * } 6372 * 6373 * @returns {Boolean|Object} 6374 */ 6375 validate: function(validator, $field, options) { 6376 var value = $field.val(); 6377 if (value === '' || !options.country) { 6378 return true; 6379 } 6380 6381 var country = options.country; 6382 if (typeof country !== 'string' || $.inArray(country, this.COUNTRY_CODES) === -1) { 6383 // Try to determine the country 6384 country = validator.getDynamicOption($field, country); 6385 } 6386 6387 if (!country || $.inArray(country.toUpperCase(), this.COUNTRY_CODES) === -1) { 6388 return { valid: false, message: $.fn.bootstrapValidator.helpers.format($.fn.bootstrapValidator.i18n.zipCode.countryNotSupported, country) }; 6389 } 6390 6391 var isValid = false; 6392 country = country.toUpperCase(); 6393 switch (country) { 6394 case 'CA': 6395 isValid = /^(?:A|B|C|E|G|H|J|K|L|M|N|P|R|S|T|V|X|Y){1}[0-9]{1}(?:A|B|C|E|G|H|J|K|L|M|N|P|R|S|T|V|W|X|Y|Z){1}\s?[0-9]{1}(?:A|B|C|E|G|H|J|K|L|M|N|P|R|S|T|V|W|X|Y|Z){1}[0-9]{1}$/i.test(value); 6396 break; 6397 6398 case 'DK': 6399 isValid = /^(DK(-|\s)?)?\d{4}$/i.test(value); 6400 break; 6401 6402 case 'GB': 6403 isValid = this._gb(value); 6404 break; 6405 6406 // http://en.wikipedia.org/wiki/List_of_postal_codes_in_Italy 6407 case 'IT': 6408 isValid = /^(I-|IT-)?\d{5}$/i.test(value); 6409 break; 6410 6411 // http://en.wikipedia.org/wiki/Postal_codes_in_the_Netherlands 6412 case 'NL': 6413 isValid = /^[1-9][0-9]{3} ?(?!sa|sd|ss)[a-z]{2}$/i.test(value); 6414 break; 6415 6416 case 'SE': 6417 isValid = /^(S-)?\d{3}\s?\d{2}$/i.test(value); 6418 break; 6419 6420 case 'SG': 6421 isValid = /^([0][1-9]|[1-6][0-9]|[7]([0-3]|[5-9])|[8][0-2])(\d{4})$/i.test(value); 6422 break; 6423 6424 case 'US': 6425 /* falls through */ 6426 default: 6427 isValid = /^\d{4,5}([\-]?\d{4})?$/.test(value); 6428 break; 6429 } 6430 6431 return { 6432 valid: isValid, 6433 message: $.fn.bootstrapValidator.helpers.format(options.message || $.fn.bootstrapValidator.i18n.zipCode.country, $.fn.bootstrapValidator.i18n.zipCode.countries[country]) 6434 }; 6435 }, 6436 6437 /** 6438 * Validate United Kingdom postcode 6439 * Examples:
6440 * - Standard: EC1A 1BB, W1A 1HQ, M1 1AA, B33 8TH, CR2 6XH, DN55 1PT 6441 * - Special cases: 6442 * AI-2640, ASCN 1ZZ, GIR 0AA 6443 * 6444 * @see http://en.wikipedia.org/wiki/Postcodes_in_the_United_Kingdom 6445 * @param {String} value The postcode 6446 * @returns {Boolean} 6447 */ 6448 _gb: function(value) { 6449 var firstChar = '[ABCDEFGHIJKLMNOPRSTUWYZ]', // Does not accept QVX 6450 secondChar = '[ABCDEFGHKLMNOPQRSTUVWXY]', // Does not accept IJZ 6451 thirdChar = '[ABCDEFGHJKPMNRSTUVWXY]', 6452 fourthChar = '[ABEHMNPRVWXY]', 6453 fifthChar = '[ABDEFGHJLNPQRSTUWXYZ]', 6454 regexps = [ 6455 // AN NAA, ANN NAA, AAN NAA, AANN NAA format 6456 new RegExp('^(' + firstChar + '{1}' + secondChar + '?[0-9]{1,2})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'), 6457 // ANA NAA 6458 new RegExp('^(' + firstChar + '{1}[0-9]{1}' + thirdChar + '{1})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'), 6459 // AANA NAA 6460 new RegExp('^(' + firstChar + '{1}' + secondChar + '{1}?[0-9]{1}' + fourthChar + '{1})(\\s*)([0-9]{1}' + fifthChar + '{2})$', 'i'), 6461 6462 new RegExp('^(BF1)(\\s*)([0-6]{1}[ABDEFGHJLNPQRST]{1}[ABDEFGHJLNPQRSTUWZYZ]{1})$', 'i'), // BFPO postcodes 6463 /^(GIR)(\s*)(0AA)$/i, // Special postcode GIR 0AA 6464 /^(BFPO)(\s*)([0-9]{1,4})$/i, // Standard BFPO numbers 6465 /^(BFPO)(\s*)(c\/o\s*[0-9]{1,3})$/i, // c/o BFPO numbers 6466 /^([A-Z]{4})(\s*)(1ZZ)$/i, // Overseas Territories 6467 /^(AI-2640)$/i // Anguilla 6468 ]; 6469 for (var i = 0; i < regexps.length; i++) { 6470 if (regexps[i].test(value)) { 6471 return true; 6472 } 6473 } 6474 6475 return false; 6476 } 6477 }; 6478}(window.jQuery));
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.