bootstrapValidator.js 39 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051
  1. /**
  2. * BootstrapValidator (http://github.com/nghuuphuoc/bootstrapvalidator)
  3. *
  4. * A jQuery plugin to validate form fields. Use with Bootstrap 3
  5. *
  6. * @version v0.3.0-dev
  7. * @author https://twitter.com/nghuuphuoc
  8. * @copyright (c) 2013 - 2014 Nguyen Huu Phuoc
  9. * @license MIT
  10. */
  11. (function($) {
  12. var BootstrapValidator = function(form, options) {
  13. this.$form = $(form);
  14. this.options = $.extend({}, BootstrapValidator.DEFAULT_OPTIONS, options);
  15. this.dfds = {}; // Array of deferred
  16. this.results = {}; // Validating results
  17. this.invalidField = null; // First invalid field
  18. this.$submitButton = null; // The submit button which is clicked to submit form
  19. this._init();
  20. this.STATUS_NOT_VALIDATED = 'NOT_VALIDATED';
  21. this.STATUS_VALIDATING = 'VALIDATING';
  22. this.STATUS_INVALID = 'INVALID';
  23. this.STATUS_VALID = 'VALID';
  24. };
  25. // The default options
  26. BootstrapValidator.DEFAULT_OPTIONS = {
  27. // The form CSS class
  28. elementClass: 'bootstrap-validator-form',
  29. // Default invalid message
  30. message: 'This value is not valid',
  31. // The number of grid columns
  32. // Change it if you use custom grid with different number of columns
  33. columns: 12,
  34. // Shows ok/error icons based on the field validity.
  35. // This feature requires Bootstrap v3.1.0 or later (http://getbootstrap.com/css/#forms-control-validation).
  36. // Since Bootstrap doesn't provide any methods to know its version, this option cannot be on/off automatically.
  37. // In other word, to use this feature you have to upgrade your Bootstrap to v3.1.0 or later.
  38. feedbackIcons: false,
  39. // The submit buttons selector
  40. // These buttons will be disabled to prevent the valid form from multiple submissions
  41. submitButtons: 'button[type="submit"]',
  42. // The custom submit handler
  43. // It will prevent the form from the default submission
  44. //
  45. // submitHandler: function(validator, form) {
  46. // - validator is the BootstrapValidator instance
  47. // - form is the jQuery object present the current form
  48. // }
  49. submitHandler: null,
  50. // Live validating option
  51. // Can be one of 3 values:
  52. // - enabled: The plugin validates fields as soon as they are changed
  53. // - disabled: Disable the live validating. The error messages are only shown after the form is submitted
  54. // - submitted: The live validating is enabled after the form is submitted
  55. live: 'enabled',
  56. // Map the field name with validator rules
  57. fields: null
  58. };
  59. BootstrapValidator.prototype = {
  60. constructor: BootstrapValidator,
  61. /**
  62. * Init form
  63. */
  64. _init: function() {
  65. if (this.options.fields == null) {
  66. return;
  67. }
  68. var that = this;
  69. this.$form
  70. // Disable client side validation in HTML 5
  71. .attr('novalidate', 'novalidate')
  72. .addClass(this.options.elementClass)
  73. // Disable the default submission first
  74. .on('submit.bootstrapValidator', function(e) {
  75. e.preventDefault();
  76. that.validate();
  77. })
  78. .find(this.options.submitButtons)
  79. .on('click', function() {
  80. that.$submitButton = $(this);
  81. });
  82. for (var field in this.options.fields) {
  83. this._initField(field);
  84. }
  85. this._setLiveValidating();
  86. },
  87. /**
  88. * Init field
  89. *
  90. * @param {String} field The field name
  91. */
  92. _initField: function(field) {
  93. if (this.options.fields[field] == null || this.options.fields[field].validators == null) {
  94. return;
  95. }
  96. this.dfds[field] = {};
  97. this.results[field] = {};
  98. var fields = this.getFieldElements(field);
  99. // We don't need to validate ...
  100. if (fields == null // ... non-existing fields
  101. || (fields.length == 1 && fields.is(':disabled'))) // ... disabled field
  102. {
  103. delete this.options.fields[field];
  104. delete this.dfds[field];
  105. return;
  106. }
  107. // Create a help block element for showing the error
  108. var $field = $(fields[0]),
  109. $parent = $field.parents('.form-group'),
  110. // Calculate the number of columns of the label/field element
  111. // Then set offset to the help block element
  112. label, cssClasses, offset, size;
  113. if (label = $parent.find('label').get(0)) {
  114. // The default Bootstrap form don't require class for label (http://getbootstrap.com/css/#forms)
  115. if (cssClasses = $(label).attr('class')) {
  116. cssClasses = cssClasses.split(' ');
  117. for (var i = 0; i < cssClasses.length; i++) {
  118. if (/^col-(xs|sm|md|lg)-\d+$/.test(cssClasses[i])) {
  119. offset = cssClasses[i].substr(7);
  120. size = cssClasses[i].substr(4, 2);
  121. break;
  122. }
  123. }
  124. }
  125. } else if (cssClasses = $parent.children().eq(0).attr('class')) {
  126. cssClasses = cssClasses.split(' ');
  127. for (var i = 0; i < cssClasses.length; i++) {
  128. if (/^col-(xs|sm|md|lg)-offset-\d+$/.test(cssClasses[i])) {
  129. offset = cssClasses[i].substr(14);
  130. size = cssClasses[i].substr(4, 2);
  131. break;
  132. }
  133. }
  134. }
  135. if (size && offset) {
  136. for (var validatorName in this.options.fields[field].validators) {
  137. if (!$.fn.bootstrapValidator.validators[validatorName]) {
  138. delete this.options.fields[field].validators[validatorName];
  139. continue;
  140. }
  141. this.results[field][validatorName] = this.STATUS_NOT_VALIDATED;
  142. $('<small/>')
  143. .css('display', 'none')
  144. .attr('data-bs-validator', validatorName)
  145. .addClass('help-block')
  146. .addClass(['col-', size, '-offset-', offset].join(''))
  147. .addClass(['col-', size, '-', this.options.columns - offset].join(''))
  148. .appendTo($parent);
  149. }
  150. }
  151. // Prepare the feedback icons
  152. // Available from Bootstrap 3.1 (http://getbootstrap.com/css/#forms-control-validation)
  153. if (this.options.feedbackIcons) {
  154. $parent.addClass('has-feedback');
  155. $('<span/>').css('display', 'none').addClass('glyphicon form-control-feedback').insertAfter($(fields[fields.length - 1]));
  156. }
  157. // Whenever the user change the field value, make it as not validated yet
  158. var that = this,
  159. type = fields.attr('type'),
  160. event = ('radio' == type || 'checkbox' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup';
  161. fields.on(event, function() {
  162. // Whenever the user change the field value, make it as not validated yet
  163. for (var v in that.options.fields[field].validators) {
  164. that.results[field][v] = that.STATUS_NOT_VALIDATED;
  165. }
  166. });
  167. },
  168. /**
  169. * Enable live validating
  170. */
  171. _setLiveValidating: function() {
  172. if ('enabled' == this.options.live) {
  173. var that = this;
  174. for (var field in this.options.fields) {
  175. (function(f) {
  176. var fields = that.getFieldElements(f);
  177. if (fields) {
  178. var type = fields.attr('type'),
  179. event = ('radio' == type || 'checkbox' == type || 'SELECT' == fields[0].tagName) ? 'change' : 'keyup';
  180. fields.on(event, function() {
  181. that.validateField(f);
  182. });
  183. }
  184. })(field);
  185. }
  186. }
  187. },
  188. /**
  189. * Disable/Enable submit buttons
  190. *
  191. * @param {Boolean} disabled
  192. */
  193. _disableSubmitButtons: function(disabled) {
  194. if (!disabled) {
  195. this.$form.find(this.options.submitButtons).removeAttr('disabled');
  196. } else if (this.options.live != 'disabled') {
  197. // Don't disable if the live validating mode is disabled
  198. this.$form.find(this.options.submitButtons).attr('disabled', 'disabled');
  199. }
  200. },
  201. /**
  202. * Called when all validations are completed
  203. */
  204. _submit: function() {
  205. if (!this.isValid()) {
  206. if ('submitted' == this.options.live) {
  207. this.options.live = 'enabled';
  208. this._setLiveValidating();
  209. }
  210. // Focus to the first invalid field
  211. if (this.invalidField) {
  212. this.getFieldElements(this.invalidField).focus();
  213. }
  214. return;
  215. }
  216. this._disableSubmitButtons(true);
  217. // Call the custom submission if enabled
  218. if (this.options.submitHandler && 'function' == typeof this.options.submitHandler) {
  219. this.options.submitHandler.call(this, this, this.$form, this.$submitButton);
  220. } else {
  221. // Submit form
  222. this.$form.off('submit.bootstrapValidator').submit();
  223. }
  224. },
  225. // --- Public methods ---
  226. /**
  227. * Retrieve the field elements by given name
  228. *
  229. * @param {String} field The field name
  230. * @returns {null|jQuery[]}
  231. */
  232. getFieldElements: function(field) {
  233. var fields = this.$form.find('[name="' + field + '"]');
  234. return (fields.length == 0) ? null : fields;
  235. },
  236. /**
  237. * Validate the form
  238. */
  239. validate: function() {
  240. if (!this.options.fields) {
  241. return this;
  242. }
  243. this._disableSubmitButtons(true);
  244. for (var field in this.options.fields) {
  245. this.validateField(field);
  246. }
  247. this._submit();
  248. return this;
  249. },
  250. /**
  251. * Validate given field
  252. *
  253. * @param {String} field The field name
  254. */
  255. validateField: function(field) {
  256. var that = this,
  257. fields = this.$form.find('[name="' + field + '"]'),
  258. $field = $(fields[0]),
  259. validators = this.options.fields[field].validators,
  260. validatorName,
  261. validateResult;
  262. for (validatorName in validators) {
  263. if (this.dfds[field][validatorName]) {
  264. this.dfds[field][validatorName].reject();
  265. }
  266. // Don't validate field if it is already done
  267. if (this.results[field][validatorName] == this.STATUS_VALID || this.results[field][validatorName] == this.STATUS_INVALID) {
  268. continue;
  269. }
  270. this.results[field][validatorName] = this.STATUS_VALIDATING;
  271. validateResult = $.fn.bootstrapValidator.validators[validatorName].validate(this, $field, validators[validatorName]);
  272. if ('object' == typeof validateResult) {
  273. this.updateStatus($field, validatorName, this.STATUS_VALIDATING);
  274. this.dfds[field][validatorName] = validateResult;
  275. validateResult.done(function(isValid, v) {
  276. // v is validator name
  277. delete that.dfds[field][v];
  278. isValid ? that.updateStatus($field, v, that.STATUS_VALID)
  279. : that.updateStatus($field, v, that.STATUS_INVALID);
  280. });
  281. } else if ('boolean' == typeof validateResult) {
  282. validateResult ? this.updateStatus($field, validatorName, this.STATUS_VALID)
  283. : this.updateStatus($field, validatorName, this.STATUS_INVALID);
  284. }
  285. }
  286. },
  287. /**
  288. * Check the form validity
  289. *
  290. * @returns {Boolean}
  291. */
  292. isValid: function() {
  293. var field, validatorName;
  294. for (field in this.results) {
  295. for (validatorName in this.results[field]) {
  296. if (this.results[field][validatorName] == this.STATUS_NOT_VALIDATED || this.results[field][validatorName] == this.STATUS_VALIDATING) {
  297. return false;
  298. }
  299. if (this.results[field][validatorName] == this.STATUS_INVALID) {
  300. this.invalidField = field;
  301. return false;
  302. }
  303. }
  304. }
  305. return true;
  306. },
  307. /**
  308. * Update field status
  309. *
  310. * @param {jQuery} $field The field element
  311. * @param {String} validatorName
  312. * @param {String} status The status
  313. * Can be STATUS_VALIDATING, STATUS_INVALID, STATUS_VALID
  314. */
  315. updateStatus: function($field, validatorName, status) {
  316. var that = this,
  317. field = $field.attr('name'),
  318. validator = this.options.fields[field].validators[validatorName],
  319. message = validator.message || this.options.message,
  320. $parent = $field.parents('.form-group'),
  321. $errors = $parent.find('.help-block[data-bs-validator]');
  322. switch (status) {
  323. case this.STATUS_VALIDATING:
  324. this.results[field][validatorName] = this.STATUS_VALIDATING;
  325. this._disableSubmitButtons(true);
  326. $parent.removeClass('has-success').removeClass('has-error');
  327. // TODO: Show validating message
  328. $errors.filter('.help-block[data-bs-validator="' + validatorName + '"]').html(message).hide();
  329. if (this.options.feedbackIcons) {
  330. // Show "loading" icon
  331. $parent.find('.form-control-feedback').removeClass('glyphicon-ok').removeClass('glyphicon-remove').addClass('glyphicon-refresh').show();
  332. }
  333. break;
  334. case this.STATUS_INVALID:
  335. this.results[field][validatorName] = this.STATUS_INVALID;
  336. this._disableSubmitButtons(true);
  337. // Add has-error class to parent element
  338. $parent.removeClass('has-success').addClass('has-error');
  339. $errors.filter('[data-bs-validator="' + validatorName + '"]').html(message).show();
  340. if (this.options.feedbackIcons) {
  341. // Show "error" icon
  342. $parent.find('.form-control-feedback').removeClass('glyphicon-ok').removeClass('glyphicon-refresh').addClass('glyphicon-remove').show();
  343. }
  344. break;
  345. case this.STATUS_VALID:
  346. this.results[field][validatorName] = this.STATUS_VALID;
  347. // Hide error element
  348. $errors.filter('[data-bs-validator="' + validatorName + '"]').hide();
  349. // If the field is valid
  350. if ($errors.filter(function() {
  351. var display = $(this).css('display'), v = $(this).attr('data-bs-validator');
  352. return ('block' == display) || (that.results[field][v] != that.STATUS_VALID);
  353. }).length == 0
  354. ) {
  355. this._disableSubmitButtons(false);
  356. $parent.removeClass('has-error').addClass('has-success');
  357. // Show the "ok" icon
  358. if (this.options.feedbackIcons) {
  359. $parent.find('.form-control-feedback').removeClass('glyphicon-remove').removeClass('glyphicon-refresh').addClass('glyphicon-ok').show();
  360. }
  361. }
  362. break;
  363. default:
  364. break;
  365. }
  366. },
  367. // Useful APIs which aren't use internally
  368. /**
  369. * Reset the form
  370. *
  371. * @param {Boolean} resetFormData Reset current form data
  372. */
  373. resetForm: function(resetFormData) {
  374. for (var field in this.options.fields) {
  375. this.dfds[field] = {};
  376. this.results[field] = {};
  377. // Mark all fields as not validated yet
  378. for (var v in this.options.fields[field].validators) {
  379. this.results[field][v] = this.STATUS_NOT_VALIDATED;
  380. }
  381. }
  382. this.invalidField = null;
  383. this.$submitButton = null;
  384. // Hide all error elements
  385. this.$form
  386. .find('.has-error').removeClass('has-error').end()
  387. .find('.has-success').removeClass('has-success').end()
  388. .find('.help-block[data-bs-validator]').hide();
  389. // Enable submit buttons
  390. this._disableSubmitButtons(false);
  391. // Hide all feeback icons
  392. if (this.options.feedbackIcons) {
  393. this.$form.find('.form-control-feedback').removeClass('glyphicon-ok').removeClass('glyphicon-remove').removeClass('glyphicon-refresh').hide();
  394. }
  395. if (resetFormData) {
  396. this.$form.get(0).reset();
  397. }
  398. }
  399. };
  400. // Plugin definition
  401. $.fn.bootstrapValidator = function(options) {
  402. return this.each(function() {
  403. var $this = $(this), data = $this.data('bootstrapValidator');
  404. if (!data) {
  405. $this.data('bootstrapValidator', (data = new BootstrapValidator(this, options)));
  406. }
  407. if ('string' == typeof options) {
  408. data[options]();
  409. }
  410. });
  411. };
  412. // Available validators
  413. $.fn.bootstrapValidator.validators = {};
  414. $.fn.bootstrapValidator.Constructor = BootstrapValidator;
  415. }(window.jQuery));
  416. ;(function($) {
  417. $.fn.bootstrapValidator.validators.between = {
  418. /**
  419. * Return true if the input value is between (strictly or not) two given numbers
  420. *
  421. * @param {BootstrapValidator} validator The validator plugin instance
  422. * @param {jQuery} $field Field element
  423. * @param {Object} options Can consist of the following keys:
  424. * - min
  425. * - max
  426. * - inclusive [optional]: Can be true or false. Default is true
  427. * - message: The invalid message
  428. * @returns {Boolean}
  429. */
  430. validate: function(validator, $field, options) {
  431. var value = $field.val();
  432. if (value == '') {
  433. return true;
  434. }
  435. value = parseFloat(value);
  436. return (options.inclusive === true)
  437. ? (value > options.min && value < options.max)
  438. : (value >= options.min && value <= options.max);
  439. }
  440. };
  441. }(window.jQuery));
  442. ;(function($) {
  443. $.fn.bootstrapValidator.validators.callback = {
  444. /**
  445. * Return result from the callback method
  446. *
  447. * @param {BootstrapValidator} validator The validator plugin instance
  448. * @param {jQuery} $field Field element
  449. * @param {Object} options Can consist of the following keys:
  450. * - callback: The callback method that passes 2 parameters:
  451. * callback: function(fieldValue, validator) {
  452. * // fieldValue is the value of field
  453. * // validator is instance of BootstrapValidator
  454. * }
  455. * - message: The invalid message
  456. * @returns {Boolean|Deferred}
  457. */
  458. validate: function(validator, $field, options) {
  459. var value = $field.val();
  460. if (options.callback && 'function' == typeof options.callback) {
  461. var dfd = new $.Deferred();
  462. dfd.resolve(options.callback.call(this, value, validator), 'callback');
  463. return dfd;
  464. return options.callback.call(this, value, validator);
  465. }
  466. return true;
  467. }
  468. };
  469. }(window.jQuery));
  470. ;(function($) {
  471. $.fn.bootstrapValidator.validators.choice = {
  472. /**
  473. * Check if the number of checked boxes are less or more than a given number
  474. *
  475. * @param {BootstrapValidator} validator The validator plugin instance
  476. * @param {jQuery} $field Field element
  477. * @param {Object} options Consists of following keys:
  478. * - min
  479. * - max
  480. * At least one of two keys is required
  481. * @returns {Boolean}
  482. */
  483. validate: function(validator, $field, options) {
  484. var numChoices = validator
  485. .getFieldElements($field.attr('name'))
  486. .filter(':checked')
  487. .length;
  488. if ((options.min && numChoices < options.min) || (options.max && numChoices > options.max)) {
  489. return false;
  490. }
  491. return true;
  492. }
  493. };
  494. }(window.jQuery));
  495. ;(function($) {
  496. $.fn.bootstrapValidator.validators.creditCard = {
  497. /**
  498. * Return true if the input value is valid credit card number
  499. * Based on https://gist.github.com/DiegoSalazar/4075533
  500. *
  501. * @param {BootstrapValidator} validator The validator plugin instance
  502. * @param {jQuery} $field Field element
  503. * @param {Object} options Can consist of the following key:
  504. * - message: The invalid message
  505. * @returns {Boolean}
  506. */
  507. validate: function(validator, $field, options) {
  508. var value = $field.val();
  509. if (value == '') {
  510. return true;
  511. }
  512. // Accept only digits, dashes or spaces
  513. if (/[^0-9-\s]+/.test(value)) {
  514. return false;
  515. }
  516. // The Luhn Algorithm
  517. // http://en.wikipedia.org/wiki/Luhn
  518. value = value.replace(/\D/g, '');
  519. var check = 0, digit = 0, even = false, length = value.length;
  520. for (var n = length - 1; n >= 0; n--) {
  521. digit = parseInt(value.charAt(n), 10);
  522. if (even) {
  523. if ((digit *= 2) > 9) {
  524. digit -= 9;
  525. }
  526. }
  527. check += digit;
  528. even = !even;
  529. }
  530. return (check % 10) == 0;
  531. }
  532. };
  533. }(window.jQuery));
  534. ;(function($) {
  535. $.fn.bootstrapValidator.validators.different = {
  536. /**
  537. * Return true if the input value is different with given field's value
  538. *
  539. * @param {BootstrapValidator} validator The validator plugin instance
  540. * @param {jQuery} $field Field element
  541. * @param {Object} options Consists of the following key:
  542. * - field: The name of field that will be used to compare with current one
  543. * @returns {Boolean}
  544. */
  545. validate: function(validator, $field, options) {
  546. var value = $field.val();
  547. if (value == '') {
  548. return true;
  549. }
  550. var compareWith = validator.getFieldElements(options.field);
  551. if (compareWith == null) {
  552. return true;
  553. }
  554. if (value != compareWith.val()) {
  555. validator.updateStatus(compareWith, 'different', validator.STATUS_VALID);
  556. return true;
  557. } else {
  558. return false;
  559. }
  560. }
  561. };
  562. }(window.jQuery));
  563. ;(function($) {
  564. $.fn.bootstrapValidator.validators.digits = {
  565. /**
  566. * Return true if the input value contains digits only
  567. *
  568. * @param {BootstrapValidator} validator Validate plugin instance
  569. * @param {jQuery} $field Field element
  570. * @param {Object} options
  571. * @returns {Boolean}
  572. */
  573. validate: function(validator, $field, options) {
  574. var value = $field.val();
  575. if (value == '') {
  576. return true;
  577. }
  578. return /^\d+$/.test(value);
  579. }
  580. }
  581. }(window.jQuery));
  582. ;(function($) {
  583. $.fn.bootstrapValidator.validators.dkZipCode = {
  584. /**
  585. * Return true if and only if the input value is a valid DK zip code
  586. *
  587. * @param {BootstrapValidator} validator The validator plugin instance
  588. * @param {jQuery} $field Field element
  589. * @param {Object} options
  590. * @returns {Boolean}
  591. */
  592. validate: function(validateInstance, $field, options) {
  593. var value = $field.val();
  594. if (value == '') {
  595. return true;
  596. }
  597. return /^(DK(-|\s)?)?\d{4}$/i.test(value);
  598. }
  599. };
  600. }(window.jQuery));
  601. ;(function($) {
  602. $.fn.bootstrapValidator.validators.emailAddress = {
  603. /**
  604. * Return true if and only if the input value is a valid email address
  605. *
  606. * @param {BootstrapValidator} validator Validate plugin instance
  607. * @param {jQuery} $field Field element
  608. * @param {Object} options
  609. * @returns {Boolean}
  610. */
  611. validate: function(validator, $field, options) {
  612. var value = $field.val();
  613. if (value == '') {
  614. return true;
  615. }
  616. // Email address regular expression
  617. // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
  618. 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,}))$/;
  619. return emailRegExp.test(value);
  620. }
  621. }
  622. }(window.jQuery));
  623. ;(function($) {
  624. $.fn.bootstrapValidator.validators.greaterThan = {
  625. /**
  626. * Return true if the input value is greater than or equals to given number
  627. *
  628. * @param {BootstrapValidator} validator Validate plugin instance
  629. * @param {jQuery} $field Field element
  630. * @param {Object} options Can consist of the following keys:
  631. * - value: The number used to compare to
  632. * - inclusive [optional]: Can be true or false. Default is true
  633. * - message: The invalid message
  634. * @returns {Boolean}
  635. */
  636. validate: function(validator, $field, options) {
  637. var value = $field.val();
  638. if (value == '') {
  639. return true;
  640. }
  641. value = parseFloat(value);
  642. return (options.inclusive === true) ? (value > options.value) : (value >= options.value);
  643. }
  644. }
  645. }(window.jQuery));
  646. ;(function($) {
  647. $.fn.bootstrapValidator.validators.hexColor = {
  648. /**
  649. * Return true if the input value is a valid hex color
  650. *
  651. * @param {BootstrapValidator} validator The validator plugin instance
  652. * @param {jQuery} $field Field element
  653. * @param {Object} options Can consist of the following keys:
  654. * - message: The invalid message
  655. * @returns {Boolean}
  656. */
  657. validate: function(validator, $field, options) {
  658. var value = $field.val();
  659. if (value == '') {
  660. return true;
  661. }
  662. return /(^#[0-9A-F]{6}$)|(^#[0-9A-F]{3}$)/i.test(value);
  663. }
  664. };
  665. }(window.jQuery));
  666. ;(function($) {
  667. $.fn.bootstrapValidator.validators.identical = {
  668. /**
  669. * Check if input value equals to value of particular one
  670. *
  671. * @param {BootstrapValidator} validator The validator plugin instance
  672. * @param {jQuery} $field Field element
  673. * @param {Object} options Consists of the following key:
  674. * - field: The name of field that will be used to compare with current one
  675. * @returns {Boolean}
  676. */
  677. validate: function(validator, $field, options) {
  678. var value = $field.val();
  679. if (value == '') {
  680. return true;
  681. }
  682. var compareWith = validator.getFieldElements(options.field);
  683. if (compareWith == null) {
  684. return true;
  685. }
  686. if (value == compareWith.val()) {
  687. validator.updateStatus(compareWith, 'identical', validator.STATUS_VALID);
  688. return true;
  689. } else {
  690. return false;
  691. }
  692. }
  693. };
  694. }(window.jQuery));
  695. ;(function($) {
  696. $.fn.bootstrapValidator.validators.lessThan = {
  697. /**
  698. * Return true if the input value is less than or equal to given number
  699. *
  700. * @param {BootstrapValidator} validator The validator plugin instance
  701. * @param {jQuery} $field Field element
  702. * @param {Object} options Can consist of the following keys:
  703. * - value: The number used to compare to
  704. * - inclusive [optional]: Can be true or false. Default is true
  705. * - message: The invalid message
  706. * @returns {Boolean}
  707. */
  708. validate: function(validator, $field, options) {
  709. var value = $field.val();
  710. if (value == '') {
  711. return true;
  712. }
  713. value = parseFloat(value);
  714. return (options.inclusive === true) ? (value < options.value) : (value <= options.value);
  715. }
  716. };
  717. }(window.jQuery));
  718. ;(function($) {
  719. $.fn.bootstrapValidator.validators.notEmpty = {
  720. /**
  721. * Check if input value is empty or not
  722. *
  723. * @param {BootstrapValidator} validator The validator plugin instance
  724. * @param {jQuery} $field Field element
  725. * @param {Object} options
  726. * @returns {Boolean}
  727. */
  728. validate: function(validator, $field, options) {
  729. var type = $field.attr('type');
  730. if ('radio' == type || 'checkbox' == type) {
  731. return validator
  732. .getFieldElements($field.attr('name'))
  733. .filter(':checked')
  734. .length > 0;
  735. }
  736. return $.trim($field.val()) != '';
  737. }
  738. };
  739. }(window.jQuery));
  740. ;(function($) {
  741. $.fn.bootstrapValidator.validators.regexp = {
  742. /**
  743. * Check if the element value matches given regular expression
  744. *
  745. * @param {BootstrapValidator} validator The validator plugin instance
  746. * @param {jQuery} $field Field element
  747. * @param {Object} options Consists of the following key:
  748. * - regexp: The regular expression you need to check
  749. * @returns {Boolean}
  750. */
  751. validate: function(validator, $field, options) {
  752. var value = $field.val();
  753. if (value == '') {
  754. return true;
  755. }
  756. return options.regexp.test(value);
  757. }
  758. };
  759. }(window.jQuery));
  760. ;(function($) {
  761. $.fn.bootstrapValidator.validators.remote = {
  762. /**
  763. * Request a remote server to check the input value
  764. *
  765. * @param {BootstrapValidator} validator Plugin instance
  766. * @param {jQuery} $field Field element
  767. * @param {Object} options Can consist of the following keys:
  768. * - url
  769. * - data [optional]: By default, it will take the value
  770. * {
  771. * <fieldName>: <fieldValue>
  772. * }
  773. * - message: The invalid message
  774. * @returns {Boolean|Deferred}
  775. */
  776. validate: function(validator, $field, options) {
  777. var value = $field.val();
  778. if (value == '') {
  779. return true;
  780. }
  781. var name = $field.attr('name'), data = options.data;
  782. if (data == null) {
  783. data = {};
  784. }
  785. data[name] = value;
  786. var dfd = new $.Deferred();
  787. var xhr = $.ajax({
  788. type: 'POST',
  789. url: options.url,
  790. dataType: 'json',
  791. data: data
  792. });
  793. xhr.then(function(response) {
  794. dfd.resolve(response.valid === true || response.valid === 'true', 'remote');
  795. });
  796. dfd.fail(function() {
  797. xhr.abort();
  798. });
  799. return dfd;
  800. }
  801. };
  802. }(window.jQuery));
  803. ;(function($) {
  804. $.fn.bootstrapValidator.validators.stringLength = {
  805. /**
  806. * Check if the length of element value is less or more than given number
  807. *
  808. * @param {BootstrapValidator} validator The validator plugin instance
  809. * @param {jQuery} $field Field element
  810. * @param {Object} options Consists of following keys:
  811. * - min
  812. * - max
  813. * At least one of two keys is required
  814. * @returns {Boolean}
  815. */
  816. validate: function(validator, $field, options) {
  817. var value = $field.val();
  818. if (value == '') {
  819. return true;
  820. }
  821. var length = $.trim(value).length;
  822. if ((options.min && length < options.min) || (options.max && length > options.max)) {
  823. return false;
  824. }
  825. return true;
  826. }
  827. };
  828. }(window.jQuery));
  829. ;(function($) {
  830. $.fn.bootstrapValidator.validators.uri = {
  831. /**
  832. * Return true if the input value is a valid URL
  833. *
  834. * @param {BootstrapValidator} validator The validator plugin instance
  835. * @param {jQuery} $field Field element
  836. * @param {Object} options
  837. * @returns {Boolean}
  838. */
  839. validate: function(validator, $field, options) {
  840. var value = $field.val();
  841. if (value == '') {
  842. return true;
  843. }
  844. // Credit to https://gist.github.com/dperini/729294
  845. //
  846. // Regular Expression for URL validation
  847. //
  848. // Author: Diego Perini
  849. // Updated: 2010/12/05
  850. //
  851. // the regular expression composed & commented
  852. // could be easily tweaked for RFC compliance,
  853. // it was expressly modified to fit & satisfy
  854. // these test for an URL shortener:
  855. //
  856. // http://mathiasbynens.be/demo/url-regex
  857. //
  858. // Notes on possible differences from a standard/generic validation:
  859. //
  860. // - utf-8 char class take in consideration the full Unicode range
  861. // - TLDs have been made mandatory so single names like "localhost" fails
  862. // - protocols have been restricted to ftp, http and https only as requested
  863. //
  864. // Changes:
  865. //
  866. // - IP address dotted notation validation, range: 1.0.0.0 - 223.255.255.255
  867. // first and last IP address of each class is considered invalid
  868. // (since they are broadcast/network addresses)
  869. //
  870. // - Added exclusion of private, reserved and/or local networks ranges
  871. //
  872. // Compressed one-line versions:
  873. //
  874. // Javascript version
  875. //
  876. // /^(?:(?:https?|ftp):\/\/)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)(?:\.(?:[a-z\u00a1-\uffff0-9]+-?)*[a-z\u00a1-\uffff0-9]+)*(?:\.(?:[a-z\u00a1-\uffff]{2,})))(?::\d{2,5})?(?:\/[^\s]*)?$/i
  877. //
  878. // PHP version
  879. //
  880. // _^(?:(?:https?|ftp)://)(?:\S+(?::\S*)?@)?(?:(?!10(?:\.\d{1,3}){3})(?!127(?:\.\d{1,3}){3})(?!169\.254(?:\.\d{1,3}){2})(?!192\.168(?:\.\d{1,3}){2})(?!172\.(?:1[6-9]|2\d|3[0-1])(?:\.\d{1,3}){2})(?:[1-9]\d?|1\d\d|2[01]\d|22[0-3])(?:\.(?:1?\d{1,2}|2[0-4]\d|25[0-5])){2}(?:\.(?:[1-9]\d?|1\d\d|2[0-4]\d|25[0-4]))|(?:(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)(?:\.(?:[a-z\x{00a1}-\x{ffff}0-9]+-?)*[a-z\x{00a1}-\x{ffff}0-9]+)*(?:\.(?:[a-z\x{00a1}-\x{ffff}]{2,})))(?::\d{2,5})?(?:/[^\s]*)?$_iuS
  881. var urlExp = new RegExp(
  882. "^" +
  883. // protocol identifier
  884. "(?:(?:https?|ftp)://)" +
  885. // user:pass authentication
  886. "(?:\\S+(?::\\S*)?@)?" +
  887. "(?:" +
  888. // IP address exclusion
  889. // private & local networks
  890. "(?!10(?:\\.\\d{1,3}){3})" +
  891. "(?!127(?:\\.\\d{1,3}){3})" +
  892. "(?!169\\.254(?:\\.\\d{1,3}){2})" +
  893. "(?!192\\.168(?:\\.\\d{1,3}){2})" +
  894. "(?!172\\.(?:1[6-9]|2\\d|3[0-1])(?:\\.\\d{1,3}){2})" +
  895. // IP address dotted notation octets
  896. // excludes loopback network 0.0.0.0
  897. // excludes reserved space >= 224.0.0.0
  898. // excludes network & broacast addresses
  899. // (first & last IP address of each class)
  900. "(?:[1-9]\\d?|1\\d\\d|2[01]\\d|22[0-3])" +
  901. "(?:\\.(?:1?\\d{1,2}|2[0-4]\\d|25[0-5])){2}" +
  902. "(?:\\.(?:[1-9]\\d?|1\\d\\d|2[0-4]\\d|25[0-4]))" +
  903. "|" +
  904. // host name
  905. "(?:(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)" +
  906. // domain name
  907. "(?:\\.(?:[a-z\\u00a1-\\uffff0-9]+-?)*[a-z\\u00a1-\\uffff0-9]+)*" +
  908. // TLD identifier
  909. "(?:\\.(?:[a-z\\u00a1-\\uffff]{2,}))" +
  910. ")" +
  911. // port number
  912. "(?::\\d{2,5})?" +
  913. // resource path
  914. "(?:/[^\\s]*)?" +
  915. "$", "i"
  916. );
  917. return urlExp.test(value);
  918. }
  919. };
  920. }(window.jQuery));
  921. ;(function($) {
  922. $.fn.bootstrapValidator.validators.zipCode = {
  923. /**
  924. * Return true if and only if the input value is a valid country zip code
  925. *
  926. * @param {BootstrapValidator} validator The validator plugin instance
  927. * @param {jQuery} $field Field element
  928. * @param {Object} options Consist of key:
  929. * - country: The ISO 3166 country code
  930. *
  931. * Currently it supports the following countries:
  932. * - US (United State)
  933. * - DK (Denmark)
  934. * - SE (Sweden)
  935. *
  936. * @returns {Boolean}
  937. */
  938. validate: function(validateInstance, $field, options) {
  939. var value = $field.val();
  940. if (value == '' || !options.country) {
  941. return true;
  942. }
  943. switch (options.country.toUpperCase()) {
  944. case 'DK':
  945. return /^(DK(-|\s)?)?\d{4}$/i.test(value);
  946. case 'SE':
  947. return /^(S-)?\d{3}\s?\d{2}$/i.test(value);
  948. case 'US':
  949. default:
  950. return /^\d{5}([\-]\d{4})?$/.test(value);
  951. }
  952. }
  953. };
  954. }(window.jQuery));