├── test
├── helper.js
├── valid.json
├── invalid.json
├── spec
│ ├── validator
│ │ ├── cusip.js
│ │ ├── imo.js
│ │ ├── ean.js
│ │ ├── issn.js
│ │ ├── bic.js
│ │ ├── isin.js
│ │ ├── ismn.js
│ │ ├── identical.js
│ │ ├── ein.js
│ │ ├── isbn.js
│ │ ├── callback.js
│ │ ├── creditCard.js
│ │ └── meid.js
│ ├── dynamic.js
│ ├── api.js
│ ├── autoFocus.js
│ ├── enable.js
│ ├── transformer.js
│ └── message.js
└── index.html
├── .gitignore
├── screenshots
├── pure.gif
├── uikit.gif
├── bootstrap.gif
├── semantic.gif
└── foundation.gif
├── vendor
├── jasmine
│ ├── jasmine_favicon.png
│ └── jasmine.css
└── bootstrap
│ ├── fonts
│ ├── glyphicons-halflings-regular.eot
│ ├── glyphicons-halflings-regular.ttf
│ └── glyphicons-halflings-regular.woff
│ └── js
│ └── npm.js
├── demo
├── ajaxSubmit.php
├── target.php
├── remote.php
├── remote2.php
├── event2.html
├── tooltip.html
├── ignored.html
├── event3.html
├── container.html
├── selector2.html
└── mailgun.html
├── dist
├── js
│ └── framework
│ │ ├── pure.min.js
│ │ ├── semantic.min.js
│ │ ├── uikit.min.js
│ │ ├── foundation.min.js
│ │ ├── pure.js
│ │ └── bootstrap.min.js
└── css
│ └── formValidation.min.css
├── src
└── js
│ ├── validator
│ ├── digits.js
│ ├── siren.js
│ ├── hex.js
│ ├── mac.js
│ ├── base64.js
│ ├── siret.js
│ ├── bic.js
│ ├── blank.js
│ ├── integer.js
│ ├── rtn.js
│ ├── regexp.js
│ ├── notEmpty.js
│ ├── sedol.js
│ ├── ean.js
│ ├── grid.js
│ ├── stringCase.js
│ ├── numeric.js
│ ├── callback.js
│ ├── issn.js
│ ├── imo.js
│ ├── imei.js
│ ├── vin.js
│ ├── cusip.js
│ ├── uuid.js
│ ├── ismn.js
│ ├── ein.js
│ ├── step.js
│ ├── identical.js
│ ├── lessThan.js
│ ├── greaterThan.js
│ ├── isin.js
│ ├── between.js
│ ├── choice.js
│ ├── ip.js
│ ├── different.js
│ ├── isbn.js
│ ├── meid.js
│ ├── emailAddress.js
│ └── file.js
│ └── framework
│ └── pure.js
├── package.json
├── README.md
└── LICENSE.txt
/test/helper.js:
--------------------------------------------------------------------------------
1 | var TestSuite = {};
--------------------------------------------------------------------------------
/test/valid.json:
--------------------------------------------------------------------------------
1 | {
2 | "valid": true
3 | }
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .idea
2 | _gh_pages
3 | node_modules
--------------------------------------------------------------------------------
/test/invalid.json:
--------------------------------------------------------------------------------
1 | {
2 | "valid": "false"
3 | }
--------------------------------------------------------------------------------
/screenshots/pure.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icai/formvalidation/master/screenshots/pure.gif
--------------------------------------------------------------------------------
/screenshots/uikit.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icai/formvalidation/master/screenshots/uikit.gif
--------------------------------------------------------------------------------
/screenshots/bootstrap.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icai/formvalidation/master/screenshots/bootstrap.gif
--------------------------------------------------------------------------------
/screenshots/semantic.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icai/formvalidation/master/screenshots/semantic.gif
--------------------------------------------------------------------------------
/screenshots/foundation.gif:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icai/formvalidation/master/screenshots/foundation.gif
--------------------------------------------------------------------------------
/vendor/jasmine/jasmine_favicon.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icai/formvalidation/master/vendor/jasmine/jasmine_favicon.png
--------------------------------------------------------------------------------
/demo/ajaxSubmit.php:
--------------------------------------------------------------------------------
1 | sprintf('Welcome %s', $userName),
6 | ));
7 |
--------------------------------------------------------------------------------
/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icai/formvalidation/master/vendor/bootstrap/fonts/glyphicons-halflings-regular.eot
--------------------------------------------------------------------------------
/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icai/formvalidation/master/vendor/bootstrap/fonts/glyphicons-halflings-regular.ttf
--------------------------------------------------------------------------------
/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/icai/formvalidation/master/vendor/bootstrap/fonts/glyphicons-halflings-regular.woff
--------------------------------------------------------------------------------
/demo/target.php:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | FormValidation demo
5 |
6 |
7 |
8 |
9 |
10 |
Form data
11 |
12 |
This is a simple page showing the data you have just submitted
13 |
14 |
15 |
16 |
17 |
--------------------------------------------------------------------------------
/vendor/bootstrap/js/npm.js:
--------------------------------------------------------------------------------
1 | // This file is autogenerated via the `commonjs` Grunt task. You can require() this file in a CommonJS environment.
2 | require('../../js/transition.js')
3 | require('../../js/alert.js')
4 | require('../../js/button.js')
5 | require('../../js/carousel.js')
6 | require('../../js/collapse.js')
7 | require('../../js/dropdown.js')
8 | require('../../js/modal.js')
9 | require('../../js/tooltip.js')
10 | require('../../js/popover.js')
11 | require('../../js/scrollspy.js')
12 | require('../../js/tab.js')
13 | require('../../js/affix.js')
--------------------------------------------------------------------------------
/demo/remote.php:
--------------------------------------------------------------------------------
1 | 'admin@domain.com',
15 | 'administrator' => 'administrator@domain.com',
16 | 'root' => 'root@domain.com',
17 | );
18 |
19 | if (isset($_POST['username']) && array_key_exists($_POST['username'], $users)) {
20 | $valid = false;
21 | } else if (isset($_POST['email'])) {
22 | $email = $_POST['email'][0];
23 | foreach ($users as $k => $v) {
24 | if ($email == $v) {
25 | $valid = false;
26 | break;
27 | }
28 | }
29 | }
30 |
31 | echo json_encode(array(
32 | 'valid' => $valid,
33 | ));
34 |
--------------------------------------------------------------------------------
/demo/remote2.php:
--------------------------------------------------------------------------------
1 | 'admin@domain.com',
14 | 'administrator' => 'administrator@domain.com',
15 | 'root' => 'root@domain.com',
16 | );
17 |
18 | if (isset($_POST['username']) && array_key_exists($_POST['username'], $users)) {
19 | $valid = false;
20 | $message = 'The username is not available';
21 | } else if (isset($_POST['email'])) {
22 | $email = $_POST['email'];
23 | foreach ($users as $k => $v) {
24 | if ($email == $v) {
25 | $valid = false;
26 | $message = 'The email is not available';
27 | break;
28 | }
29 | }
30 | }
31 |
32 | echo json_encode(
33 | $valid ? array('valid' => $valid) : array('valid' => $valid, 'message' => $message)
34 | );
35 |
--------------------------------------------------------------------------------
/dist/js/framework/pure.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * FormValidation (http://formvalidation.io)
3 | * The best jQuery plugin to validate form fields. Support Bootstrap, Foundation, Pure, SemanticUI, UIKit and custom frameworks
4 | *
5 | * @version v0.6.2-dev, built on 2015-03-13 8:15:46 AM
6 | * @author https://twitter.com/nghuuphuoc
7 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
8 | * @license http://formvalidation.io/license/
9 | */
10 | !function(a){FormValidation.Framework.Pure=function(b,c){c=a.extend(!0,{button:{selector:'[type="submit"]',disabled:"pure-button-disabled"},err:{clazz:"fv-help-block",parent:"^.*pure-control-group.*$"},icon:{valid:null,invalid:null,validating:null,feedback:"fv-control-feedback"},row:{selector:".pure-control-group",valid:"fv-has-success",invalid:"fv-has-error",feedback:"fv-has-feedback"}},c),FormValidation.Base.apply(this,[b,c])},FormValidation.Framework.Pure.prototype=a.extend({},FormValidation.Base.prototype,{_fixIcon:function(a,b){var c=this._namespace,d=(a.attr("type"),a.attr("data-"+c+"-field")),e=this.options.fields[d].row||this.options.row.selector,f=a.closest(e);0===f.find("label").length&&b.addClass("fv-icon-no-label")}})}(jQuery);
--------------------------------------------------------------------------------
/src/js/validator/digits.js:
--------------------------------------------------------------------------------
1 | /**
2 | * digits validator
3 | *
4 | * @link http://formvalidation.io/validators/digits/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | digits: {
13 | 'default': 'Please enter only digits'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.digits = {
19 | /**
20 | * Return true if the input value contains digits only
21 | *
22 | * @param {FormValidation.Base} validator Validate plugin instance
23 | * @param {jQuery} $field Field element
24 | * @param {Object} [options]
25 | * @returns {Boolean}
26 | */
27 | validate: function(validator, $field, options) {
28 | var value = validator.getFieldValue($field, 'digits');
29 | if (value === '') {
30 | return true;
31 | }
32 |
33 | return /^\d+$/.test(value);
34 | }
35 | };
36 | }(jQuery));
37 |
--------------------------------------------------------------------------------
/src/js/validator/siren.js:
--------------------------------------------------------------------------------
1 | /**
2 | * siren validator
3 | *
4 | * @link http://formvalidation.io/validators/siren/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | siren: {
13 | 'default': 'Please enter a valid SIREN number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.siren = {
19 | /**
20 | * Check if a string is a siren number
21 | *
22 | * @param {FormValidation.Base} validator The validator plugin instance
23 | * @param {jQuery} $field Field element
24 | * @param {Object} options Consist of key:
25 | * - message: The invalid message
26 | * @returns {Boolean}
27 | */
28 | validate: function(validator, $field, options) {
29 | var value = validator.getFieldValue($field, 'siren');
30 | if (value === '') {
31 | return true;
32 | }
33 |
34 | if (!/^\d{9}$/.test(value)) {
35 | return false;
36 | }
37 | return FormValidation.Helper.luhn(value);
38 | }
39 | };
40 | }(jQuery));
41 |
--------------------------------------------------------------------------------
/src/js/validator/hex.js:
--------------------------------------------------------------------------------
1 | /**
2 | * hex validator
3 | *
4 | * @link http://formvalidation.io/validators/hex/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | hex: {
13 | 'default': 'Please enter a valid hexadecimal number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.hex = {
19 | /**
20 | * Return true if and only if the input value is a valid hexadecimal number
21 | *
22 | * @param {FormValidation.Base} validator The validator plugin instance
23 | * @param {jQuery} $field Field element
24 | * @param {Object} options Consist of key:
25 | * - message: The invalid message
26 | * @returns {Boolean}
27 | */
28 | validate: function(validator, $field, options) {
29 | var value = validator.getFieldValue($field, 'hex');
30 | if (value === '') {
31 | return true;
32 | }
33 |
34 | return /^[0-9a-fA-F]+$/.test(value);
35 | }
36 | };
37 | }(jQuery));
38 |
--------------------------------------------------------------------------------
/src/js/validator/mac.js:
--------------------------------------------------------------------------------
1 | /**
2 | * mac validator
3 | *
4 | * @link http://formvalidation.io/validators/mac/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | mac: {
13 | 'default': 'Please enter a valid MAC address'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.mac = {
19 | /**
20 | * Return true if the input value is a MAC address.
21 | *
22 | * @param {FormValidation.Base} validator The validator plugin instance
23 | * @param {jQuery} $field Field element
24 | * @param {Object} options Can consist of the following keys:
25 | * - message: The invalid message
26 | * @returns {Boolean}
27 | */
28 | validate: function(validator, $field, options) {
29 | var value = validator.getFieldValue($field, 'mac');
30 | if (value === '') {
31 | return true;
32 | }
33 |
34 | return /^([0-9A-F]{2}[:-]){5}([0-9A-F]{2})$/.test(value);
35 | }
36 | };
37 | }(jQuery));
38 |
--------------------------------------------------------------------------------
/src/js/validator/base64.js:
--------------------------------------------------------------------------------
1 | /**
2 | * base64 validator
3 | *
4 | * @link http://formvalidation.io/validators/base64/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | base64: {
13 | 'default': 'Please enter a valid base 64 encoded'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.base64 = {
19 | /**
20 | * Return true if the input value is a base 64 encoded string.
21 | *
22 | * @param {FormValidation.Base} validator The validator plugin instance
23 | * @param {jQuery} $field Field element
24 | * @param {Object} options Can consist of the following keys:
25 | * - message: The invalid message
26 | * @returns {Boolean}
27 | */
28 | validate: function(validator, $field, options) {
29 | var value = validator.getFieldValue($field, 'base64');
30 | if (value === '') {
31 | return true;
32 | }
33 |
34 | return /^(?:[A-Za-z0-9+/]{4})*(?:[A-Za-z0-9+/]{2}==|[A-Za-z0-9+/]{3}=|[A-Za-z0-9+/]{4})$/.test(value);
35 | }
36 | };
37 | }(jQuery));
38 |
--------------------------------------------------------------------------------
/test/spec/validator/cusip.js:
--------------------------------------------------------------------------------
1 | describe('cusip', function() {
2 | beforeEach(function() {
3 | $([
4 | ''
9 | ].join('\n')).appendTo('body');
10 | $('#cusipForm').formValidation();
11 |
12 | this.fv = $('#cusipForm').data('formValidation');
13 | this.$cusip = this.fv.getFieldElements('cusip');
14 | });
15 |
16 | afterEach(function() {
17 | $('#cusipForm').formValidation('destroy').remove();
18 | });
19 |
20 | it('valid', function() {
21 | var samples = ['037833100', '931142103', '14149YAR8', '126650BG6'];
22 |
23 | for (var i in samples) {
24 | this.fv.resetForm();
25 | this.$cusip.val(samples[i]);
26 | this.fv.validate();
27 | expect(this.fv.isValidField('cusip')).toBeTruthy();
28 | }
29 | });
30 |
31 | it('invalid', function() {
32 | var samples = ['31430F200', '022615AC2'];
33 |
34 | for (var i in samples) {
35 | this.fv.resetForm();
36 | this.$cusip.val(samples[i]);
37 | this.fv.validate();
38 | expect(this.fv.isValidField('cusip')).toEqual(false);
39 | }
40 | });
41 | });
42 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "formvalidation",
3 | "version": "0.6.2-dev",
4 | "description": "The best jQuery plugin to validate form fields. Support Bootstrap, Foundation, Pure, SemanticUI, UIKit and custom frameworks",
5 | "keywords": [
6 | "jQuery",
7 | "plugin",
8 | "validate",
9 | "validator",
10 | "form",
11 | "Bootstrap",
12 | "Foundation",
13 | "Pure",
14 | "SemanticUI",
15 | "UIKit"
16 | ],
17 | "author": {
18 | "name": "Nguyen Huu Phuoc",
19 | "email": "phuoc@huuphuoc.me",
20 | "url": "https://twitter.com/nghuuphuoc"
21 | },
22 | "homepage": "http://formvalidation.io",
23 | "bugs": {
24 | "url": "https://github.com/formvalidation/formvalidation/issues",
25 | "email": "phuoc@huuphuoc.me"
26 | },
27 | "license": "http://formvalidation.io/license/",
28 | "main": "./dist/js/formValidation.js",
29 | "repository": {
30 | "type": "git",
31 | "url": "https://github.com/formvalidation/formvalidation.git"
32 | },
33 | "devDependencies": {
34 | "grunt": "latest",
35 | "grunt-contrib-concat": "latest",
36 | "grunt-contrib-copy": "latest",
37 | "grunt-contrib-cssmin": "latest",
38 | "grunt-contrib-jasmine": "latest",
39 | "grunt-contrib-jshint": "latest",
40 | "grunt-contrib-uglify": "latest",
41 | "grunt-contrib-watch": "latest"
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/src/js/validator/siret.js:
--------------------------------------------------------------------------------
1 | /**
2 | * siret validator
3 | *
4 | * @link http://formvalidation.io/validators/siret/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | siret: {
13 | 'default': 'Please enter a valid SIRET number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.siret = {
19 | /**
20 | * Check if a string is a siret number
21 | *
22 | * @param {FormValidation.Base} validator The validator plugin instance
23 | * @param {jQuery} $field Field element
24 | * @param {Object} options Consist of key:
25 | * - message: The invalid message
26 | * @returns {Boolean}
27 | */
28 | validate: function(validator, $field, options) {
29 | var value = validator.getFieldValue($field, 'siret');
30 | if (value === '') {
31 | return true;
32 | }
33 |
34 | var sum = 0,
35 | length = value.length,
36 | tmp;
37 | for (var i = 0; i < length; i++) {
38 | tmp = parseInt(value.charAt(i), 10);
39 | if ((i % 2) === 0) {
40 | tmp = tmp * 2;
41 | if (tmp > 9) {
42 | tmp -= 9;
43 | }
44 | }
45 | sum += tmp;
46 | }
47 | return (sum % 10 === 0);
48 | }
49 | };
50 | }(jQuery));
51 |
--------------------------------------------------------------------------------
/src/js/validator/bic.js:
--------------------------------------------------------------------------------
1 | /**
2 | * bic validator
3 | *
4 | * @link http://formvalidation.io/validators/bic/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | bic: {
13 | 'default': 'Please enter a valid BIC number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.bic = {
19 | /**
20 | * Validate an Business Identifier Code (BIC), also known as ISO 9362, SWIFT-BIC, SWIFT ID or SWIFT code
21 | *
22 | * For more information see http://en.wikipedia.org/wiki/ISO_9362
23 | *
24 | * @todo The 5 and 6 characters are an ISO 3166-1 country code, this could also be validated
25 | * @param {FormValidation.Base} validator The validator plugin instance
26 | * @param {jQuery} $field Field element
27 | * @param {Object} options Can consist of the following keys:
28 | * - message: The invalid message
29 | * @returns {Object}
30 | */
31 | validate: function(validator, $field, options) {
32 | var value = validator.getFieldValue($field, 'bic');
33 | if (value === '') {
34 | return true;
35 | }
36 | return /^[a-zA-Z]{6}[a-zA-Z0-9]{2}([a-zA-Z0-9]{3})?$/.test(value);
37 | }
38 | };
39 | }(jQuery));
40 |
--------------------------------------------------------------------------------
/test/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FormValidation test suites
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/src/js/validator/blank.js:
--------------------------------------------------------------------------------
1 | /**
2 | * blank validator
3 | *
4 | * @author https://twitter.com/nghuuphuoc
5 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
6 | * @license http://formvalidation.io/license/
7 | */
8 | (function($) {
9 | FormValidation.Validator.blank = {
10 | /**
11 | * Placeholder validator that can be used to display a custom validation message
12 | * returned from the server
13 | * Example:
14 | *
15 | * (1) a "blank" validator is applied to an input field.
16 | * (2) data is entered via the UI that is unable to be validated client-side.
17 | * (3) server returns a 400 with JSON data that contains the field that failed
18 | * validation and an associated message.
19 | * (4) ajax 400 call handler does the following:
20 | *
21 | * bv.updateMessage(field, 'blank', errorMessage);
22 | * bv.updateStatus(field, 'INVALID');
23 | *
24 | * @see https://github.com/formvalidation/formvalidation/issues/542
25 | * @see https://github.com/formvalidation/formvalidation/pull/666
26 | * @param {FormValidation.Base} validator The validator plugin instance
27 | * @param {jQuery} $field Field element
28 | * @param {Object} options Can consist of the following keys:
29 | * - message: The invalid message
30 | * @returns {Boolean}
31 | */
32 | validate: function(validator, $field, options) {
33 | return true;
34 | }
35 | };
36 | }(jQuery));
37 |
--------------------------------------------------------------------------------
/test/spec/validator/imo.js:
--------------------------------------------------------------------------------
1 | describe('imo', function() {
2 | beforeEach(function() {
3 | $([
4 | ''
9 | ].join('\n')).appendTo('body');
10 |
11 | $('#imoForm').formValidation();
12 |
13 | this.fv = $('#imoForm').data('formValidation');
14 | this.$imo = this.fv.getFieldElements('imo');
15 | });
16 |
17 | afterEach(function() {
18 | $('#imoForm').formValidation('destroy').remove();
19 | });
20 |
21 | it('Valid IMO (upper)', function() {
22 | this.fv.resetForm();
23 | this.$imo.val('IMO 9074729');
24 | this.fv.validate();
25 | expect(this.fv.isValid()).toBeTruthy();
26 | });
27 |
28 | it('Valid IMO (lower)', function() {
29 | this.fv.resetForm();
30 | this.$imo.val('imo 9074729');
31 | this.fv.validate();
32 | expect(this.fv.isValid()).toBeTruthy();
33 | });
34 |
35 | it('Invalid IMO (bad format)', function() {
36 | this.fv.resetForm();
37 | this.$imo.val('9074729');
38 | this.fv.validate();
39 | expect(this.fv.isValid()).toBeFalsy();
40 | });
41 |
42 | it('Invalid IMO (bad check digit)', function() {
43 | this.fv.resetForm();
44 | this.$imo.val('IMO 9074728');
45 | this.fv.validate();
46 | expect(this.fv.isValid()).toBeFalsy();
47 | });
48 | });
49 |
--------------------------------------------------------------------------------
/src/js/validator/integer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * integer validator
3 | *
4 | * @link http://formvalidation.io/validators/integer/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | integer: {
13 | 'default': 'Please enter a valid number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.integer = {
19 | enableByHtml5: function($field) {
20 | return ('number' === $field.attr('type')) && ($field.attr('step') === undefined || $field.attr('step') % 1 === 0);
21 | },
22 |
23 | /**
24 | * Return true if the input value is an integer
25 | *
26 | * @param {FormValidation.Base} validator The validator plugin instance
27 | * @param {jQuery} $field Field element
28 | * @param {Object} options Can consist of the following key:
29 | * - message: The invalid message
30 | * @returns {Boolean}
31 | */
32 | validate: function(validator, $field, options) {
33 | if (this.enableByHtml5($field) && $field.get(0).validity && $field.get(0).validity.badInput === true) {
34 | return false;
35 | }
36 |
37 | var value = validator.getFieldValue($field, 'integer');
38 | if (value === '') {
39 | return true;
40 | }
41 | return /^(?:-?(?:0|[1-9][0-9]*))$/.test(value);
42 | }
43 | };
44 | }(jQuery));
45 |
--------------------------------------------------------------------------------
/dist/js/framework/semantic.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * FormValidation (http://formvalidation.io)
3 | * The best jQuery plugin to validate form fields. Support Bootstrap, Foundation, Pure, SemanticUI, UIKit and custom frameworks
4 | *
5 | * @version v0.6.2-dev, built on 2015-03-13 8:15:46 AM
6 | * @author https://twitter.com/nghuuphuoc
7 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
8 | * @license http://formvalidation.io/license/
9 | */
10 | !function(a){FormValidation.Framework.Semantic=function(b,c){c=a.extend(!0,{button:{selector:'[type="submit"]',disabled:"disabled"},control:{valid:"",invalid:""},err:{clazz:"ui red pointing label transition",parent:"^.*(field|column).*$"},icon:{valid:null,invalid:null,validating:null,feedback:"fv-control-feedback"},row:{selector:".field",valid:"fv-has-success",invalid:"error",feedback:"fv-has-feedback"}},c),FormValidation.Base.apply(this,[b,c])},FormValidation.Framework.Semantic.prototype=a.extend({},FormValidation.Base.prototype,{_fixIcon:function(a,b){var c=a.attr("type");if("checkbox"===c||"radio"===c){var d=a.parent();d.hasClass(c)&&b.insertAfter(d)}},_createTooltip:function(a,b,c){var d=a.data("fv.icon");if(d)switch(d.popup("exists")&&d.popup("remove popup").popup("destroy"),c){case"popover":d.css({cursor:"pointer"}).popup({content:b,position:"top center"});break;case"tooltip":default:d.css({cursor:"pointer"}).popup({content:b,position:"top center",variation:"inverted"})}},_destroyTooltip:function(a){var b=a.data("fv.icon");b&&b.popup("exists")&&b.css({cursor:""}).popup("remove popup").popup("destroy")},_hideTooltip:function(a){var b=a.data("fv.icon");b&&b.popup("hide")},_showTooltip:function(a){var b=a.data("fv.icon");b&&b.popup("show")}})}(jQuery);
--------------------------------------------------------------------------------
/test/spec/validator/ean.js:
--------------------------------------------------------------------------------
1 | describe('ean', function() {
2 | beforeEach(function() {
3 | var html = [
4 | ''
11 | ].join('\n');
12 |
13 | $(html).appendTo('body');
14 | $('#eanForm').formValidation();
15 |
16 | this.fv = $('#eanForm').data('formValidation');
17 | this.$ean = this.fv.getFieldElements('ean');
18 | });
19 |
20 | afterEach(function() {
21 | $('#eanForm').formValidation('destroy').parent().remove();
22 | });
23 |
24 | it('valid', function() {
25 | var samples = ['73513537', '9780471117094', '4006381333931'];
26 |
27 | for (var i in samples) {
28 | this.$ean.val(samples[i]);
29 | this.fv.validate();
30 | expect(this.fv.isValidField('ean')).toBeTruthy();
31 | }
32 | });
33 |
34 | it('contains only digits', function() {
35 | this.$ean.val('123abcDEF!@#');
36 | this.fv.validate();
37 | expect(this.fv.isValidField('ean')).toEqual(false);
38 | });
39 |
40 | it('invalid length', function() {
41 | this.$ean.val('1234567');
42 | this.fv.validate();
43 | expect(this.fv.isValidField('ean')).toEqual(false);
44 | });
45 |
46 | it('invalid check digit', function() {
47 | this.$ean.val('73513536');
48 | this.fv.validate();
49 | expect(this.fv.isValidField('ean')).toEqual(false);
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/test/spec/validator/issn.js:
--------------------------------------------------------------------------------
1 | describe('issn', function() {
2 | beforeEach(function() {
3 | var html = [
4 | ''
11 | ].join('\n');
12 |
13 | $(html).appendTo('body');
14 | $('#issnForm').formValidation();
15 |
16 | this.fv = $('#issnForm').data('formValidation');
17 | this.$issn = this.fv.getFieldElements('issn');
18 | });
19 |
20 | afterEach(function() {
21 | $('#issnForm').formValidation('destroy').parent().remove();
22 | });
23 |
24 | it('valid', function() {
25 | var samples = ['0378-5955', '0024-9319', '0032-1478'];
26 |
27 | for (var i in samples) {
28 | this.$issn.val(samples[i]);
29 | this.fv.validate();
30 | expect(this.fv.isValidField('issn')).toBeTruthy();
31 | }
32 | });
33 |
34 | it('not contains hyphen', function() {
35 | this.$issn.val('03785955');
36 | this.fv.validate();
37 | expect(this.fv.isValidField('issn')).toEqual(false);
38 | });
39 |
40 | it('contains only digits, X', function() {
41 | this.$issn.val('1234-566A');
42 | this.fv.validate();
43 | expect(this.fv.isValidField('issn')).toEqual(false);
44 | });
45 |
46 | it('invalid check sum', function() {
47 | this.$issn.val('0032-147X');
48 | this.fv.validate();
49 | expect(this.fv.isValidField('issn')).toEqual(false);
50 | });
51 | });
52 |
--------------------------------------------------------------------------------
/test/spec/validator/bic.js:
--------------------------------------------------------------------------------
1 | describe('bic', function() {
2 | beforeEach(function() {
3 | $([
4 | ''
9 | ].join('\n')).appendTo('body');
10 |
11 | $('#bicForm').formValidation();
12 |
13 | this.fv = $('#bicForm').data('formValidation');
14 | this.$bic = this.fv.getFieldElements('bic');
15 | });
16 |
17 | afterEach(function() {
18 | $('#bicForm').formValidation('destroy').remove();
19 | });
20 |
21 | it('invalid bic', function() {
22 | // Test some invalid BICs
23 | var invalidSamples = [
24 | 'ASPKAT2LXX', 'ASPKAT2LX', 'ASPKAT2LXXX1', 'DABADKK', 'RZ00AT2L303',
25 | // Invalid fist 6 characters
26 | '1SBACNBXSHA', 'D2BACNBXSHA', 'DS3ACNBXSHA', 'DSB4CNBXSHA', 'DSBA5NBXSHA', 'DSBAC6BXSHA', '1S3AC6BXSHA'
27 | ];
28 | for (i in invalidSamples) {
29 | this.fv.resetForm();
30 | this.$bic.val(invalidSamples[i]);
31 | this.fv.validate();
32 | expect(this.fv.isValid()).toEqual(false);
33 | }
34 | });
35 |
36 | it('valid bic', function() {
37 | // Examples see http://en.wikipedia.org/wiki/ISO_9362
38 | var validSamples = ['ASPKAT2LXXX', 'ASPKAT2L', 'DSBACNBXSHA', 'UNCRIT2B912', 'DABADKKK', 'RZOOAT2L303'];
39 | for (i in validSamples) {
40 | this.fv.resetForm();
41 | this.$bic.val(validSamples[i]);
42 | this.fv.validate();
43 | expect(this.fv.isValid()).toBeTruthy();
44 | }
45 | });
46 | });
47 |
--------------------------------------------------------------------------------
/src/js/validator/rtn.js:
--------------------------------------------------------------------------------
1 | /**
2 | * rtn validator
3 | *
4 | * @link http://formvalidation.io/validators/rtn/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | rtn: {
13 | 'default': 'Please enter a valid RTN number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.rtn = {
19 | /**
20 | * Validate a RTN (Routing transit number)
21 | * Examples:
22 | * - Valid: 021200025, 789456124
23 | *
24 | * @see http://en.wikipedia.org/wiki/Routing_transit_number
25 | * @param {FormValidation.Base} validator The validator plugin instance
26 | * @param {jQuery} $field Field element
27 | * @param {Object} options Can consist of the following keys:
28 | * - message: The invalid message
29 | * @returns {Boolean}
30 | */
31 | validate: function(validator, $field, options) {
32 | var value = validator.getFieldValue($field, 'rtn');
33 | if (value === '') {
34 | return true;
35 | }
36 |
37 | if (!/^\d{9}$/.test(value)) {
38 | return false;
39 | }
40 |
41 | var sum = 0;
42 | for (var i = 0; i < value.length; i += 3) {
43 | sum += parseInt(value.charAt(i), 10) * 3
44 | + parseInt(value.charAt(i + 1), 10) * 7
45 | + parseInt(value.charAt(i + 2), 10);
46 | }
47 | return (sum !== 0 && sum % 10 === 0);
48 | }
49 | };
50 | }(jQuery));
51 |
--------------------------------------------------------------------------------
/src/js/validator/regexp.js:
--------------------------------------------------------------------------------
1 | /**
2 | * regexp validator
3 | *
4 | * @link http://formvalidation.io/validators/regexp/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | regexp: {
13 | 'default': 'Please enter a value matching the pattern'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.regexp = {
19 | html5Attributes: {
20 | message: 'message',
21 | regexp: 'regexp'
22 | },
23 |
24 | enableByHtml5: function($field) {
25 | var pattern = $field.attr('pattern');
26 | if (pattern) {
27 | return {
28 | regexp: pattern
29 | };
30 | }
31 |
32 | return false;
33 | },
34 |
35 | /**
36 | * Check if the element value matches given regular expression
37 | *
38 | * @param {FormValidation.Base} validator The validator plugin instance
39 | * @param {jQuery} $field Field element
40 | * @param {Object} options Consists of the following key:
41 | * - regexp: The regular expression you need to check
42 | * @returns {Boolean}
43 | */
44 | validate: function(validator, $field, options) {
45 | var value = validator.getFieldValue($field, 'regexp');
46 | if (value === '') {
47 | return true;
48 | }
49 |
50 | var regexp = ('string' === typeof options.regexp) ? new RegExp(options.regexp) : options.regexp;
51 | return regexp.test(value);
52 | }
53 | };
54 | }(jQuery));
55 |
--------------------------------------------------------------------------------
/dist/css/formValidation.min.css:
--------------------------------------------------------------------------------
1 | .fv-has-feedback{position:relative}.fv-control-feedback{position:absolute;top:0;right:0;z-index:2;display:block;width:34px;height:34px;line-height:34px;text-align:center}.fv-help-block{display:block}.fv-form-bootstrap .help-block{margin-bottom:0}.fv-form-bootstrap .tooltip-inner{text-align:left}.fv-form-bootstrap .fv-icon-no-label{top:0}.fv-form-bootstrap .fv-bootstrap-icon-input-group{z-index:100}.form-inline.fv-form-bootstrap .form-group{vertical-align:top}.fv-form-foundation .fv-control-feedback{top:21px;right:15px;width:37px;height:37px;line-height:37px}.fv-form-foundation .collapse .fv-control-feedback{top:0;right:0}.fv-form-foundation .fv-icon-no-label,.fv-form-horizontal.fv-form-foundation .fv-control-feedback{top:0}.fv-form-foundation .error .fv-control-feedback{color:#f04124}.error.fv-has-tooltip select,.error.fv-has-tooltip textarea,.fv-form-foundation .error.fv-has-tooltip input{margin-bottom:1rem}.fv-form-pure .fv-control-feedback{top:22px;width:36px;height:36px;line-height:36px}.pure-form-stacked.fv-form-pure .fv-control-feedback{top:4px}.pure-form-aligned .pure-control-group .fv-help-block{margin-top:5px;margin-left:180px}.fv-form-pure .fv-icon-no-label,.pure-form-aligned.fv-form-pure .fv-control-feedback{top:0}.fv-form-pure .fv-has-error .fv-control-feedback,.fv-form-pure .fv-has-error .fv-help-block,.fv-form-pure .fv-has-error label{color:#CA3C3C}.fv-form-semantic .fv-control-feedback.icon{right:7px}.fv-form-semantic .error .icon{color:#d95c5c}.fv-form-horizontal.fv-form-semantic .row{padding-bottom:0}.fv-form-uikit .fv-control-feedback{top:25px;width:30px;height:30px;line-height:30px}.fv-form-uikit .uk-text-danger{display:block}.uk-form-horizontal.fv-form-uikit .fv-control-feedback{top:0}.fv-form-uikit .fv-has-error .fv-control-feedback,.fv-form-uikit .fv-has-error .uk-form-label,.fv-form-uikit .fv-has-error label{color:#D85030}.fv-form-uikit .fv-icon-no-label{top:0}
--------------------------------------------------------------------------------
/src/js/validator/notEmpty.js:
--------------------------------------------------------------------------------
1 | /**
2 | * notEmpty validator
3 | *
4 | * @link http://formvalidation.io/validators/notEmpty/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | notEmpty: {
13 | 'default': 'Please enter a value'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.notEmpty = {
19 | enableByHtml5: function($field) {
20 | var required = $field.attr('required') + '';
21 | return ('required' === required || 'true' === required);
22 | },
23 |
24 | /**
25 | * Check if input value is empty or not
26 | *
27 | * @param {FormValidation.Base} validator The validator plugin instance
28 | * @param {jQuery} $field Field element
29 | * @param {Object} options
30 | * @returns {Boolean}
31 | */
32 | validate: function(validator, $field, options) {
33 | var type = $field.attr('type');
34 | if ('radio' === type || 'checkbox' === type) {
35 | var ns = validator.getNamespace();
36 | return validator
37 | .getFieldElements($field.attr('data-' + ns + '-field'))
38 | .filter(':checked')
39 | .length > 0;
40 | }
41 |
42 | if ('number' === type && $field.get(0).validity && $field.get(0).validity.badInput === true) {
43 | return true;
44 | }
45 |
46 | var value = validator.getFieldValue($field, 'notEmpty');
47 | return $.trim(value) !== '';
48 | }
49 | };
50 | }(jQuery));
51 |
--------------------------------------------------------------------------------
/dist/js/framework/uikit.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * FormValidation (http://formvalidation.io)
3 | * The best jQuery plugin to validate form fields. Support Bootstrap, Foundation, Pure, SemanticUI, UIKit and custom frameworks
4 | *
5 | * @version v0.6.2-dev, built on 2015-03-13 8:15:46 AM
6 | * @author https://twitter.com/nghuuphuoc
7 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
8 | * @license http://formvalidation.io/license/
9 | */
10 | !function(a){FormValidation.Framework.Uikit=function(b,c){c=a.extend(!0,{button:{selector:'[type="submit"]',disabled:"disabled"},control:{valid:"uk-form-success",invalid:"uk-form-danger"},err:{clazz:"uk-text-danger",parent:"^.*(uk-form-controls|uk-width-[\\d+]-[\\d+]).*$"},icon:{valid:null,invalid:null,validating:null,feedback:"fv-control-feedback"},row:{selector:".uk-form-row",valid:"fv-has-success",invalid:"fv-has-error",feedback:"fv-has-feedback"}},c),FormValidation.Base.apply(this,[b,c])},FormValidation.Framework.Uikit.prototype=a.extend({},FormValidation.Base.prototype,{_fixIcon:function(a,b){var c=this._namespace,d=a.attr("type"),e=a.attr("data-"+c+"-field"),f=this.options.fields[e].row||this.options.row.selector,g=a.closest(f);if("checkbox"===d||"radio"===d){var h=a.parent();h.is("label")&&b.insertAfter(h)}0===g.find("label").length&&b.addClass("fv-icon-no-label")},_createTooltip:function(b,c){var d=b.data("fv.icon");d&&(d.data("tooltip")&&(d.data("tooltip").off(),d.removeData("tooltip")),d.attr("title",c).css({cursor:"pointer"}),new a.UIkit.tooltip(d))},_destroyTooltip:function(a){var b=a.data("fv.icon");if(b){var c=b.data("tooltip");c&&(c.hide(),c.off(),b.off("focus mouseenter").removeData("tooltip")),b.css({cursor:""})}},_hideTooltip:function(a){var b=a.data("fv.icon");if(b){var c=b.data("tooltip");c&&c.hide(),b.css({cursor:""})}},_showTooltip:function(a){var b=a.data("fv.icon");if(b){b.css({cursor:"pointer"});var c=b.data("tooltip");c&&c.show()}}})}(jQuery);
--------------------------------------------------------------------------------
/src/js/validator/sedol.js:
--------------------------------------------------------------------------------
1 | /**
2 | * sedol validator
3 | *
4 | * @link http://formvalidation.io/validators/sedol/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | sedol: {
13 | 'default': 'Please enter a valid SEDOL number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.sedol = {
19 | /**
20 | * Validate a SEDOL (Stock Exchange Daily Official List)
21 | * Examples:
22 | * - Valid: 0263494, B0WNLY7
23 | *
24 | * @see http://en.wikipedia.org/wiki/SEDOL
25 | * @param {FormValidation.Base} validator The validator plugin instance
26 | * @param {jQuery} $field Field element
27 | * @param {Object} options Can consist of the following keys:
28 | * - message: The invalid message
29 | * @returns {Boolean}
30 | */
31 | validate: function(validator, $field, options) {
32 | var value = validator.getFieldValue($field, 'sedol');
33 | if (value === '') {
34 | return true;
35 | }
36 |
37 | value = value.toUpperCase();
38 | if (!/^[0-9A-Z]{7}$/.test(value)) {
39 | return false;
40 | }
41 |
42 | var sum = 0,
43 | weight = [1, 3, 1, 7, 3, 9, 1],
44 | length = value.length;
45 | for (var i = 0; i < length - 1; i++) {
46 | sum += weight[i] * parseInt(value.charAt(i), 36);
47 | }
48 | sum = (10 - sum % 10) % 10;
49 | return sum + '' === value.charAt(length - 1);
50 | }
51 | };
52 | }(jQuery));
53 |
--------------------------------------------------------------------------------
/src/js/validator/ean.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ean validator
3 | *
4 | * @link http://formvalidation.io/validators/ean/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | ean: {
13 | 'default': 'Please enter a valid EAN number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.ean = {
19 | /**
20 | * Validate EAN (International Article Number)
21 | * Examples:
22 | * - Valid: 73513537, 9780471117094, 4006381333931
23 | * - Invalid: 73513536
24 | *
25 | * @see http://en.wikipedia.org/wiki/European_Article_Number
26 | * @param {FormValidation.Base} validator The validator plugin instance
27 | * @param {jQuery} $field Field element
28 | * @param {Object} options Can consist of the following keys:
29 | * - message: The invalid message
30 | * @returns {Boolean}
31 | */
32 | validate: function(validator, $field, options) {
33 | var value = validator.getFieldValue($field, 'ean');
34 | if (value === '') {
35 | return true;
36 | }
37 |
38 | if (!/^(\d{8}|\d{12}|\d{13})$/.test(value)) {
39 | return false;
40 | }
41 |
42 | var length = value.length,
43 | sum = 0,
44 | weight = (length === 8) ? [3, 1] : [1, 3];
45 | for (var i = 0; i < length - 1; i++) {
46 | sum += parseInt(value.charAt(i), 10) * weight[i % 2];
47 | }
48 | sum = (10 - sum % 10) % 10;
49 | return (sum + '' === value.charAt(length - 1));
50 | }
51 | };
52 | }(jQuery));
53 |
--------------------------------------------------------------------------------
/src/js/validator/grid.js:
--------------------------------------------------------------------------------
1 | /**
2 | * grid validator
3 | *
4 | * @link http://formvalidation.io/validators/grid/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | grid: {
13 | 'default': 'Please enter a valid GRId number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.grid = {
19 | /**
20 | * Validate GRId (Global Release Identifier)
21 | * Examples:
22 | * - Valid: A12425GABC1234002M, A1-2425G-ABC1234002-M, A1 2425G ABC1234002 M, Grid:A1-2425G-ABC1234002-M
23 | * - Invalid: A1-2425G-ABC1234002-Q
24 | *
25 | * @see http://en.wikipedia.org/wiki/Global_Release_Identifier
26 | * @param {FormValidation.Base} validator The validator plugin instance
27 | * @param {jQuery} $field Field element
28 | * @param {Object} options Can consist of the following keys:
29 | * - message: The invalid message
30 | * @returns {Boolean}
31 | */
32 | validate: function(validator, $field, options) {
33 | var value = validator.getFieldValue($field, 'grid');
34 | if (value === '') {
35 | return true;
36 | }
37 |
38 | value = value.toUpperCase();
39 | if (!/^[GRID:]*([0-9A-Z]{2})[-\s]*([0-9A-Z]{5})[-\s]*([0-9A-Z]{10})[-\s]*([0-9A-Z]{1})$/g.test(value)) {
40 | return false;
41 | }
42 | value = value.replace(/\s/g, '').replace(/-/g, '');
43 | if ('GRID:' === value.substr(0, 5)) {
44 | value = value.substr(5);
45 | }
46 | return FormValidation.Helper.mod37And36(value);
47 | }
48 | };
49 | }(jQuery));
50 |
--------------------------------------------------------------------------------
/src/js/validator/stringCase.js:
--------------------------------------------------------------------------------
1 | /**
2 | * stringCase validator
3 | *
4 | * @link http://formvalidation.io/validators/stringCase/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | stringCase: {
13 | 'default': 'Please enter only lowercase characters',
14 | upper: 'Please enter only uppercase characters'
15 | }
16 | }
17 | });
18 |
19 | FormValidation.Validator.stringCase = {
20 | html5Attributes: {
21 | message: 'message',
22 | 'case': 'case'
23 | },
24 |
25 | /**
26 | * Check if a string is a lower or upper case one
27 | *
28 | * @param {FormValidation.Base} validator The validator plugin instance
29 | * @param {jQuery} $field Field element
30 | * @param {Object} options Consist of key:
31 | * - message: The invalid message
32 | * - case: Can be 'lower' (default) or 'upper'
33 | * @returns {Object}
34 | */
35 | validate: function(validator, $field, options) {
36 | var value = validator.getFieldValue($field, 'stringCase');
37 | if (value === '') {
38 | return true;
39 | }
40 |
41 | var locale = validator.getLocale(),
42 | stringCase = (options['case'] || 'lower').toLowerCase();
43 | return {
44 | valid: ('upper' === stringCase) ? value === value.toUpperCase() : value === value.toLowerCase(),
45 | message: options.message || (('upper' === stringCase) ? FormValidation.I18n[locale].stringCase.upper : FormValidation.I18n[locale].stringCase['default'])
46 | };
47 | }
48 | };
49 | }(jQuery));
50 |
--------------------------------------------------------------------------------
/test/spec/validator/isin.js:
--------------------------------------------------------------------------------
1 | describe('isin', function() {
2 | beforeEach(function() {
3 | var html = [
4 | ''
11 | ].join('\n');
12 |
13 | $(html).appendTo('body');
14 | $('#isinForm').formValidation();
15 |
16 | this.fv = $('#isinForm').data('formValidation');
17 | this.$isin = this.fv.getFieldElements('isin');
18 | });
19 |
20 | afterEach(function() {
21 | $('#isinForm').formValidation('destroy').parent().remove();
22 | });
23 |
24 | it('valid', function() {
25 | var samples = ['US0378331005', 'AU0000XVGZA3', 'GB0002634946'];
26 |
27 | for (var i in samples) {
28 | this.$isin.val(samples[i]);
29 | this.fv.validate();
30 | expect(this.fv.isValidField('isin')).toBeTruthy();
31 | }
32 | });
33 |
34 | it('invalid country code', function() {
35 | this.$isin.val('AA0000XVGZA3');
36 | this.fv.validate();
37 | expect(this.fv.isValidField('isin')).toEqual(false);
38 | });
39 |
40 | it('contains only digits and alphabet', function() {
41 | this.$isin.val('US12345ABC@#$');
42 | this.fv.validate();
43 | expect(this.fv.isValidField('isin')).toEqual(false);
44 | });
45 |
46 | it('invalid length', function() {
47 | this.$isin.val('US1234567');
48 | this.fv.validate();
49 | expect(this.fv.isValidField('isin')).toEqual(false);
50 | });
51 |
52 | it('invalid check digit', function() {
53 | this.$isin.val('US0378331004');
54 | this.fv.validate();
55 | expect(this.fv.isValidField('isin')).toEqual(false);
56 | });
57 | });
58 |
--------------------------------------------------------------------------------
/src/js/validator/numeric.js:
--------------------------------------------------------------------------------
1 | /**
2 | * numeric validator
3 | *
4 | * @link http://formvalidation.io/validators/numeric/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | numeric: {
13 | 'default': 'Please enter a valid float number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.numeric = {
19 | html5Attributes: {
20 | message: 'message',
21 | separator: 'separator'
22 | },
23 |
24 | enableByHtml5: function($field) {
25 | return ('number' === $field.attr('type')) && ($field.attr('step') !== undefined) && ($field.attr('step') % 1 !== 0);
26 | },
27 |
28 | /**
29 | * Validate decimal number
30 | *
31 | * @param {FormValidation.Base} validator The validator plugin instance
32 | * @param {jQuery} $field Field element
33 | * @param {Object} options Consist of key:
34 | * - message: The invalid message
35 | * - separator: The decimal separator. Can be "." (default), ","
36 | * @returns {Boolean}
37 | */
38 | validate: function(validator, $field, options) {
39 | if (this.enableByHtml5($field) && $field.get(0).validity && $field.get(0).validity.badInput === true) {
40 | return false;
41 | }
42 |
43 | var value = validator.getFieldValue($field, 'numeric');
44 | if (value === '') {
45 | return true;
46 | }
47 | var separator = options.separator || '.';
48 | if (separator !== '.') {
49 | value = value.replace(separator, '.');
50 | }
51 |
52 | return !isNaN(parseFloat(value)) && isFinite(value);
53 | }
54 | };
55 | }(jQuery));
56 |
--------------------------------------------------------------------------------
/test/spec/validator/ismn.js:
--------------------------------------------------------------------------------
1 | describe('ismn', function() {
2 | beforeEach(function() {
3 | var html = [
4 | ''
11 | ].join('\n');
12 |
13 | $(html).appendTo('body');
14 | $('#ismnForm').formValidation();
15 |
16 | this.fv = $('#ismnForm').data('formValidation');
17 | this.$ismn = this.fv.getFieldElements('ismn');
18 | });
19 |
20 | afterEach(function() {
21 | $('#ismnForm').formValidation('destroy').parent().remove();
22 | });
23 |
24 | it('valid start with M', function() {
25 | this.$ismn.val('M230671187');
26 | this.fv.validate();
27 | expect(this.fv.isValidField('ismn')).toBeTruthy();
28 | });
29 |
30 | it('valid start with 979', function() {
31 | this.$ismn.val('9790060115615');
32 | this.fv.validate();
33 | expect(this.fv.isValidField('ismn')).toBeTruthy();
34 | });
35 |
36 | it('valid contains spaces', function() {
37 | this.$ismn.val('979 0 3452 4680 5');
38 | this.fv.validate();
39 | expect(this.fv.isValidField('ismn')).toBeTruthy();
40 | });
41 |
42 | it('valid contains dashes', function() {
43 | this.$ismn.val('979-0-0601-1561-5');
44 | this.fv.validate();
45 | expect(this.fv.isValidField('ismn')).toBeTruthy();
46 | });
47 |
48 | it('invalid format', function() {
49 | this.$ismn.val('N123456789');
50 | this.fv.validate();
51 | expect(this.fv.isValidField('ismn')).toEqual(false);
52 | });
53 |
54 | it('invalid check digit', function() {
55 | this.$ismn.val('9790060115614');
56 | this.fv.validate();
57 | expect(this.fv.isValidField('ismn')).toEqual(false);
58 | });
59 | });
60 |
--------------------------------------------------------------------------------
/test/spec/validator/identical.js:
--------------------------------------------------------------------------------
1 | describe('identical', function() {
2 | beforeEach(function() {
3 | $([
4 | ''
15 | ].join('\n')).appendTo('body');
16 |
17 | $('#identicalForm').formValidation();
18 |
19 | this.fv = $('#identicalForm').data('formValidation');
20 | this.$a = this.fv.getFieldElements('a');
21 | this.$b = this.fv.getFieldElements('b');
22 | });
23 |
24 | afterEach(function () {
25 | $('#identicalForm').formValidation('destroy').remove();
26 | });
27 |
28 | // #1267
29 | it('compare to field which does not use any validators', function() {
30 | this.$a.val('123');
31 | this.$b.val('123abc');
32 | this.fv.validate();
33 | expect(this.fv.isValid()).toEqual(false);
34 |
35 | this.fv.resetForm();
36 | this.$a.val('123456');
37 | this.$b.val('123456');
38 | this.fv.validate();
39 | expect(this.fv.isValid()).toEqual(true);
40 | });
41 |
42 | it('compare to hidden field', function() {
43 | this.$b.attr('data-fv-identical-field', 'hiddenField');
44 |
45 | this.fv = $('#identicalForm').formValidation('destroy').formValidation().data('formValidation');
46 | this.$b.val('123abc');
47 | this.fv.validate();
48 | expect(this.fv.isValid()).toEqual(false);
49 |
50 | this.fv.resetForm();
51 | this.$b.val('abcdef');
52 | this.fv.validate();
53 | expect(this.fv.isValid()).toEqual(true);
54 | });
55 | });
--------------------------------------------------------------------------------
/src/js/validator/callback.js:
--------------------------------------------------------------------------------
1 | /**
2 | * callback validator
3 | *
4 | * @link http://formvalidation.io/validators/callback/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | callback: {
13 | 'default': 'Please enter a valid value'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.callback = {
19 | html5Attributes: {
20 | message: 'message',
21 | callback: 'callback'
22 | },
23 |
24 | /**
25 | * Return result from the callback method
26 | *
27 | * @param {FormValidation.Base} validator The validator plugin instance
28 | * @param {jQuery} $field Field element
29 | * @param {Object} options Can consist of the following keys:
30 | * - callback: The callback method that passes 2 parameters:
31 | * callback: function(fieldValue, validator, $field) {
32 | * // fieldValue is the value of field
33 | * // validator is instance of BootstrapValidator
34 | * // $field is the field element
35 | * }
36 | * - message: The invalid message
37 | * @returns {Deferred}
38 | */
39 | validate: function(validator, $field, options) {
40 | var value = validator.getFieldValue($field, 'callback'),
41 | dfd = new $.Deferred(),
42 | result = { valid: true };
43 |
44 | if (options.callback) {
45 | var response = FormValidation.Helper.call(options.callback, [value, validator, $field]);
46 | result = ('boolean' === typeof response || null === response) ? { valid: response } : response;
47 | }
48 |
49 | dfd.resolve($field, 'callback', result);
50 | return dfd;
51 | }
52 | };
53 | }(jQuery));
54 |
--------------------------------------------------------------------------------
/src/js/validator/issn.js:
--------------------------------------------------------------------------------
1 | /**
2 | * issn validator
3 | *
4 | * @link http://formvalidation.io/validators/issn/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | issn: {
13 | 'default': 'Please enter a valid ISSN number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.issn = {
19 | /**
20 | * Validate ISSN (International Standard Serial Number)
21 | * Examples:
22 | * - Valid: 0378-5955, 0024-9319, 0032-1478
23 | * - Invalid: 0032-147X
24 | *
25 | * @see http://en.wikipedia.org/wiki/International_Standard_Serial_Number
26 | * @param {FormValidation.Base} validator The validator plugin instance
27 | * @param {jQuery} $field Field element
28 | * @param {Object} options Can consist of the following keys:
29 | * - message: The invalid message
30 | * @returns {Boolean}
31 | */
32 | validate: function(validator, $field, options) {
33 | var value = validator.getFieldValue($field, 'issn');
34 | if (value === '') {
35 | return true;
36 | }
37 |
38 | // Groups are separated by a hyphen or a space
39 | if (!/^\d{4}\-\d{3}[\dX]$/.test(value)) {
40 | return false;
41 | }
42 |
43 | // Replace all special characters except digits and X
44 | value = value.replace(/[^0-9X]/gi, '');
45 | var chars = value.split(''),
46 | length = chars.length,
47 | sum = 0;
48 |
49 | if (chars[7] === 'X') {
50 | chars[7] = 10;
51 | }
52 | for (var i = 0; i < length; i++) {
53 | sum += parseInt(chars[i], 10) * (8 - i);
54 | }
55 | return (sum % 11 === 0);
56 | }
57 | };
58 | }(jQuery));
59 |
--------------------------------------------------------------------------------
/src/js/validator/imo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * imo validator
3 | *
4 | * @link http://formvalidation.io/validators/imo/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | imo: {
13 | 'default': 'Please enter a valid IMO number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.imo = {
19 | /**
20 | * Validate IMO (International Maritime Organization)
21 | * Examples:
22 | * - Valid: IMO 8814275, IMO 9176187
23 | * - Invalid: IMO 8814274
24 | *
25 | * @see http://en.wikipedia.org/wiki/IMO_Number
26 | * @param {FormValidation.Base} validator The validator plugin instance
27 | * @param {jQuery} $field Field element
28 | * @param {Object} options Can consist of the following keys:
29 | * - message: The invalid message
30 | * @returns {Boolean}
31 | */
32 | validate: function(validator, $field, options) {
33 | var value = validator.getFieldValue($field, 'imo');
34 | if (value === '') {
35 | return true;
36 | }
37 |
38 | if (!/^IMO \d{7}$/i.test(value)) {
39 | return false;
40 | }
41 |
42 | // Grab just the digits
43 | var sum = 0,
44 | digits = value.replace(/^.*(\d{7})$/, '$1');
45 |
46 | // Go over each char, multiplying by the inverse of it's position
47 | // IMO 9176187
48 | // (9 * 7) + (1 * 6) + (7 * 5) + (6 * 4) + (1 * 3) + (8 * 2) = 147
49 | // Take the last digit of that, that's the check digit (7)
50 | for (var i = 6; i >= 1; i--) {
51 | sum += (digits.slice((6 - i), -i) * (i + 1));
52 | }
53 |
54 | return sum % 10 === parseInt(digits.charAt(6), 10);
55 | }
56 | };
57 | }(jQuery));
58 |
--------------------------------------------------------------------------------
/dist/js/framework/foundation.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * FormValidation (http://formvalidation.io)
3 | * The best jQuery plugin to validate form fields. Support Bootstrap, Foundation, Pure, SemanticUI, UIKit and custom frameworks
4 | *
5 | * @version v0.6.2-dev, built on 2015-03-13 8:15:46 AM
6 | * @author https://twitter.com/nghuuphuoc
7 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
8 | * @license http://formvalidation.io/license/
9 | */
10 | !function(a){FormValidation.Framework.Foundation=function(b,c){c=a.extend(!0,{button:{selector:'[type="submit"]',disabled:"disabled"},err:{clazz:"error",parent:"^.*((small|medium|large)-[0-9]+)\\s.*(columns).*$"},icon:{valid:null,invalid:null,validating:null,feedback:"fv-control-feedback"},row:{selector:".row",valid:"fv-has-success",invalid:"error",feedback:"fv-has-feedback"}},c),FormValidation.Base.apply(this,[b,c])},FormValidation.Framework.Foundation.prototype=a.extend({},FormValidation.Base.prototype,{_fixIcon:function(a,b){var c=this._namespace,d=a.attr("type"),e=a.attr("data-"+c+"-field"),f=this.options.fields[e].row||this.options.row.selector,g=a.closest(f);if("checkbox"===d||"radio"===d){var h=b.next();h.is("label")&&b.insertAfter(h)}0===g.find("label").length&&b.addClass("fv-icon-no-label")},_createTooltip:function(a,b,c){var d=this,e=a.data("fv.icon");e&&(e.attr("title",b).css({cursor:"pointer"}).off("mouseenter.container.fv focusin.container.fv").on("mouseenter.container.fv",function(){d._showTooltip(a,c)}).off("mouseleave.container.fv focusout.container.fv").on("mouseleave.container.fv focusout.container.fv",function(){d._hideTooltip(a,c)}),Foundation.libs.tooltip.create(e),e.data("fv.foundation.tooltip",e))},_destroyTooltip:function(a){var b=a.data("fv.icon");if(b){b.css({cursor:""});var c=b.data("fv.foundation.tooltip");c&&(c.off(".fndtn.tooltip"),Foundation.libs.tooltip.hide(c),b.removeData("fv.foundation.tooltip"))}},_hideTooltip:function(a){var b=a.data("fv.icon");if(b){b.css({cursor:""});var c=b.data("fv.foundation.tooltip");c&&Foundation.libs.tooltip.hide(c)}},_showTooltip:function(a){var b=a.data("fv.icon");if(b){var c=b.data("fv.foundation.tooltip");c&&(b.css({cursor:"pointer"}),Foundation.libs.tooltip.show(c))}}})}(jQuery);
--------------------------------------------------------------------------------
/src/js/validator/imei.js:
--------------------------------------------------------------------------------
1 | /**
2 | * imei validator
3 | *
4 | * @link http://formvalidation.io/validators/imei/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | imei: {
13 | 'default': 'Please enter a valid IMEI number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.imei = {
19 | /**
20 | * Validate IMEI (International Mobile Station Equipment Identity)
21 | * Examples:
22 | * - Valid: 35-209900-176148-1, 35-209900-176148-23, 3568680000414120, 490154203237518
23 | * - Invalid: 490154203237517
24 | *
25 | * @see http://en.wikipedia.org/wiki/International_Mobile_Station_Equipment_Identity
26 | * @param {FormValidation.Base} validator The validator plugin instance
27 | * @param {jQuery} $field Field element
28 | * @param {Object} options Can consist of the following keys:
29 | * - message: The invalid message
30 | * @returns {Boolean}
31 | */
32 | validate: function(validator, $field, options) {
33 | var value = validator.getFieldValue($field, 'imei');
34 | if (value === '') {
35 | return true;
36 | }
37 |
38 | switch (true) {
39 | case /^\d{15}$/.test(value):
40 | case /^\d{2}-\d{6}-\d{6}-\d{1}$/.test(value):
41 | case /^\d{2}\s\d{6}\s\d{6}\s\d{1}$/.test(value):
42 | value = value.replace(/[^0-9]/g, '');
43 | return FormValidation.Helper.luhn(value);
44 |
45 | case /^\d{14}$/.test(value):
46 | case /^\d{16}$/.test(value):
47 | case /^\d{2}-\d{6}-\d{6}(|-\d{2})$/.test(value):
48 | case /^\d{2}\s\d{6}\s\d{6}(|\s\d{2})$/.test(value):
49 | return true;
50 |
51 | default:
52 | return false;
53 | }
54 | }
55 | };
56 | }(jQuery));
57 |
--------------------------------------------------------------------------------
/test/spec/validator/ein.js:
--------------------------------------------------------------------------------
1 | describe('ein', function() {
2 | beforeEach(function() {
3 | $([
4 | ''
9 | ].join('\n')).appendTo('body');
10 | $('#einForm').formValidation();
11 |
12 | this.fv = $('#einForm').data('formValidation');
13 | this.$ein = this.fv.getFieldElements('ein');
14 | });
15 |
16 | afterEach(function() {
17 | $('#einForm').formValidation('destroy').remove();
18 | });
19 |
20 | it('valid', function() {
21 | var samples = ['01-1234567', '91-1144442', '011234567'];
22 |
23 | for (var i in samples) {
24 | this.fv.resetForm();
25 | this.$ein.val(samples[i]);
26 | this.fv.validate();
27 | expect(this.fv.isValid()).toBeTruthy();
28 | }
29 | });
30 |
31 | it('invalid format', function() {
32 | var samples = ['123-45-6789'];
33 |
34 | for (var i in samples) {
35 | this.fv.resetForm();
36 | this.$ein.val(samples[i]);
37 | this.fv.validate();
38 | expect(this.fv.isValid()).toEqual(false);
39 | }
40 | });
41 |
42 | it('invalid campus', function() {
43 | var samples = ['00-1234567', '07-1144442', '49-1234567'];
44 |
45 | for (var i in samples) {
46 | this.fv.resetForm();
47 | this.$ein.val(samples[i]);
48 | this.fv.validate();
49 | expect(this.fv.isValid()).toEqual(false);
50 | }
51 | });
52 |
53 | it('campus', function() {
54 | $('#einForm').on('success.field.fv', function(e, data) {
55 | expect(data.result.campus).toEqual(data.element.attr('data-campus'));
56 | });
57 |
58 | var samples = {
59 | AUSTIN: '50-1234567',
60 | BROOKHAVEN: '04-2103594',
61 | SMALL_BUSINESS_ADMINISTRATION: '31-1234567'
62 | };
63 |
64 | for (var i in samples) {
65 | this.fv.resetForm();
66 | this.$ein.val(samples[i]).attr('data-campus', i);
67 | this.fv.validate();
68 | }
69 | });
70 | });
71 |
--------------------------------------------------------------------------------
/src/js/validator/vin.js:
--------------------------------------------------------------------------------
1 | /**
2 | * vin validator
3 | *
4 | * @link http://formvalidation.io/validators/vin/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | vin: {
13 | 'default': 'Please enter a valid VIN number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.vin = {
19 | /**
20 | * Validate an US VIN (Vehicle Identification Number)
21 | *
22 | * @param {FormValidation.Base} validator The validator plugin instance
23 | * @param {jQuery} $field Field element
24 | * @param {Object} options Consist of key:
25 | * - message: The invalid message
26 | * @returns {Boolean}
27 | */
28 | validate: function(validator, $field, options) {
29 | var value = validator.getFieldValue($field, 'vin');
30 | if (value === '') {
31 | return true;
32 | }
33 |
34 | // Don't accept I, O, Q characters
35 | if (!/^[a-hj-npr-z0-9]{8}[0-9xX][a-hj-npr-z0-9]{8}$/i.test(value)) {
36 | return false;
37 | }
38 |
39 | value = value.toUpperCase();
40 | var chars = {
41 | A: 1, B: 2, C: 3, D: 4, E: 5, F: 6, G: 7, H: 8,
42 | J: 1, K: 2, L: 3, M: 4, N: 5, P: 7, R: 9,
43 | S: 2, T: 3, U: 4, V: 5, W: 6, X: 7, Y: 8, Z: 9,
44 | '1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7, '8': 8, '9': 9, '0': 0
45 | },
46 | weights = [8, 7, 6, 5, 4, 3, 2, 10, 0, 9, 8, 7, 6, 5, 4, 3, 2],
47 | sum = 0,
48 | length = value.length;
49 | for (var i = 0; i < length; i++) {
50 | sum += chars[value.charAt(i) + ''] * weights[i];
51 | }
52 |
53 | var reminder = sum % 11;
54 | if (reminder === 10) {
55 | reminder = 'X';
56 | }
57 |
58 | return (reminder + '') === value.charAt(8);
59 | }
60 | };
61 | }(jQuery));
62 |
--------------------------------------------------------------------------------
/test/spec/validator/isbn.js:
--------------------------------------------------------------------------------
1 | describe('isbn', function() {
2 | beforeEach(function() {
3 | var html = [
4 | ''
11 | ].join('\n');
12 |
13 | $(html).appendTo('body');
14 | $('#isbnForm').formValidation();
15 |
16 | this.fv = $('#isbnForm').data('formValidation');
17 | this.$isbn = this.fv.getFieldElements('isbn');
18 | });
19 |
20 | afterEach(function() {
21 | $('#isbnForm').formValidation('destroy').parent().remove();
22 | });
23 |
24 | it('isbn10 hyphen', function() {
25 | var samples = ['99921-58-10-7', '9971-5-0210-0', '960-425-059-0', '80-902734-1-6'];
26 |
27 | for (var i in samples) {
28 | this.$isbn.val(samples[i]);
29 | this.fv.validate();
30 | expect(this.fv.isValidField('isbn')).toBeTruthy();
31 | }
32 | });
33 |
34 | it('isbn10 space', function() {
35 | var samples = ['85 359 0277 5', '1 84356 028 3', '0 684 84328 5', '0 85131 041 9', '0 943396 04 2'];
36 |
37 | for (var i in samples) {
38 | this.$isbn.val(samples[i]);
39 | this.fv.validate();
40 | expect(this.fv.isValidField('isbn')).toBeTruthy();
41 | }
42 | });
43 |
44 | it('isbn10 hyphen with X', function() {
45 | var samples = ['0-8044-2957-X', '0-9752298-0-X'];
46 | for (var i in samples) {
47 | this.$isbn.val(samples[i]);
48 | this.fv.validate();
49 | expect(this.fv.isValidField('isbn')).toBeTruthy();
50 | }
51 | });
52 |
53 | it('isbn10 invalid check digit', function() {
54 | this.$isbn.val('99921-58-10-6');
55 | this.fv.validate();
56 | expect(this.fv.isValidField('isbn')).toEqual(false);
57 | });
58 |
59 | it('isbn13', function() {
60 | this.$isbn.val('978-0-306-40615-7');
61 | this.fv.validate();
62 | expect(this.fv.isValidField('isbn')).toBeTruthy();
63 | });
64 |
65 | it('isbn13 invalid check digit', function() {
66 | this.$isbn.val('978-0-306-40615-6');
67 | this.fv.validate();
68 | expect(this.fv.isValidField('isbn')).toEqual(false);
69 | });
70 | });
71 |
--------------------------------------------------------------------------------
/src/js/framework/pure.js:
--------------------------------------------------------------------------------
1 | /**
2 | * FormValidation (http://formvalidation.io)
3 | * The best jQuery plugin to validate form fields. Support Bootstrap, Foundation, Pure, SemanticUI, UIKit and custom frameworks
4 | *
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 |
10 | /**
11 | * This class supports validating Pure framework (http://purecss.io/)
12 | */
13 | (function($) {
14 | FormValidation.Framework.Pure = function(element, options) {
15 | options = $.extend(true, {
16 | button: {
17 | selector: '[type="submit"]',
18 | // The class of disabled button
19 | // http://purecss.io/buttons/#disabled-buttons
20 | disabled: 'pure-button-disabled'
21 | },
22 | err: {
23 | clazz: 'fv-help-block',
24 | parent: '^.*pure-control-group.*$'
25 | },
26 | // Pure doesn't support feedback icon
27 | icon: {
28 | valid: null,
29 | invalid: null,
30 | validating: null,
31 | feedback: 'fv-control-feedback'
32 | },
33 | row: {
34 | // http://purecss.io/forms/#aligned-form
35 | selector: '.pure-control-group',
36 | valid: 'fv-has-success',
37 | invalid: 'fv-has-error',
38 | feedback: 'fv-has-feedback'
39 | }
40 | }, options);
41 |
42 | FormValidation.Base.apply(this, [element, options]);
43 | };
44 |
45 | FormValidation.Framework.Pure.prototype = $.extend({}, FormValidation.Base.prototype, {
46 | /**
47 | * Specific framework might need to adjust the icon position
48 | *
49 | * @param {jQuery} $field The field element
50 | * @param {jQuery} $icon The icon element
51 | */
52 | _fixIcon: function($field, $icon) {
53 | var ns = this._namespace,
54 | type = $field.attr('type'),
55 | field = $field.attr('data-' + ns + '-field'),
56 | row = this.options.fields[field].row || this.options.row.selector,
57 | $parent = $field.closest(row);
58 |
59 | if ($parent.find('label').length === 0) {
60 | $icon.addClass('fv-icon-no-label');
61 | }
62 | }
63 | });
64 | }(jQuery));
65 |
--------------------------------------------------------------------------------
/dist/js/framework/pure.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * FormValidation (http://formvalidation.io)
3 | * The best jQuery plugin to validate form fields. Support Bootstrap, Foundation, Pure, SemanticUI, UIKit and custom frameworks
4 | *
5 | * @version v0.6.2-dev, built on 2015-03-13 8:15:45 AM
6 | * @author https://twitter.com/nghuuphuoc
7 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
8 | * @license http://formvalidation.io/license/
9 | */
10 | /**
11 | * This class supports validating Pure framework (http://purecss.io/)
12 | */
13 | (function($) {
14 | FormValidation.Framework.Pure = function(element, options) {
15 | options = $.extend(true, {
16 | button: {
17 | selector: '[type="submit"]',
18 | // The class of disabled button
19 | // http://purecss.io/buttons/#disabled-buttons
20 | disabled: 'pure-button-disabled'
21 | },
22 | err: {
23 | clazz: 'fv-help-block',
24 | parent: '^.*pure-control-group.*$'
25 | },
26 | // Pure doesn't support feedback icon
27 | icon: {
28 | valid: null,
29 | invalid: null,
30 | validating: null,
31 | feedback: 'fv-control-feedback'
32 | },
33 | row: {
34 | // http://purecss.io/forms/#aligned-form
35 | selector: '.pure-control-group',
36 | valid: 'fv-has-success',
37 | invalid: 'fv-has-error',
38 | feedback: 'fv-has-feedback'
39 | }
40 | }, options);
41 |
42 | FormValidation.Base.apply(this, [element, options]);
43 | };
44 |
45 | FormValidation.Framework.Pure.prototype = $.extend({}, FormValidation.Base.prototype, {
46 | /**
47 | * Specific framework might need to adjust the icon position
48 | *
49 | * @param {jQuery} $field The field element
50 | * @param {jQuery} $icon The icon element
51 | */
52 | _fixIcon: function($field, $icon) {
53 | var ns = this._namespace,
54 | type = $field.attr('type'),
55 | field = $field.attr('data-' + ns + '-field'),
56 | row = this.options.fields[field].row || this.options.row.selector,
57 | $parent = $field.closest(row);
58 |
59 | if ($parent.find('label').length === 0) {
60 | $icon.addClass('fv-icon-no-label');
61 | }
62 | }
63 | });
64 | }(jQuery));
65 |
--------------------------------------------------------------------------------
/src/js/validator/cusip.js:
--------------------------------------------------------------------------------
1 | /**
2 | * cusip validator
3 | *
4 | * @link http://formvalidation.io/validators/cusip/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | cusip: {
13 | 'default': 'Please enter a valid CUSIP number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.cusip = {
19 | /**
20 | * Validate a CUSIP number
21 | * Examples:
22 | * - Valid: 037833100, 931142103, 14149YAR8, 126650BG6
23 | * - Invalid: 31430F200, 022615AC2
24 | *
25 | * @see http://en.wikipedia.org/wiki/CUSIP
26 | * @param {FormValidation.Base} validator The validator plugin instance
27 | * @param {jQuery} $field Field element
28 | * @param {Object} [options] Can consist of the following keys:
29 | * - message: The invalid message
30 | * @returns {Boolean}
31 | */
32 | validate: function(validator, $field, options) {
33 | var value = validator.getFieldValue($field, 'cusip');
34 | if (value === '') {
35 | return true;
36 | }
37 |
38 | value = value.toUpperCase();
39 | if (!/^[0-9A-Z]{9}$/.test(value)) {
40 | return false;
41 | }
42 |
43 | var converted = $.map(value.split(''), function(item) {
44 | var code = item.charCodeAt(0);
45 | return (code >= 'A'.charCodeAt(0) && code <= 'Z'.charCodeAt(0))
46 | // Replace A, B, C, ..., Z with 10, 11, ..., 35
47 | ? (code - 'A'.charCodeAt(0) + 10)
48 | : item;
49 | }),
50 | length = converted.length,
51 | sum = 0;
52 | for (var i = 0; i < length - 1; i++) {
53 | var num = parseInt(converted[i], 10);
54 | if (i % 2 !== 0) {
55 | num *= 2;
56 | }
57 | if (num > 9) {
58 | num -= 9;
59 | }
60 | sum += num;
61 | }
62 |
63 | sum = (10 - (sum % 10)) % 10;
64 | return sum === parseInt(converted[length - 1], 10);
65 | }
66 | };
67 | }(jQuery));
68 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # FormValidation - [v0.6.1](http://formvalidation.io/download/)
2 |
3 | [http://formvalidation.io](http://formvalidation.io) - The best [jQuery](http://jquery.com/) plugin to validate form fields, designed to use with:
4 |
5 | - [x] [Bootstrap](http://getbootstrap.com/)
6 | - [x] [Foundation](http://foundation.zurb.com/)
7 | - [x] [Pure](http://purecss.io/)
8 | - [x] [Semantic UI](http://semantic-ui.com/)
9 | - [x] [UIKit](http://getuikit.com/)
10 |
11 | It's developed from scratch by [@nghuuphuoc](http://twitter.com/nghuuphuoc).
12 |
13 | __Required__: [jQuery 1.9.1+](http://jquery.com/)
14 |
15 | Screenshots first because we love it!
16 |
17 | __Validating Bootstrap form__
18 |
19 | 
20 |
21 | __Validating Foundation form__
22 |
23 | 
24 |
25 | __Validating Pure form__
26 |
27 | 
28 |
29 | __Validating Semantic UI form__
30 |
31 | 
32 |
33 | __Validating UI Kit form__
34 |
35 | 
36 |
37 | ## Live demo
38 |
39 | http://formvalidation.io/examples/
40 |
41 | There are also many examples located in the [demo](demo) directory.
42 |
43 | You also can run the ```demo``` locally by:
44 |
45 | * Clone the repo:
46 |
47 | ```
48 | git clone https://github.com/formvalidation/formvalidation.git
49 | ```
50 |
51 | * Go to the cloned directory and run the command:
52 |
53 | ```
54 | python -m SimpleHTTPServer 8000
55 | ```
56 |
57 | * Access the demo at
58 |
59 | ```
60 | http://localhost:8000/demo/the_demo_file_here.html
61 | ```
62 |
63 | ## Features
64 |
65 | See the [official website](http://formvalidation.io) for the full list of features
66 |
67 | ## Download
68 |
69 | * Latest version: [v0.6.1](http://formvalidation.io/download/), released on 2015-02-24
70 | * For older versions, look at the [Releases](https://github.com/formvalidation/formvalidation/releases) page
71 | * Release History: Look at the [Change Log](CHANGELOG.md)
72 |
73 | ## Documentation
74 |
75 | * [Official website](http://formvalidation.io)
76 |
77 | ## Author
78 |
79 | The __FormValidation__ plugin is written by Nguyen Huu Phuoc, aka @nghuuphuoc
80 |
81 | * [http://twitter.com/nghuuphuoc](http://twitter.com/nghuuphuoc)
82 | * [http://github.com/nghuuphuoc](http://github.com/nghuuphuoc)
83 |
84 | ## Contribution
85 |
86 | Contributions are welcome!
87 |
88 | Please notice that **your code** may be used as part of a **commercial product** if the pull request is **merged**.
89 |
90 | ## License
91 |
92 | For more information about the license, see http://formvalidation.io/license/
--------------------------------------------------------------------------------
/src/js/validator/uuid.js:
--------------------------------------------------------------------------------
1 | /**
2 | * uuid validator
3 | *
4 | * @link http://formvalidation.io/validators/uuid/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | uuid: {
13 | 'default': 'Please enter a valid UUID number',
14 | version: 'Please enter a valid UUID version %s number'
15 | }
16 | }
17 | });
18 |
19 | FormValidation.Validator.uuid = {
20 | html5Attributes: {
21 | message: 'message',
22 | version: 'version'
23 | },
24 |
25 | /**
26 | * Return true if and only if the input value is a valid UUID string
27 | *
28 | * @see http://en.wikipedia.org/wiki/Universally_unique_identifier
29 | * @param {FormValidation.Base} validator The validator plugin instance
30 | * @param {jQuery} $field Field element
31 | * @param {Object} options Consist of key:
32 | * - message: The invalid message
33 | * - version: Can be 3, 4, 5, null
34 | * @returns {Boolean|Object}
35 | */
36 | validate: function(validator, $field, options) {
37 | var value = validator.getFieldValue($field, 'uuid');
38 | if (value === '') {
39 | return true;
40 | }
41 |
42 | // See the format at http://en.wikipedia.org/wiki/Universally_unique_identifier#Variants_and_versions
43 | var locale = validator.getLocale(),
44 | patterns = {
45 | '3': /^[0-9A-F]{8}-[0-9A-F]{4}-3[0-9A-F]{3}-[0-9A-F]{4}-[0-9A-F]{12}$/i,
46 | '4': /^[0-9A-F]{8}-[0-9A-F]{4}-4[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
47 | '5': /^[0-9A-F]{8}-[0-9A-F]{4}-5[0-9A-F]{3}-[89AB][0-9A-F]{3}-[0-9A-F]{12}$/i,
48 | all: /^[0-9A-F]{8}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{4}-[0-9A-F]{12}$/i
49 | },
50 | version = options.version ? (options.version + '') : 'all';
51 | return {
52 | valid: (null === patterns[version]) ? true : patterns[version].test(value),
53 | message: options.version
54 | ? FormValidation.Helper.format(options.message || FormValidation.I18n[locale].uuid.version, options.version)
55 | : (options.message || FormValidation.I18n[locale].uuid['default'])
56 | };
57 | }
58 | };
59 | }(jQuery));
60 |
--------------------------------------------------------------------------------
/src/js/validator/ismn.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ismn validator
3 | *
4 | * @link http://formvalidation.io/validators/ismn/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | ismn: {
13 | 'default': 'Please enter a valid ISMN number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.ismn = {
19 | /**
20 | * Validate ISMN (International Standard Music Number)
21 | * Examples:
22 | * - Valid: M230671187, 979-0-0601-1561-5, 979 0 3452 4680 5, 9790060115615
23 | * - Invalid: 9790060115614
24 | *
25 | * @see http://en.wikipedia.org/wiki/International_Standard_Music_Number
26 | * @param {FormValidation.Base} validator The validator plugin instance
27 | * @param {jQuery} $field Field element
28 | * @param {Object} options Can consist of the following keys:
29 | * - message: The invalid message
30 | * @returns {Boolean}
31 | */
32 | validate: function(validator, $field, options) {
33 | var value = validator.getFieldValue($field, 'ismn');
34 | if (value === '') {
35 | return true;
36 | }
37 |
38 | // Groups are separated by a hyphen or a space
39 | var type;
40 | switch (true) {
41 | case /^M\d{9}$/.test(value):
42 | case /^M-\d{4}-\d{4}-\d{1}$/.test(value):
43 | case /^M\s\d{4}\s\d{4}\s\d{1}$/.test(value):
44 | type = 'ISMN10';
45 | break;
46 | case /^9790\d{9}$/.test(value):
47 | case /^979-0-\d{4}-\d{4}-\d{1}$/.test(value):
48 | case /^979\s0\s\d{4}\s\d{4}\s\d{1}$/.test(value):
49 | type = 'ISMN13';
50 | break;
51 | default:
52 | return false;
53 | }
54 |
55 | if ('ISMN10' === type) {
56 | value = '9790' + value.substr(1);
57 | }
58 |
59 | // Replace all special characters except digits
60 | value = value.replace(/[^0-9]/gi, '');
61 | var length = value.length,
62 | sum = 0,
63 | weight = [1, 3];
64 | for (var i = 0; i < length - 1; i++) {
65 | sum += parseInt(value.charAt(i), 10) * weight[i % 2];
66 | }
67 | sum = 10 - sum % 10;
68 | return (sum + '' === value.charAt(length - 1));
69 | }
70 | };
71 | }(jQuery));
72 |
--------------------------------------------------------------------------------
/test/spec/validator/callback.js:
--------------------------------------------------------------------------------
1 | function validateCaptcha(value, validator, $field) {
2 | var items = $('#captchaOperation').html().split(' '), sum = parseInt(items[0]) + parseInt(items[2]);
3 | return value === sum + '';
4 | };
5 |
6 | describe('callback', function() {
7 | beforeEach(function() {
8 | $([
9 | ''
22 | ].join('\n')).appendTo('body');
23 |
24 | $('#callbackForm').formValidation({
25 | fields: {
26 | captcha: {
27 | validators: {
28 | callback: {
29 | message: 'Wrong answer',
30 | callback: function(value, validator, $field) {
31 | return validateCaptcha(value, validator, $field);
32 | }
33 | }
34 | }
35 | }
36 | }
37 | });
38 |
39 | this.fv = $('#callbackForm').data('formValidation');
40 | this.$captcha = this.fv.getFieldElements('captcha');
41 | this.$declarativeCaptcha = this.fv.getFieldElements('declarativeCaptcha');
42 | });
43 |
44 | afterEach(function() {
45 | $('#callbackForm').formValidation('destroy').remove();
46 | });
47 |
48 | it('execute the callback', function() {
49 | $('#captchaOperation').html('1 + 2');
50 |
51 | this.$captcha.val('3');
52 | this.fv.validate();
53 | expect(this.fv.isValidField('captcha')).toBeTruthy();
54 |
55 | this.fv.resetForm();
56 | this.$captcha.val('5');
57 | this.fv.validate();
58 | expect(this.fv.isValidField('captcha')).toEqual(false);
59 | });
60 |
61 | it('callback declarative', function() {
62 | $('#captchaOperation').html('10 + 20');
63 |
64 | this.$declarativeCaptcha.val('40');
65 | this.fv.validate();
66 | expect(this.fv.isValidField('declarativeCaptcha')).toEqual(false);
67 |
68 | this.fv.resetForm();
69 | this.$declarativeCaptcha.val('30');
70 | this.fv.validate();
71 | expect(this.fv.isValidField('declarativeCaptcha')).toBeTruthy();
72 | });
73 | });
74 |
--------------------------------------------------------------------------------
/src/js/validator/ein.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ein validator
3 | *
4 | * @link http://formvalidation.io/validators/ein/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | ein: {
13 | 'default': 'Please enter a valid EIN number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.ein = {
19 | // The first two digits are called campus
20 | // See http://en.wikipedia.org/wiki/Employer_Identification_Number
21 | // http://www.irs.gov/Businesses/Small-Businesses-&-Self-Employed/How-EINs-are-Assigned-and-Valid-EIN-Prefixes
22 | CAMPUS: {
23 | ANDOVER: ['10', '12'],
24 | ATLANTA: ['60', '67'],
25 | AUSTIN: ['50', '53'],
26 | BROOKHAVEN: ['01', '02', '03', '04', '05', '06', '11', '13', '14', '16', '21', '22', '23', '25', '34', '51', '52', '54', '55', '56', '57', '58', '59', '65'],
27 | CINCINNATI: ['30', '32', '35', '36', '37', '38', '61'],
28 | FRESNO: ['15', '24'],
29 | KANSAS_CITY: ['40', '44'],
30 | MEMPHIS: ['94', '95'],
31 | OGDEN: ['80', '90'],
32 | PHILADELPHIA: ['33', '39', '41', '42', '43', '46', '48', '62', '63', '64', '66', '68', '71', '72', '73', '74', '75', '76', '77', '81', '82', '83', '84', '85', '86', '87', '88', '91', '92', '93', '98', '99'],
33 | INTERNET: ['20', '26', '27', '45', '46'],
34 | SMALL_BUSINESS_ADMINISTRATION: ['31']
35 | },
36 |
37 | /**
38 | * Validate EIN (Employer Identification Number) which is also known as
39 | * Federal Employer Identification Number (FEIN) or Federal Tax Identification Number
40 | *
41 | * @param {FormValidation.Base} validator The validator plugin instance
42 | * @param {jQuery} $field Field element
43 | * @param {Object} options Can consist of the following keys:
44 | * - message: The invalid message
45 | * @returns {Object|Boolean}
46 | */
47 | validate: function(validator, $field, options) {
48 | var value = validator.getFieldValue($field, 'ein');
49 | if (value === '') {
50 | return true;
51 | }
52 |
53 | if (!/^[0-9]{2}-?[0-9]{7}$/.test(value)) {
54 | return false;
55 | }
56 | // Check the first two digits
57 | var campus = value.substr(0, 2) + '';
58 | for (var key in this.CAMPUS) {
59 | if ($.inArray(campus, this.CAMPUS[key]) !== -1) {
60 | return {
61 | valid: true,
62 | campus: key
63 | };
64 | }
65 | }
66 |
67 | return false;
68 | }
69 | };
70 | }(jQuery));
71 |
--------------------------------------------------------------------------------
/src/js/validator/step.js:
--------------------------------------------------------------------------------
1 | /**
2 | * step validator
3 | *
4 | * @link http://formvalidation.io/validators/step/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | step: {
13 | 'default': 'Please enter a valid step of %s'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.step = {
19 | html5Attributes: {
20 | message: 'message',
21 | base: 'baseValue',
22 | step: 'step'
23 | },
24 |
25 | /**
26 | * Return true if the input value is valid step one
27 | *
28 | * @param {FormValidation.Base} validator The validator plugin instance
29 | * @param {jQuery} $field Field element
30 | * @param {Object} options Can consist of the following keys:
31 | * - baseValue: The base value
32 | * - step: The step
33 | * - message: The invalid message
34 | * @returns {Boolean|Object}
35 | */
36 | validate: function(validator, $field, options) {
37 | var value = validator.getFieldValue($field, 'step');
38 | if (value === '') {
39 | return true;
40 | }
41 |
42 | options = $.extend({}, { baseValue: 0, step: 1 }, options);
43 | value = parseFloat(value);
44 | if (!$.isNumeric(value)) {
45 | return false;
46 | }
47 |
48 | var round = function(x, precision) {
49 | var m = Math.pow(10, precision);
50 | x = x * m;
51 | var sign = (x > 0) | -(x < 0),
52 | isHalf = (x % 1 === 0.5 * sign);
53 | if (isHalf) {
54 | return (Math.floor(x) + (sign > 0)) / m;
55 | } else {
56 | return Math.round(x) / m;
57 | }
58 | },
59 | floatMod = function(x, y) {
60 | if (y === 0.0) {
61 | return 1.0;
62 | }
63 | var dotX = (x + '').split('.'),
64 | dotY = (y + '').split('.'),
65 | precision = ((dotX.length === 1) ? 0 : dotX[1].length) + ((dotY.length === 1) ? 0 : dotY[1].length);
66 | return round(x - y * Math.floor(x / y), precision);
67 | };
68 |
69 | var locale = validator.getLocale(),
70 | mod = floatMod(value - options.baseValue, options.step);
71 | return {
72 | valid: mod === 0.0 || mod === options.step,
73 | message: FormValidation.Helper.format(options.message || FormValidation.I18n[locale].step['default'], [options.step])
74 | };
75 | }
76 | };
77 | }(jQuery));
78 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 | FormValidation License
2 | ---
3 |
4 | For more information about the license, see http://formvalidation.io/license/
5 |
6 | ## FormValidation commercial license agreement
7 |
8 | This Commercial License Agreement is a binding legal agreement between you and Nguyen Huu Phuoc.
9 | By installing, copying, or using FormValidation (the Software), you agree to be bound
10 | by these terms of this Agreement.
11 |
12 | ### Grant of license
13 |
14 | Subject to the payment of the fee required and the conditions herein, you are hereby granted
15 | a non-exclusive, non-transferable right to use FormValidation (the Software) to design
16 | and develop commercial applications (Applications).
17 |
18 | ### Developer grant
19 |
20 | The FormValidation Commercial Developer License grants one license for you as one designated
21 | user (Developer) to use the Software for developing Applications. A Developer is an individual
22 | who implements the Software into Applications, most often writing the necessary code to do so.
23 | You must purchase another separate license to the Software for each and any additional Developer,
24 | or purchase a FormValidation Commercial Organization License to cover your entire organization.
25 |
26 | ### Organization grant
27 |
28 | The FormValidation Commercial Organization License grants one license for your Organization
29 | as one designated, collective user (Organization) to use the Software for developing Applications.
30 | There is no limit or restriction of the number of Developers within your Organization who
31 | may develop Applications using the Software.
32 |
33 | ### Usage
34 |
35 | You are granted the right to use and to modify the source code of the Software for use in
36 | Applications. There is no limit or restriction of the number of Applications which use the
37 | Software. You own any original work authored by you. Nguyen Huu Phuoc continues to retain
38 | all copyright and other intellectual property rights in the Software. You are not permitted
39 | to move, remove, edit, or obscure any copyright, trademark, attribution, warning or disclaimer
40 | notices in the Software.
41 |
42 | You may use the Software only to create Applications that are significantly different than
43 | and do not compete with the Software. You are granted the license to distribute the Software
44 | as part of your Applications on a royalty-free basis. Users of your Applications are permitted
45 | to use the Software or your modifications of the Software as part of your Applications.
46 | Users do not need to purchase their own commercial license for the Software, so long as they
47 | are not acting as Developers, developing their own commercial Applications with the Software.
48 |
49 | ### Warranties and remedies
50 |
51 | The Software is provided "as is", without warranty of any kind, express or implied, including
52 | but not limited to the warranties of merchantability, fitness for a particular purpose and
53 | non-infringement. Nguyen Huu Phuoc's entire liability and your exclusive remedy under this
54 | agreement shall be return of the price paid for the Software.
--------------------------------------------------------------------------------
/dist/js/framework/bootstrap.min.js:
--------------------------------------------------------------------------------
1 | /*!
2 | * FormValidation (http://formvalidation.io)
3 | * The best jQuery plugin to validate form fields. Support Bootstrap, Foundation, Pure, SemanticUI, UIKit and custom frameworks
4 | *
5 | * @version v0.6.2-dev, built on 2015-03-13 8:15:46 AM
6 | * @author https://twitter.com/nghuuphuoc
7 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
8 | * @license http://formvalidation.io/license/
9 | */
10 | !function(a){FormValidation.Framework.Bootstrap=function(b,c,d){c=a.extend(!0,{button:{selector:'[type="submit"]',disabled:"disabled"},err:{clazz:"help-block",parent:"^(.*)col-(xs|sm|md|lg)-(offset-){0,1}[0-9]+(.*)$"},icon:{valid:null,invalid:null,validating:null,feedback:"form-control-feedback"},row:{selector:".form-group",valid:"has-success",invalid:"has-error",feedback:"has-feedback"}},c),FormValidation.Base.apply(this,[b,c,d])},FormValidation.Framework.Bootstrap.prototype=a.extend({},FormValidation.Base.prototype,{_fixIcon:function(a,b){var c=this._namespace,d=a.attr("type"),e=a.attr("data-"+c+"-field"),f=this.options.fields[e].row||this.options.row.selector,g=a.closest(f);if("checkbox"===d||"radio"===d){var h=a.parent();h.hasClass(d)?b.insertAfter(h):h.parent().hasClass(d)&&b.insertAfter(h.parent())}0===g.find("label").length&&b.addClass("fv-icon-no-label"),0!==g.find(".input-group").length&&b.addClass("fv-bootstrap-icon-input-group").insertAfter(g.find(".input-group").eq(0))},_createTooltip:function(a,b,c){var d=this._namespace,e=a.data(d+".icon");if(e)switch(c){case"popover":e.css({cursor:"pointer","pointer-events":"auto"}).popover("destroy").popover({container:"body",content:b,html:!0,placement:"auto top",trigger:"hover click"});break;case"tooltip":default:e.css({cursor:"pointer","pointer-events":"auto"}).tooltip("destroy").tooltip({container:"body",html:!0,placement:"auto top",title:b})}},_destroyTooltip:function(a,b){var c=this._namespace,d=a.data(c+".icon");if(d)switch(b){case"popover":d.css({cursor:"","pointer-events":"none"}).popover("destroy");break;case"tooltip":default:d.css({cursor:"","pointer-events":"none"}).tooltip("destroy")}},_hideTooltip:function(a,b){var c=this._namespace,d=a.data(c+".icon");if(d)switch(b){case"popover":d.popover("hide");break;case"tooltip":default:d.tooltip("hide")}},_showTooltip:function(a,b){var c=this._namespace,d=a.data(c+".icon");if(d)switch(b){case"popover":d.popover("show");break;case"tooltip":default:d.tooltip("show")}}}),a.fn.bootstrapValidator=function(b){var c=arguments;return this.each(function(){var d=a(this),e=d.data("formValidation")||d.data("bootstrapValidator"),f="object"==typeof b&&b;e||(e=new FormValidation.Framework.Bootstrap(this,a.extend({},{events:{formInit:"init.form.bv",formError:"error.form.bv",formSuccess:"success.form.bv",fieldAdded:"added.field.bv",fieldRemoved:"removed.field.bv",fieldInit:"init.field.bv",fieldError:"error.field.bv",fieldSuccess:"success.field.bv",fieldStatus:"status.field.bv",localeChanged:"changed.locale.bv",validatorError:"error.validator.bv",validatorSuccess:"success.validator.bv"}},f),"bv"),d.addClass("fv-form-bootstrap").data("formValidation",e).data("bootstrapValidator",e)),"string"==typeof b&&e[b].apply(e,Array.prototype.slice.call(c,1))})},a.fn.bootstrapValidator.Constructor=FormValidation.Framework.Bootstrap}(jQuery);
--------------------------------------------------------------------------------
/src/js/validator/identical.js:
--------------------------------------------------------------------------------
1 | /**
2 | * identical validator
3 | *
4 | * @link http://formvalidation.io/validators/identical/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | identical: {
13 | 'default': 'Please enter the same value'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.identical = {
19 | html5Attributes: {
20 | message: 'message',
21 | field: 'field'
22 | },
23 |
24 | /**
25 | * Bind the validator on the live change of the field to compare with current one
26 | *
27 | * @param {FormValidation.Base} validator The validator plugin instance
28 | * @param {jQuery} $field Field element
29 | * @param {Object} options Consists of the following key:
30 | * - field: The name of field that will be used to compare with current one
31 | */
32 | init: function(validator, $field, options) {
33 | var compareWith = validator.getFieldElements(options.field);
34 | validator.onLiveChange(compareWith, 'live_identical', function() {
35 | var status = validator.getStatus($field, 'identical');
36 | if (status !== validator.STATUS_NOT_VALIDATED) {
37 | validator.revalidateField($field);
38 | }
39 | });
40 | },
41 |
42 | /**
43 | * Unbind the validator on the live change of the field to compare with current one
44 | *
45 | * @param {FormValidation.Base} validator The validator plugin instance
46 | * @param {jQuery} $field Field element
47 | * @param {Object} options Consists of the following key:
48 | * - field: The name of field that will be used to compare with current one
49 | */
50 | destroy: function(validator, $field, options) {
51 | var compareWith = validator.getFieldElements(options.field);
52 | validator.offLiveChange(compareWith, 'live_identical');
53 | },
54 |
55 | /**
56 | * Check if input value equals to value of particular one
57 | *
58 | * @param {FormValidation.Base} validator The validator plugin instance
59 | * @param {jQuery} $field Field element
60 | * @param {Object} options Consists of the following key:
61 | * - field: The name of field that will be used to compare with current one
62 | * @returns {Boolean}
63 | */
64 | validate: function(validator, $field, options) {
65 | var value = validator.getFieldValue($field, 'identical'),
66 | compareWith = validator.getFieldElements(options.field);
67 | if (compareWith === null || compareWith.length === 0) {
68 | return true;
69 | }
70 |
71 | var compareValue = validator.getFieldValue(compareWith, 'identical');
72 | if (value === compareValue) {
73 | validator.updateStatus(compareWith, validator.STATUS_VALID, 'identical');
74 | return true;
75 | }
76 |
77 | return false;
78 | }
79 | };
80 | }(jQuery));
81 |
--------------------------------------------------------------------------------
/src/js/validator/lessThan.js:
--------------------------------------------------------------------------------
1 | /**
2 | * lessThan validator
3 | *
4 | * @link http://formvalidation.io/validators/lessThan/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | lessThan: {
13 | 'default': 'Please enter a value less than or equal to %s',
14 | notInclusive: 'Please enter a value less than %s'
15 | }
16 | }
17 | });
18 |
19 | FormValidation.Validator.lessThan = {
20 | html5Attributes: {
21 | message: 'message',
22 | value: 'value',
23 | inclusive: 'inclusive'
24 | },
25 |
26 | enableByHtml5: function($field) {
27 | var type = $field.attr('type'),
28 | max = $field.attr('max');
29 | if (max && type !== 'date') {
30 | return {
31 | value: max
32 | };
33 | }
34 |
35 | return false;
36 | },
37 |
38 | /**
39 | * Return true if the input value is less than or equal to given number
40 | *
41 | * @param {FormValidation.Base} validator The validator plugin instance
42 | * @param {jQuery} $field Field element
43 | * @param {Object} options Can consist of the following keys:
44 | * - value: The number used to compare to. It can be
45 | * - A number
46 | * - Name of field which its value defines the number
47 | * - Name of callback function that returns the number
48 | * - A callback function that returns the number
49 | *
50 | * - inclusive [optional]: Can be true or false. Default is true
51 | * - message: The invalid message
52 | * @returns {Boolean|Object}
53 | */
54 | validate: function(validator, $field, options) {
55 | var value = validator.getFieldValue($field, 'lessThan');
56 | if (value === '') {
57 | return true;
58 | }
59 |
60 | value = this._format(value);
61 | if (!$.isNumeric(value)) {
62 | return false;
63 | }
64 |
65 | var locale = validator.getLocale(),
66 | compareTo = $.isNumeric(options.value) ? options.value : validator.getDynamicOption($field, options.value),
67 | compareToValue = this._format(compareTo);
68 |
69 | value = parseFloat(value);
70 | return (options.inclusive === true || options.inclusive === undefined)
71 | ? {
72 | valid: value <= compareToValue,
73 | message: FormValidation.Helper.format(options.message || FormValidation.I18n[locale].lessThan['default'], compareTo)
74 | }
75 | : {
76 | valid: value < compareToValue,
77 | message: FormValidation.Helper.format(options.message || FormValidation.I18n[locale].lessThan.notInclusive, compareTo)
78 | };
79 | },
80 |
81 | _format: function(value) {
82 | return (value + '').replace(',', '.');
83 | }
84 | };
85 | }(jQuery));
86 |
--------------------------------------------------------------------------------
/src/js/validator/greaterThan.js:
--------------------------------------------------------------------------------
1 | /**
2 | * greaterThan validator
3 | *
4 | * @link http://formvalidation.io/validators/greaterThan/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | greaterThan: {
13 | 'default': 'Please enter a value greater than or equal to %s',
14 | notInclusive: 'Please enter a value greater than %s'
15 | }
16 | }
17 | });
18 |
19 | FormValidation.Validator.greaterThan = {
20 | html5Attributes: {
21 | message: 'message',
22 | value: 'value',
23 | inclusive: 'inclusive'
24 | },
25 |
26 | enableByHtml5: function($field) {
27 | var type = $field.attr('type'),
28 | min = $field.attr('min');
29 | if (min && type !== 'date') {
30 | return {
31 | value: min
32 | };
33 | }
34 |
35 | return false;
36 | },
37 |
38 | /**
39 | * Return true if the input value is greater than or equals to given number
40 | *
41 | * @param {FormValidation.Base} validator Validate plugin instance
42 | * @param {jQuery} $field Field element
43 | * @param {Object} options Can consist of the following keys:
44 | * - value: Define the number to compare with. It can be
45 | * - A number
46 | * - Name of field which its value defines the number
47 | * - Name of callback function that returns the number
48 | * - A callback function that returns the number
49 | *
50 | * - inclusive [optional]: Can be true or false. Default is true
51 | * - message: The invalid message
52 | * @returns {Boolean|Object}
53 | */
54 | validate: function(validator, $field, options) {
55 | var value = validator.getFieldValue($field, 'greaterThan');
56 | if (value === '') {
57 | return true;
58 | }
59 |
60 | value = this._format(value);
61 | if (!$.isNumeric(value)) {
62 | return false;
63 | }
64 |
65 | var locale = validator.getLocale(),
66 | compareTo = $.isNumeric(options.value) ? options.value : validator.getDynamicOption($field, options.value),
67 | compareToValue = this._format(compareTo);
68 |
69 | value = parseFloat(value);
70 | return (options.inclusive === true || options.inclusive === undefined)
71 | ? {
72 | valid: value >= compareToValue,
73 | message: FormValidation.Helper.format(options.message || FormValidation.I18n[locale].greaterThan['default'], compareTo)
74 | }
75 | : {
76 | valid: value > compareToValue,
77 | message: FormValidation.Helper.format(options.message || FormValidation.I18n[locale].greaterThan.notInclusive, compareTo)
78 | };
79 | },
80 |
81 | _format: function(value) {
82 | return (value + '').replace(',', '.');
83 | }
84 | };
85 | }(jQuery));
86 |
--------------------------------------------------------------------------------
/src/js/validator/isin.js:
--------------------------------------------------------------------------------
1 | /**
2 | * isin validator
3 | *
4 | * @link http://formvalidation.io/validators/isin/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | isin: {
13 | 'default': 'Please enter a valid ISIN number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.isin = {
19 | // Available country codes
20 | // See http://isin.net/country-codes/
21 | 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',
22 |
23 | /**
24 | * Validate an ISIN (International Securities Identification Number)
25 | * Examples:
26 | * - Valid: US0378331005, AU0000XVGZA3, GB0002634946
27 | * - Invalid: US0378331004, AA0000XVGZA3
28 | *
29 | * @see http://en.wikipedia.org/wiki/International_Securities_Identifying_Number
30 | * @param {FormValidation.Base} validator The validator plugin instance
31 | * @param {jQuery} $field Field element
32 | * @param {Object} options Can consist of the following keys:
33 | * - message: The invalid message
34 | * @returns {Boolean}
35 | */
36 | validate: function(validator, $field, options) {
37 | var value = validator.getFieldValue($field, 'isin');
38 | if (value === '') {
39 | return true;
40 | }
41 |
42 | value = value.toUpperCase();
43 | var regex = new RegExp('^(' + this.COUNTRY_CODES + ')[0-9A-Z]{10}$');
44 | if (!regex.test(value)) {
45 | return false;
46 | }
47 |
48 | var converted = '',
49 | length = value.length;
50 | // Convert letters to number
51 | for (var i = 0; i < length - 1; i++) {
52 | var c = value.charCodeAt(i);
53 | converted += ((c > 57) ? (c - 55).toString() : value.charAt(i));
54 | }
55 |
56 | var digits = '',
57 | n = converted.length,
58 | group = (n % 2 !== 0) ? 0 : 1;
59 | for (i = 0; i < n; i++) {
60 | digits += (parseInt(converted[i], 10) * ((i % 2) === group ? 2 : 1) + '');
61 | }
62 |
63 | var sum = 0;
64 | for (i = 0; i < digits.length; i++) {
65 | sum += parseInt(digits.charAt(i), 10);
66 | }
67 | sum = (10 - (sum % 10)) % 10;
68 | return sum + '' === value.charAt(length - 1);
69 | }
70 | };
71 | }(jQuery));
72 |
--------------------------------------------------------------------------------
/test/spec/dynamic.js:
--------------------------------------------------------------------------------
1 | describe('dynamic fields', function() {
2 | beforeEach(function() {
3 | $([
4 | ''
12 | ].join('\n')).appendTo('body');
13 |
14 | $('#dynamicForm').formValidation({
15 | fields: {
16 | userName: {
17 | validators: {
18 | notEmpty: {
19 | message: 'The user name is required and cannot be empty'
20 | },
21 | regexp: {
22 | regexp: /^[a-zA-Z]+$/,
23 | message: 'The user name can only consist of alphabetical, number'
24 | }
25 | }
26 | },
27 | // #725: Note that the email field isn't available in the form yet
28 | email: {
29 | validators: {
30 | emailAddress: {
31 | message: 'The email address is not valid'
32 | }
33 | }
34 | }
35 | }
36 | });
37 |
38 | this.fv = $('#dynamicForm').data('formValidation');
39 | this.$userName = this.fv.getFieldElements('userName');
40 | });
41 |
42 | afterEach(function() {
43 | $('#dynamicForm').formValidation('destroy').remove();
44 | });
45 |
46 | // https://github.com/formvalidation/formvalidation/pull/725
47 | it('adding field [does not exist but is already set in "fields" option]', function() {
48 | var $div = $('').addClass('form-group').appendTo($('#dynamicForm'));
49 | $email = $('')
50 | .attr('type', 'text')
51 | .addClass('form-control')
52 | .attr('name', 'email')
53 | .appendTo($div);
54 |
55 | this.fv.addField('email');
56 |
57 | this.$userName.val('FormValidation');
58 |
59 | $email.val('not valid@email');
60 | this.fv.validate();
61 | expect(this.fv.isValidField('email')).toBeFalsy();
62 | expect(this.fv.isValid()).toBeFalsy();
63 |
64 | this.fv.resetForm();
65 | $email.val('valid@email.com');
66 | this.fv.validate();
67 | expect(this.fv.isValidField('email')).toBeTruthy();
68 | expect(this.fv.isValid()).toBeTruthy();
69 | });
70 |
71 | // support#48
72 | it('Override the options when adding field', function() {
73 | var options = {
74 | validators: {
75 | stringLength: {
76 | min: 6,
77 | max: 20
78 | }
79 | }
80 | };
81 |
82 | $('#dynamicForm')
83 | .formValidation('destroy')
84 | .formValidation()
85 | .formValidation('addField', 'userName', options);
86 |
87 | // The options shouldn't contain the notEmpty validator (userName field have required attribute)
88 | expect(options.validators.notEmpty).toBeUndefined();
89 | })
90 | });
91 |
--------------------------------------------------------------------------------
/test/spec/api.js:
--------------------------------------------------------------------------------
1 | describe('api', function() {
2 | beforeEach(function() {
3 | $([
4 | ''
15 | ].join('\n')).appendTo('body');
16 |
17 | $('#apiForm').formValidation({
18 | icon: {
19 | valid: 'glyphicon glyphicon-ok',
20 | invalid: 'glyphicon glyphicon-remove',
21 | validating: 'glyphicon glyphicon-refresh'
22 | }
23 | });
24 |
25 | this.fv = $('#apiForm').data('formValidation');
26 | this.$email = this.fv.getFieldElements('email');
27 | this.$note = $('#apiForm').find('input[name="note"]');
28 | });
29 |
30 | afterEach(function() {
31 | $('#apiForm').formValidation('destroy').remove();
32 | });
33 |
34 | it('revalidateField()', function() {
35 | this.$email.val('email@domain.com');
36 | this.fv.validate();
37 | expect(this.fv.isValidField('email')).toBeTruthy();
38 |
39 | this.$email.val('invalid#email.address');
40 | this.fv.revalidateField('email');
41 | expect(this.fv.isValidField(this.$email)).toEqual(false);
42 | });
43 |
44 | it('destroy()', function() {
45 | this.fv.destroy();
46 | expect($('#apiForm').data('formValidation')).toBeUndefined();
47 | expect($('#apiForm').find('i[data-fv-icon-for]').length).toEqual(0);
48 | expect($('#apiForm').find('.help-block[data-fv-for]').length).toEqual(0);
49 | expect($('#apiForm').find('.has-feedback').length).toEqual(0);
50 | expect($('#apiForm').find('.has-success').length).toEqual(0);
51 | expect($('#apiForm').find('.has-error').length).toEqual(0);
52 | expect($('#apiForm').find('[data-fv-field]').length).toEqual(0);
53 | });
54 |
55 | it('getOptions()', function() {
56 | // Form options
57 | expect(this.fv.getOptions().icon.valid).toEqual('glyphicon glyphicon-ok');
58 |
59 | // Field options
60 | expect(this.fv.getOptions('username', 'stringlength')).toBeNull();
61 | expect(this.fv.getOptions('username', 'stringlength', 'min')).toBeNull();
62 |
63 | expect(this.fv.getOptions('username', 'stringLength')).toBeDefined();
64 | expect(this.fv.getOptions('username', 'stringLength', 'min')).toEqual('8');
65 | expect(this.fv.getOptions('username', 'stringlength', 'max')).toBeNull();
66 | });
67 |
68 | // #1014
69 | it('isValidField()', function() {
70 | this.$email.val('email@domain.com');
71 | this.fv.validate();
72 | expect(this.fv.isValidField(this.$note)).toBeTruthy();
73 | expect(this.fv.isValidField(this.$email)).toBeTruthy();
74 | });
75 |
76 | // #1014
77 | it('validateField()', function() {
78 | this.$email.val('email@domain.com');
79 | this.fv.validateField(this.$email);
80 | this.fv.validateField(this.$note);
81 | expect(this.fv.isValidField(this.$email)).toBeTruthy();
82 | expect(this.fv.isValidField(this.$note)).toBeTruthy();
83 | });
84 | });
85 |
--------------------------------------------------------------------------------
/src/js/validator/between.js:
--------------------------------------------------------------------------------
1 | /**
2 | * between validator
3 | *
4 | * @link http://formvalidation.io/validators/between/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | between: {
13 | 'default': 'Please enter a value between %s and %s',
14 | notInclusive: 'Please enter a value between %s and %s strictly'
15 | }
16 | }
17 | });
18 |
19 | FormValidation.Validator.between = {
20 | html5Attributes: {
21 | message: 'message',
22 | min: 'min',
23 | max: 'max',
24 | inclusive: 'inclusive'
25 | },
26 |
27 | enableByHtml5: function($field) {
28 | if ('range' === $field.attr('type')) {
29 | return {
30 | min: $field.attr('min'),
31 | max: $field.attr('max')
32 | };
33 | }
34 |
35 | return false;
36 | },
37 |
38 | /**
39 | * Return true if the input value is between (strictly or not) two given numbers
40 | *
41 | * @param {FormValidation.Base} validator The validator plugin instance
42 | * @param {jQuery} $field Field element
43 | * @param {Object} options Can consist of the following keys:
44 | * - min
45 | * - max
46 | *
47 | * The min, max keys define the number which the field value compares to. min, max can be
48 | * - A number
49 | * - Name of field which its value defines the number
50 | * - Name of callback function that returns the number
51 | * - A callback function that returns the number
52 | *
53 | * - inclusive [optional]: Can be true or false. Default is true
54 | * - message: The invalid message
55 | * @returns {Boolean|Object}
56 | */
57 | validate: function(validator, $field, options) {
58 | var value = validator.getFieldValue($field, 'between');
59 | if (value === '') {
60 | return true;
61 | }
62 |
63 | value = this._format(value);
64 | if (!$.isNumeric(value)) {
65 | return false;
66 | }
67 |
68 | var locale = validator.getLocale(),
69 | min = $.isNumeric(options.min) ? options.min : validator.getDynamicOption($field, options.min),
70 | max = $.isNumeric(options.max) ? options.max : validator.getDynamicOption($field, options.max),
71 | minValue = this._format(min),
72 | maxValue = this._format(max);
73 |
74 | value = parseFloat(value);
75 | return (options.inclusive === true || options.inclusive === undefined)
76 | ? {
77 | valid: value >= minValue && value <= maxValue,
78 | message: FormValidation.Helper.format(options.message || FormValidation.I18n[locale].between['default'], [min, max])
79 | }
80 | : {
81 | valid: value > minValue && value < maxValue,
82 | message: FormValidation.Helper.format(options.message || FormValidation.I18n[locale].between.notInclusive, [min, max])
83 | };
84 | },
85 |
86 | _format: function(value) {
87 | return (value + '').replace(',', '.');
88 | }
89 | };
90 | }(jQuery));
91 |
--------------------------------------------------------------------------------
/src/js/validator/choice.js:
--------------------------------------------------------------------------------
1 | /**
2 | * choice validator
3 | *
4 | * @link http://formvalidation.io/validators/choice/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | choice: {
13 | 'default': 'Please enter a valid value',
14 | less: 'Please choose %s options at minimum',
15 | more: 'Please choose %s options at maximum',
16 | between: 'Please choose %s - %s options'
17 | }
18 | }
19 | });
20 |
21 | FormValidation.Validator.choice = {
22 | html5Attributes: {
23 | message: 'message',
24 | min: 'min',
25 | max: 'max'
26 | },
27 |
28 | /**
29 | * Check if the number of checked boxes are less or more than a given number
30 | *
31 | * @param {FormValidation.Base} validator The validator plugin instance
32 | * @param {jQuery} $field Field element
33 | * @param {Object} options Consists of following keys:
34 | * - min
35 | * - max
36 | *
37 | * At least one of two keys is required
38 | * The min, max keys define the number which the field value compares to. min, max can be
39 | * - A number
40 | * - Name of field which its value defines the number
41 | * - Name of callback function that returns the number
42 | * - A callback function that returns the number
43 | *
44 | * - message: The invalid message
45 | * @returns {Object}
46 | */
47 | validate: function(validator, $field, options) {
48 | var locale = validator.getLocale(),
49 | ns = validator.getNamespace(),
50 | numChoices = $field.is('select')
51 | ? validator.getFieldElements($field.attr('data-' + ns + '-field')).find('option').filter(':selected').length
52 | : validator.getFieldElements($field.attr('data-' + ns + '-field')).filter(':checked').length,
53 | min = options.min ? ($.isNumeric(options.min) ? options.min : validator.getDynamicOption($field, options.min)) : null,
54 | max = options.max ? ($.isNumeric(options.max) ? options.max : validator.getDynamicOption($field, options.max)) : null,
55 | isValid = true,
56 | message = options.message || FormValidation.I18n[locale].choice['default'];
57 |
58 | if ((min && numChoices < parseInt(min, 10)) || (max && numChoices > parseInt(max, 10))) {
59 | isValid = false;
60 | }
61 |
62 | switch (true) {
63 | case (!!min && !!max):
64 | message = FormValidation.Helper.format(options.message || FormValidation.I18n[locale].choice.between, [parseInt(min, 10), parseInt(max, 10)]);
65 | break;
66 |
67 | case (!!min):
68 | message = FormValidation.Helper.format(options.message || FormValidation.I18n[locale].choice.less, parseInt(min, 10));
69 | break;
70 |
71 | case (!!max):
72 | message = FormValidation.Helper.format(options.message || FormValidation.I18n[locale].choice.more, parseInt(max, 10));
73 | break;
74 |
75 | default:
76 | break;
77 | }
78 |
79 | return { valid: isValid, message: message };
80 | }
81 | };
82 | }(jQuery));
83 |
--------------------------------------------------------------------------------
/test/spec/autoFocus.js:
--------------------------------------------------------------------------------
1 | describe('autoFocus', function() {
2 | // Use $element.is(document.activeElement) instead of $element.is(':focus')
3 | // to support running the test cases with PhantomJS
4 | // See https://github.com/ariya/phantomjs/issues/10427
5 |
6 | beforeEach(function() {
7 | $([
8 | ''
19 | ].join('')).appendTo('body');
20 |
21 | this.fv = $('#autoFocusForm')
22 | .formValidation()
23 | .submit(function(e) {
24 | e.preventDefault();
25 | })
26 | .data('formValidation');
27 | this.$username = this.fv.getFieldElements('username');
28 | this.$email = this.fv.getFieldElements('email');
29 | });
30 |
31 | afterEach(function() {
32 | $('#autoFocusForm').formValidation('destroy').remove();
33 | });
34 |
35 | it('default option (autoFocus=true)', function() {
36 | $('#submitButton').click();
37 | expect(this.$username.is(document.activeElement)).toBeTruthy();
38 | expect($(document.activeElement).attr('name')).toEqual('username');
39 |
40 | this.fv.resetForm();
41 | this.$username.val('user_name');
42 | this.$email.val('');
43 | $('#submitButton').click();
44 | expect(this.$email.is(document.activeElement)).toBeTruthy();
45 | expect($(document.activeElement).attr('name')).toEqual('email');
46 | });
47 |
48 | it('set autoFocus=false for form', function() {
49 | $('#autoFocusForm')
50 | .formValidation('destroy')
51 | .formValidation({
52 | autoFocus: false
53 | });
54 | this.$username.val('');
55 | this.$email.val('invalid#email');
56 | $('#submitButton').click();
57 |
58 | expect(this.$username.is(document.activeElement)).toBeFalsy();
59 | expect(this.$email.is(document.activeElement)).toBeFalsy();
60 | });
61 |
62 | it('set autoFocus=false for all fields', function() {
63 | this.fv
64 | .addField('username', {
65 | autoFocus: false
66 | })
67 | .addField('email', {
68 | autoFocus: false
69 | });
70 | this.$username.val('user_name');
71 | this.$email.val('invalid#email');
72 | $('#submitButton').click();
73 |
74 | expect(this.$username.is(document.activeElement)).toBeFalsy();
75 | expect(this.$email.is(document.activeElement)).toBeFalsy();
76 | });
77 |
78 | it('set different autoFocus value for fields', function() {
79 | this.fv
80 | .addField('username', {
81 | autoFocus: false
82 | })
83 | .addField('email', {
84 | autoFocus: true
85 | });
86 | this.$username.val('');
87 | this.$email.val('invalid_email');
88 | $('#submitButton').click();
89 |
90 | expect(this.$username.is(document.activeElement)).toBeFalsy();
91 | expect(this.$email.is(document.activeElement)).toBeTruthy();
92 | expect($(document.activeElement).attr('name')).toEqual('email');
93 | });
94 | });
95 |
--------------------------------------------------------------------------------
/demo/event2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | FormValidation demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
45 |
46 |
88 |
89 |
--------------------------------------------------------------------------------
/src/js/validator/ip.js:
--------------------------------------------------------------------------------
1 | /**
2 | * ip validator
3 | *
4 | * @link http://formvalidation.io/validators/ip/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | ip: {
13 | 'default': 'Please enter a valid IP address',
14 | ipv4: 'Please enter a valid IPv4 address',
15 | ipv6: 'Please enter a valid IPv6 address'
16 | }
17 | }
18 | });
19 |
20 | FormValidation.Validator.ip = {
21 | html5Attributes: {
22 | message: 'message',
23 | ipv4: 'ipv4',
24 | ipv6: 'ipv6'
25 | },
26 |
27 | /**
28 | * Return true if the input value is a IP address.
29 | *
30 | * @param {FormValidation.Base} validator The validator plugin instance
31 | * @param {jQuery} $field Field element
32 | * @param {Object} options Can consist of the following keys:
33 | * - ipv4: Enable IPv4 validator, default to true
34 | * - ipv6: Enable IPv6 validator, default to true
35 | * - message: The invalid message
36 | * @returns {Boolean|Object}
37 | */
38 | validate: function(validator, $field, options) {
39 | var value = validator.getFieldValue($field, 'ip');
40 | if (value === '') {
41 | return true;
42 | }
43 | options = $.extend({}, { ipv4: true, ipv6: true }, options);
44 |
45 | var locale = validator.getLocale(),
46 | ipv4Regex = /^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$/,
47 | ipv6Regex = /^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/,
48 | valid = false,
49 | message;
50 |
51 | switch (true) {
52 | case (options.ipv4 && !options.ipv6):
53 | valid = ipv4Regex.test(value);
54 | message = options.message || FormValidation.I18n[locale].ip.ipv4;
55 | break;
56 |
57 | case (!options.ipv4 && options.ipv6):
58 | valid = ipv6Regex.test(value);
59 | message = options.message || FormValidation.I18n[locale].ip.ipv6;
60 | break;
61 |
62 | case (options.ipv4 && options.ipv6):
63 | /* falls through */
64 | default:
65 | valid = ipv4Regex.test(value) || ipv6Regex.test(value);
66 | message = options.message || FormValidation.I18n[locale].ip['default'];
67 | break;
68 | }
69 |
70 | return {
71 | valid: valid,
72 | message: message
73 | };
74 | }
75 | };
76 | }(jQuery));
77 |
--------------------------------------------------------------------------------
/demo/tooltip.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | FormValidation demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
48 |
49 |
98 |
99 |
--------------------------------------------------------------------------------
/src/js/validator/different.js:
--------------------------------------------------------------------------------
1 | /**
2 | * different validator
3 | *
4 | * @link http://formvalidation.io/validators/different/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | different: {
13 | 'default': 'Please enter a different value'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.different = {
19 | html5Attributes: {
20 | message: 'message',
21 | field: 'field'
22 | },
23 |
24 | /**
25 | * Bind the validator on the live change of the field to compare with current one
26 | *
27 | * @param {FormValidation.Base} validator The validator plugin instance
28 | * @param {jQuery} $field Field element
29 | * @param {Object} options Consists of the following key:
30 | * - field: The name of field that will be used to compare with current one
31 | */
32 | init: function(validator, $field, options) {
33 | var fields = options.field.split(',');
34 | for (var i = 0; i < fields.length; i++) {
35 | var compareWith = validator.getFieldElements(fields[i]);
36 | validator.onLiveChange(compareWith, 'live_different', function() {
37 | var status = validator.getStatus($field, 'different');
38 | if (status !== validator.STATUS_NOT_VALIDATED) {
39 | validator.revalidateField($field);
40 | }
41 | });
42 | }
43 | },
44 |
45 | /**
46 | * Unbind the validator on the live change of the field to compare with current one
47 | *
48 | * @param {FormValidation.Base} validator The validator plugin instance
49 | * @param {jQuery} $field Field element
50 | * @param {Object} options Consists of the following key:
51 | * - field: The name of field that will be used to compare with current one
52 | */
53 | destroy: function(validator, $field, options) {
54 | var fields = options.field.split(',');
55 | for (var i = 0; i < fields.length; i++) {
56 | var compareWith = validator.getFieldElements(fields[i]);
57 | validator.offLiveChange(compareWith, 'live_different');
58 | }
59 | },
60 |
61 | /**
62 | * Return true if the input value is different with given field's value
63 | *
64 | * @param {FormValidation.Base} validator The validator plugin instance
65 | * @param {jQuery} $field Field element
66 | * @param {Object} options Consists of the following key:
67 | * - field: The name of field that will be used to compare with current one
68 | * - message: The invalid message
69 | * @returns {Boolean}
70 | */
71 | validate: function(validator, $field, options) {
72 | var value = validator.getFieldValue($field, 'different');
73 | if (value === '') {
74 | return true;
75 | }
76 |
77 | var fields = options.field.split(','),
78 | isValid = true;
79 |
80 | for (var i = 0; i < fields.length; i++) {
81 | var compareWith = validator.getFieldElements(fields[i]);
82 | if (compareWith == null || compareWith.length === 0) {
83 | continue;
84 | }
85 |
86 | var compareValue = validator.getFieldValue(compareWith, 'different');
87 | if (value === compareValue) {
88 | isValid = false;
89 | } else if (compareValue !== '') {
90 | validator.updateStatus(compareWith, validator.STATUS_VALID, 'different');
91 | }
92 | }
93 |
94 | return isValid;
95 | }
96 | };
97 | }(jQuery));
98 |
--------------------------------------------------------------------------------
/src/js/validator/isbn.js:
--------------------------------------------------------------------------------
1 | /**
2 | * isbn validator
3 | *
4 | * @link http://formvalidation.io/validators/isbn/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | isbn: {
13 | 'default': 'Please enter a valid ISBN number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.isbn = {
19 | /**
20 | * Return true if the input value is a valid ISBN 10 or ISBN 13 number
21 | * Examples:
22 | * - Valid:
23 | * 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
24 | * ISBN 13: 978-0-306-40615-7
25 | * - Invalid:
26 | * ISBN 10: 99921-58-10-6
27 | * ISBN 13: 978-0-306-40615-6
28 | *
29 | * @see http://en.wikipedia.org/wiki/International_Standard_Book_Number
30 | * @param {FormValidation.Base} validator The validator plugin instance
31 | * @param {jQuery} $field Field element
32 | * @param {Object} [options] Can consist of the following keys:
33 | * - message: The invalid message
34 | * @returns {Boolean}
35 | */
36 | validate: function(validator, $field, options) {
37 | var value = validator.getFieldValue($field, 'isbn');
38 | if (value === '') {
39 | return true;
40 | }
41 |
42 | // http://en.wikipedia.org/wiki/International_Standard_Book_Number#Overview
43 | // Groups are separated by a hyphen or a space
44 | var type;
45 | switch (true) {
46 | case /^\d{9}[\dX]$/.test(value):
47 | case (value.length === 13 && /^(\d+)-(\d+)-(\d+)-([\dX])$/.test(value)):
48 | case (value.length === 13 && /^(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(value)):
49 | type = 'ISBN10';
50 | break;
51 | case /^(978|979)\d{9}[\dX]$/.test(value):
52 | case (value.length === 17 && /^(978|979)-(\d+)-(\d+)-(\d+)-([\dX])$/.test(value)):
53 | case (value.length === 17 && /^(978|979)\s(\d+)\s(\d+)\s(\d+)\s([\dX])$/.test(value)):
54 | type = 'ISBN13';
55 | break;
56 | default:
57 | return false;
58 | }
59 |
60 | // Replace all special characters except digits and X
61 | value = value.replace(/[^0-9X]/gi, '');
62 | var chars = value.split(''),
63 | length = chars.length,
64 | sum = 0,
65 | i,
66 | checksum;
67 |
68 | switch (type) {
69 | case 'ISBN10':
70 | sum = 0;
71 | for (i = 0; i < length - 1; i++) {
72 | sum += parseInt(chars[i], 10) * (10 - i);
73 | }
74 | checksum = 11 - (sum % 11);
75 | if (checksum === 11) {
76 | checksum = 0;
77 | } else if (checksum === 10) {
78 | checksum = 'X';
79 | }
80 | return (checksum + '' === chars[length - 1]);
81 |
82 | case 'ISBN13':
83 | sum = 0;
84 | for (i = 0; i < length - 1; i++) {
85 | sum += ((i % 2 === 0) ? parseInt(chars[i], 10) : (parseInt(chars[i], 10) * 3));
86 | }
87 | checksum = 10 - (sum % 10);
88 | if (checksum === 10) {
89 | checksum = '0';
90 | }
91 | return (checksum + '' === chars[length - 1]);
92 |
93 | default:
94 | return false;
95 | }
96 | }
97 | };
98 | }(jQuery));
99 |
--------------------------------------------------------------------------------
/demo/ignored.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | FormValidation demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
54 |
55 |
93 |
94 |
--------------------------------------------------------------------------------
/demo/event3.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | FormValidation demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
47 |
48 |
100 |
101 |
--------------------------------------------------------------------------------
/demo/container.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | FormValidation demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
55 |
56 |
99 |
100 |
--------------------------------------------------------------------------------
/test/spec/validator/creditCard.js:
--------------------------------------------------------------------------------
1 | describe('creditCard', function() {
2 | // Get the fake credit card number at http://www.getcreditcardnumbers.com/
3 |
4 | beforeEach(function() {
5 | var html = [
6 | ''
13 | ].join('\n');
14 |
15 | $(html).appendTo('body');
16 | $('#ccForm').formValidation();
17 |
18 | this.fv = $('#ccForm').data('formValidation');
19 | this.$creditCard = this.fv.getFieldElements('cc');
20 | });
21 |
22 | afterEach(function() {
23 | $('#ccForm').formValidation('destroy').parent().remove();
24 | });
25 |
26 | it('accept spaces', function() {
27 | this.$creditCard.val('5267 9789 9451 9654');
28 | this.fv.validate();
29 | expect(this.fv.isValidField('cc')).toBeTruthy();
30 | });
31 |
32 | it('accept dashes', function() {
33 | this.$creditCard.val('6011-2649-6840-4521');
34 | this.fv.validate();
35 | expect(this.fv.isValidField('cc')).toBeTruthy();
36 | });
37 |
38 | it('invalid format', function() {
39 | this.$creditCard.val('4539.1870.2954.3862');
40 | this.fv.validate();
41 | expect(this.fv.isValidField('cc')).toEqual(false);
42 | });
43 |
44 | it('American Express', function() {
45 | this.$creditCard.val('340653705597107');
46 | this.fv.validate();
47 | expect(this.fv.isValidField('cc')).toBeTruthy();
48 | });
49 |
50 | it('American Express invalid length', function() {
51 | this.$creditCard.val('3744148309166730');
52 | this.fv.validate();
53 | expect(this.fv.isValidField('cc')).toEqual(false);
54 | });
55 |
56 | it('American Express invalid prefix', function() {
57 | this.$creditCard.val('356120148436654');
58 | this.fv.validate();
59 | expect(this.fv.isValidField('cc')).toEqual(false);
60 | });
61 |
62 | it('Diners Club', function() {
63 | this.$creditCard.val('30130708434187');
64 | this.fv.validate();
65 | expect(this.fv.isValidField('cc')).toBeTruthy();
66 | });
67 |
68 | it('Diners Club (US)', function() {
69 | this.$creditCard.val('5517479515603901');
70 | this.fv.validate();
71 | expect(this.fv.isValidField('cc')).toBeTruthy();
72 | });
73 |
74 | it('Discover', function() {
75 | this.$creditCard.val('6011734674929094');
76 | this.fv.validate();
77 | expect(this.fv.isValidField('cc')).toBeTruthy();
78 | });
79 |
80 | it('JCB', function() {
81 | this.$creditCard.val('3566002020360505');
82 | this.fv.validate();
83 | expect(this.fv.isValidField('cc')).toBeTruthy();
84 | });
85 |
86 | it('Laser', function() {
87 | this.$creditCard.val('6304 9000 1774 0292 441');
88 | this.fv.validate();
89 | expect(this.fv.isValidField('cc')).toBeTruthy();
90 | });
91 |
92 | it('Maestro', function() {
93 | this.$creditCard.val('6762835098779303');
94 | this.fv.validate();
95 | expect(this.fv.isValidField('cc')).toBeTruthy();
96 | });
97 |
98 | it('Mastercard', function() {
99 | this.$creditCard.val('5303765013600904');
100 | this.fv.validate();
101 | expect(this.fv.isValidField('cc')).toBeTruthy();
102 | });
103 |
104 | it('Solo', function() {
105 | this.$creditCard.val('6334580500000000');
106 | this.fv.validate();
107 | expect(this.fv.isValidField('cc')).toBeTruthy();
108 | });
109 |
110 | it('Visa', function() {
111 | this.$creditCard.val('4929248980295542');
112 | this.fv.validate();
113 | expect(this.fv.isValidField('cc')).toBeTruthy();
114 | });
115 |
116 | it('Visa invalid check digit', function() {
117 | this.$creditCard.val('4532599916257826');
118 | this.fv.validate();
119 | expect(this.fv.isValidField('cc')).toEqual(false);
120 | });
121 | });
122 |
--------------------------------------------------------------------------------
/src/js/validator/meid.js:
--------------------------------------------------------------------------------
1 | /**
2 | * meid validator
3 | *
4 | * @link http://formvalidation.io/validators/meid/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | meid: {
13 | 'default': 'Please enter a valid MEID number'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.meid = {
19 | /**
20 | * Validate MEID (Mobile Equipment Identifier)
21 | * Examples:
22 | * - Valid: 293608736500703710, 29360-87365-0070-3710, AF0123450ABCDE, AF-012345-0ABCDE
23 | * - Invalid: 2936087365007037101
24 | *
25 | * @see http://en.wikipedia.org/wiki/Mobile_equipment_identifier
26 | * @param {FormValidation.Base} validator The validator plugin instance
27 | * @param {jQuery} $field Field element
28 | * @param {Object} options Can consist of the following keys:
29 | * - message: The invalid message
30 | * @returns {Boolean}
31 | */
32 | validate: function(validator, $field, options) {
33 | var value = validator.getFieldValue($field, 'meid');
34 | if (value === '') {
35 | return true;
36 | }
37 |
38 | switch (true) {
39 | // 14 digit hex representation (no check digit)
40 | case /^[0-9A-F]{15}$/i.test(value):
41 | // 14 digit hex representation + dashes or spaces (no check digit)
42 | case /^[0-9A-F]{2}[- ][0-9A-F]{6}[- ][0-9A-F]{6}[- ][0-9A-F]$/i.test(value):
43 | // 18 digit decimal representation (no check digit)
44 | case /^\d{19}$/.test(value):
45 | // 18 digit decimal representation + dashes or spaces (no check digit)
46 | case /^\d{5}[- ]\d{5}[- ]\d{4}[- ]\d{4}[- ]\d$/.test(value):
47 | // Grab the check digit
48 | var cd = value.charAt(value.length - 1);
49 |
50 | // Strip any non-hex chars
51 | value = value.replace(/[- ]/g, '');
52 |
53 | // If it's all digits, luhn base 10 is used
54 | if (value.match(/^\d*$/i)) {
55 | return FormValidation.Helper.luhn(value);
56 | }
57 |
58 | // Strip the check digit
59 | value = value.slice(0, -1);
60 |
61 | // Get every other char, and double it
62 | var cdCalc = '';
63 | for (var i = 1; i <= 13; i += 2) {
64 | cdCalc += (parseInt(value.charAt(i), 16) * 2).toString(16);
65 | }
66 |
67 | // Get the sum of each char in the string
68 | var sum = 0;
69 | for (i = 0; i < cdCalc.length; i++) {
70 | sum += parseInt(cdCalc.charAt(i), 16);
71 | }
72 |
73 | // If the last digit of the calc is 0, the check digit is 0
74 | return (sum % 10 === 0)
75 | ? (cd === '0')
76 | // Subtract it from the next highest 10s number (64 goes to 70) and subtract the sum
77 | // Double it and turn it into a hex char
78 | : (cd === ((Math.floor((sum + 10) / 10) * 10 - sum) * 2).toString(16));
79 |
80 | // 14 digit hex representation (no check digit)
81 | case /^[0-9A-F]{14}$/i.test(value):
82 | // 14 digit hex representation + dashes or spaces (no check digit)
83 | case /^[0-9A-F]{2}[- ][0-9A-F]{6}[- ][0-9A-F]{6}$/i.test(value):
84 | // 18 digit decimal representation (no check digit)
85 | case /^\d{18}$/.test(value):
86 | // 18 digit decimal representation + dashes or spaces (no check digit)
87 | case /^\d{5}[- ]\d{5}[- ]\d{4}[- ]\d{4}$/.test(value):
88 | return true;
89 |
90 | default:
91 | return false;
92 | }
93 | }
94 | };
95 | }(jQuery));
96 |
--------------------------------------------------------------------------------
/vendor/jasmine/jasmine.css:
--------------------------------------------------------------------------------
1 | body { background-color: #eeeeee; padding: 0; margin: 5px; overflow-y: scroll; }
2 |
3 | .html-reporter { font-size: 11px; font-family: Monaco, "Lucida Console", monospace; line-height: 14px; color: #333333; }
4 | .html-reporter a { text-decoration: none; }
5 | .html-reporter a:hover { text-decoration: underline; }
6 | .html-reporter p, .html-reporter h1, .html-reporter h2, .html-reporter h3, .html-reporter h4, .html-reporter h5, .html-reporter h6 { margin: 0; line-height: 14px; }
7 | .html-reporter .banner, .html-reporter .symbol-summary, .html-reporter .summary, .html-reporter .result-message, .html-reporter .spec .description, .html-reporter .spec-detail .description, .html-reporter .alert .bar, .html-reporter .stack-trace { padding-left: 9px; padding-right: 9px; }
8 | .html-reporter .banner .version { margin-left: 14px; }
9 | .html-reporter #jasmine_content { position: fixed; right: 100%; }
10 | .html-reporter .version { color: #aaaaaa; }
11 | .html-reporter .banner { margin-top: 14px; }
12 | .html-reporter .duration { color: #aaaaaa; float: right; }
13 | .html-reporter .symbol-summary { overflow: hidden; *zoom: 1; margin: 14px 0; }
14 | .html-reporter .symbol-summary li { display: inline-block; height: 8px; width: 14px; font-size: 16px; }
15 | .html-reporter .symbol-summary li.passed { font-size: 14px; }
16 | .html-reporter .symbol-summary li.passed:before { color: #5e7d00; content: "\02022"; }
17 | .html-reporter .symbol-summary li.failed { line-height: 9px; }
18 | .html-reporter .symbol-summary li.failed:before { color: #b03911; content: "x"; font-weight: bold; margin-left: -1px; }
19 | .html-reporter .symbol-summary li.disabled { font-size: 14px; }
20 | .html-reporter .symbol-summary li.disabled:before { color: #bababa; content: "\02022"; }
21 | .html-reporter .symbol-summary li.pending { line-height: 17px; }
22 | .html-reporter .symbol-summary li.pending:before { color: #ba9d37; content: "*"; }
23 | .html-reporter .exceptions { color: #fff; float: right; margin-top: 5px; margin-right: 5px; }
24 | .html-reporter .bar { line-height: 28px; font-size: 14px; display: block; color: #eee; }
25 | .html-reporter .bar.failed { background-color: #b03911; }
26 | .html-reporter .bar.passed { background-color: #a6b779; }
27 | .html-reporter .bar.skipped { background-color: #bababa; }
28 | .html-reporter .bar.menu { background-color: #fff; color: #aaaaaa; }
29 | .html-reporter .bar.menu a { color: #333333; }
30 | .html-reporter .bar a { color: white; }
31 | .html-reporter.spec-list .bar.menu.failure-list, .html-reporter.spec-list .results .failures { display: none; }
32 | .html-reporter.failure-list .bar.menu.spec-list, .html-reporter.failure-list .summary { display: none; }
33 | .html-reporter .running-alert { background-color: #666666; }
34 | .html-reporter .results { margin-top: 14px; }
35 | .html-reporter.showDetails .summaryMenuItem { font-weight: normal; text-decoration: inherit; }
36 | .html-reporter.showDetails .summaryMenuItem:hover { text-decoration: underline; }
37 | .html-reporter.showDetails .detailsMenuItem { font-weight: bold; text-decoration: underline; }
38 | .html-reporter.showDetails .summary { display: none; }
39 | .html-reporter.showDetails #details { display: block; }
40 | .html-reporter .summaryMenuItem { font-weight: bold; text-decoration: underline; }
41 | .html-reporter .summary { margin-top: 14px; }
42 | .html-reporter .summary ul { list-style-type: none; margin-left: 14px; padding-top: 0; padding-left: 0; }
43 | .html-reporter .summary ul.suite { margin-top: 7px; margin-bottom: 7px; }
44 | .html-reporter .summary li.passed a { color: #5e7d00; }
45 | .html-reporter .summary li.failed a { color: #b03911; }
46 | .html-reporter .summary li.pending a { color: #ba9d37; }
47 | .html-reporter .description + .suite { margin-top: 0; }
48 | .html-reporter .suite { margin-top: 14px; }
49 | .html-reporter .suite a { color: #333333; }
50 | .html-reporter .failures .spec-detail { margin-bottom: 28px; }
51 | .html-reporter .failures .spec-detail .description { background-color: #b03911; }
52 | .html-reporter .failures .spec-detail .description a { color: white; }
53 | .html-reporter .result-message { padding-top: 14px; color: #333333; white-space: pre; }
54 | .html-reporter .result-message span.result { display: block; }
55 | .html-reporter .stack-trace { margin: 5px 0 0 0; max-height: 224px; overflow: auto; line-height: 18px; color: #666666; border: 1px solid #ddd; background: white; white-space: pre; }
56 |
--------------------------------------------------------------------------------
/test/spec/enable.js:
--------------------------------------------------------------------------------
1 | describe('enable validators', function() {
2 | beforeEach(function() {
3 | $([
4 | ''
9 | ].join('\n')).appendTo('body');
10 |
11 | $('#enableForm').formValidation({
12 | fields: {
13 | fullName: {
14 | validators: {
15 | notEmpty: {
16 | message: 'The full name is required and cannot be empty'
17 | },
18 | stringLength: {
19 | min: 8,
20 | max: 40,
21 | message: 'The full name must be more than %s and less than %s characters long'
22 | },
23 | regexp: {
24 | enabled: false,
25 | regexp: /^[a-zA-Z\s]+$/,
26 | message: 'The full name can only consist of alphabetical, number, and space'
27 | }
28 | }
29 | }
30 | }
31 | });
32 |
33 | this.fv = $('#enableForm').data('formValidation');
34 | this.$fullName = this.fv.getFieldElements('fullName');
35 | });
36 |
37 | afterEach(function() {
38 | $('#enableForm').formValidation('destroy').remove();
39 | });
40 |
41 | it('enable all validators', function() {
42 | this.$fullName.val('@ $full N@m3');
43 | this.fv.validate();
44 | expect(this.fv.isValid()).toBeTruthy();
45 |
46 | this.fv.resetForm();
47 | this.$fullName.val('Contain#$@');
48 | this.fv.enableFieldValidators('fullName', true);
49 | this.fv.validate();
50 | expect(this.fv.isValidField('fullName')).toEqual(false);
51 | expect(this.fv.isValid()).toEqual(false);
52 | });
53 |
54 | it('disable all validators', function() {
55 | this.fv.resetForm();
56 | this.fv.enableFieldValidators('fullName', false);
57 | this.fv.validate();
58 | expect(this.fv.isValid()).toBeTruthy();
59 | });
60 |
61 | it('enabled option particular validator', function() {
62 | this.$fullName.val('Contain@#$');
63 | this.fv.validate();
64 | expect(this.fv.isValid()).toBeTruthy();
65 |
66 | var messages = this.fv.getMessages('fullName');
67 | expect(messages.length).toEqual(0);
68 | });
69 |
70 | it('enable particular validators', function() {
71 | // Enable stringLength validator
72 | this.fv.resetForm();
73 | this.fv.enableFieldValidators('fullName', true, 'stringLength');
74 | this.fv.enableFieldValidators('fullName', true, 'regexp');
75 | this.$fullName.val('Full@');
76 | this.fv.validate();
77 | expect(this.fv.isValid()).toEqual(false);
78 |
79 | var messages = this.fv.getMessages('fullName');
80 | expect($.inArray('The full name must be more than 8 and less than 40 characters long', messages)).toBeGreaterThan(-1);
81 | expect($.inArray('The full name can only consist of alphabetical, number, and space', messages)).toBeGreaterThan(-1);
82 | });
83 |
84 | it('disable particular validators', function() {
85 | // Disable stringLength validator
86 | this.fv.enableFieldValidators('fullName', false, 'stringLength');
87 | this.$fullName.val('Full');
88 | this.fv.validate();
89 | expect(this.fv.isValid()).toBeTruthy();
90 |
91 | var messages = this.fv.getMessages('fullName');
92 | expect($.inArray('The full name must be more than 8 and less than 40 characters long', messages)).toEqual(-1);
93 |
94 | // Disable regexp validator
95 | this.fv.enableFieldValidators('fullName', false, 'regexp');
96 | this.$fullName.val('Special@#$');
97 | this.fv.validate();
98 | expect(this.fv.isValid()).toBeTruthy();
99 |
100 | var messages = this.fv.getMessages('fullName');
101 | expect($.inArray('The full name can only consist of alphabetical, number, and space', messages)).toEqual(-1);
102 | });
103 | });
104 |
--------------------------------------------------------------------------------
/test/spec/transformer.js:
--------------------------------------------------------------------------------
1 | TestSuite = $.extend({}, TestSuite, {
2 | Transformer: {
3 | uri: function($field, validator) {
4 | var value = $field.val();
5 | if (value && value.substr(0, 7) !== 'http://' && value.substr(0, 8) !== 'https://') {
6 | value = 'http://' + value;
7 | }
8 | return value;
9 | }
10 | }
11 | });
12 |
13 | describe('transformer', function() {
14 | beforeEach(function() {
15 | $([
16 | ''
21 | ].join('\n')).appendTo('body');
22 |
23 | $('#transformerForm').formValidation();
24 |
25 | this.fv = $('#transformerForm').data('formValidation');
26 | this.$website = this.fv.getFieldElements('website');
27 | });
28 |
29 | afterEach(function() {
30 | $('#transformerForm').formValidation('destroy').remove();
31 | });
32 |
33 | it('transformer not set', function() {
34 | this.$website.val('foo.com');
35 | this.fv.validate();
36 | expect(this.fv.isValid()).toBeFalsy();
37 | });
38 |
39 | it('programmatically usage', function() {
40 | this.fv = $('#transformerForm')
41 | .formValidation('destroy')
42 | .formValidation({
43 | fields: {
44 | website: {
45 | validators: {
46 | uri: {
47 | transformer: function($field, validator) {
48 | var value = $field.val();
49 | if (value && value.substr(0, 7) !== 'http://' && value.substr(0, 8) !== 'https://') {
50 | value = 'http://' + value;
51 | }
52 | return value;
53 | }
54 | }
55 | }
56 | }
57 | }
58 | })
59 | .data('formValidation');
60 | this.$website.val('foo.com');
61 | this.fv.validate();
62 | expect(this.fv.isValid()).toBeTruthy();
63 |
64 | this.fv.resetForm();
65 | this.$website.val('http://foo.com');
66 | this.fv.validate();
67 | expect(this.fv.isValid()).toBeTruthy();
68 |
69 | this.fv.resetForm();
70 | this.$website.val('https://foo.com');
71 | this.fv.validate();
72 | expect(this.fv.isValid()).toBeTruthy();
73 | });
74 |
75 | it('declarative usage', function() {
76 | this.$website.attr('data-fv-uri-transformer', 'TestSuite.Transformer.uri');
77 |
78 | this.fv = $('#transformerForm')
79 | .formValidation('destroy')
80 | .formValidation()
81 | .data('formValidation');
82 |
83 | this.$website.val('foo.com');
84 | this.fv.validate();
85 | expect(this.fv.isValid()).toBeTruthy();
86 |
87 | this.fv.resetForm();
88 | this.$website.val('http://foo.com');
89 | this.fv.validate();
90 | expect(this.fv.isValid()).toBeTruthy();
91 |
92 | this.fv.resetForm();
93 | this.$website.val('https://foo.com');
94 | this.fv.validate();
95 | expect(this.fv.isValid()).toBeTruthy();
96 | });
97 |
98 | it('update via updateOption()', function() {
99 | this.fv.updateOption('website', 'uri', 'transformer', 'TestSuite.Transformer.uri');
100 |
101 | this.$website.val('foo.com');
102 | this.fv.validate();
103 | expect(this.fv.isValid()).toBeTruthy();
104 |
105 | this.fv.resetForm();
106 | this.$website.val('http://foo.com');
107 | this.fv.validate();
108 | expect(this.fv.isValid()).toBeTruthy();
109 |
110 | this.fv.resetForm();
111 | this.$website.val('https://foo.com');
112 | this.fv.validate();
113 | expect(this.fv.isValid()).toBeTruthy();
114 | });
115 | });
--------------------------------------------------------------------------------
/src/js/validator/emailAddress.js:
--------------------------------------------------------------------------------
1 | /**
2 | * emailAddress validator
3 | *
4 | * @link http://formvalidation.io/validators/emailAddress/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | emailAddress: {
13 | 'default': 'Please enter a valid email address'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.emailAddress = {
19 | html5Attributes: {
20 | message: 'message',
21 | multiple: 'multiple',
22 | separator: 'separator'
23 | },
24 |
25 | enableByHtml5: function($field) {
26 | return ('email' === $field.attr('type'));
27 | },
28 |
29 | /**
30 | * Return true if and only if the input value is a valid email address
31 | *
32 | * @param {FormValidation.Base} validator Validate plugin instance
33 | * @param {jQuery} $field Field element
34 | * @param {Object} [options]
35 | * - multiple: Allow multiple email addresses, separated by a comma or semicolon; default is false.
36 | * - separator: Regex for character or characters expected as separator between addresses; default is comma /[,;]/, i.e. comma or semicolon.
37 | * @returns {Boolean}
38 | */
39 | validate: function(validator, $field, options) {
40 | var value = validator.getFieldValue($field, 'emailAddress');
41 | if (value === '') {
42 | return true;
43 | }
44 |
45 | // Email address regular expression
46 | // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
47 | var emailRegExp = /^(([^<>()[\]\\.,;:\s@\"]+(\.[^<>()[\]\\.,;:\s@\"]+)*)|(\".+\"))@[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?(?:\.[a-zA-Z0-9](?:[a-zA-Z0-9-]{0,61}[a-zA-Z0-9])?)*$/,
48 | allowMultiple = options.multiple === true || options.multiple === 'true';
49 |
50 | if (allowMultiple) {
51 | var separator = options.separator || /[,;]/,
52 | addresses = this._splitEmailAddresses(value, separator);
53 |
54 | for (var i = 0; i < addresses.length; i++) {
55 | if (!emailRegExp.test(addresses[i])) {
56 | return false;
57 | }
58 | }
59 |
60 | return true;
61 | } else {
62 | return emailRegExp.test(value);
63 | }
64 | },
65 |
66 | _splitEmailAddresses: function(emailAddresses, separator) {
67 | var quotedFragments = emailAddresses.split(/"/),
68 | quotedFragmentCount = quotedFragments.length,
69 | emailAddressArray = [],
70 | nextEmailAddress = '';
71 |
72 | for (var i = 0; i < quotedFragmentCount; i++) {
73 | if (i % 2 === 0) {
74 | var splitEmailAddressFragments = quotedFragments[i].split(separator),
75 | splitEmailAddressFragmentCount = splitEmailAddressFragments.length;
76 |
77 | if (splitEmailAddressFragmentCount === 1) {
78 | nextEmailAddress += splitEmailAddressFragments[0];
79 | } else {
80 | emailAddressArray.push(nextEmailAddress + splitEmailAddressFragments[0]);
81 |
82 | for (var j = 1; j < splitEmailAddressFragmentCount - 1; j++) {
83 | emailAddressArray.push(splitEmailAddressFragments[j]);
84 | }
85 | nextEmailAddress = splitEmailAddressFragments[splitEmailAddressFragmentCount - 1];
86 | }
87 | } else {
88 | nextEmailAddress += '"' + quotedFragments[i];
89 | if (i < quotedFragmentCount - 1) {
90 | nextEmailAddress += '"';
91 | }
92 | }
93 | }
94 |
95 | emailAddressArray.push(nextEmailAddress);
96 | return emailAddressArray;
97 | }
98 | };
99 | }(jQuery));
100 |
--------------------------------------------------------------------------------
/test/spec/message.js:
--------------------------------------------------------------------------------
1 | describe('message', function() {
2 | beforeEach(function() {
3 | var html = [
4 | ''
11 | ].join('\n');
12 |
13 | $(html).appendTo('body');
14 | $('#messageForm').formValidation({
15 | fields: {
16 | password: {
17 | validators: {
18 | notEmpty: {
19 | message: 'The password is required'
20 | },
21 | callback: {
22 | callback: function(value, validator) {
23 | // Check the password strength
24 | if (value.length < 6) {
25 | return {
26 | valid: false,
27 | message: 'The password must be more than 6 characters'
28 | }
29 | }
30 |
31 | if (value === value.toLowerCase()) {
32 | return {
33 | valid: false,
34 | message: 'The password must contain at least one upper case character'
35 | }
36 | }
37 | if (value === value.toUpperCase()) {
38 | return {
39 | valid: false,
40 | message: 'The password must contain at least one lower case character'
41 | }
42 | }
43 | if (value.search(/[0-9]/) < 0) {
44 | return {
45 | valid: false,
46 | message: 'The password must contain at least one digit'
47 | }
48 | }
49 |
50 | return true;
51 | }
52 | }
53 | }
54 | }
55 | }
56 | });
57 |
58 | this.fv = $('#messageForm').data('formValidation');
59 | this.$password = this.fv.getFieldElements('password');
60 | });
61 |
62 | afterEach(function() {
63 | $('#messageForm').formValidation('destroy').parent().remove();
64 | });
65 |
66 | it('update message from callback', function() {
67 | this.fv.resetForm();
68 | this.$password.val('123');
69 | this.fv.validate();
70 | expect(this.fv.getMessages('password', 'callback')[0]).toEqual('The password must be more than 6 characters');
71 |
72 | this.fv.resetForm();
73 | this.$password.val('no_upper_case!@#');
74 | this.fv.validate();
75 | expect(this.fv.getMessages('password', 'callback')[0]).toEqual('The password must contain at least one upper case character');
76 |
77 | this.fv.resetForm();
78 | this.$password.val('NO_LOWER_CASE123');
79 | this.fv.validate();
80 | expect(this.fv.getMessages('password', 'callback')[0]).toEqual('The password must contain at least one lower case character');
81 |
82 | this.fv.resetForm();
83 | this.$password.val('NoDigits!@#');
84 | this.fv.validate();
85 | expect(this.fv.getMessages('password', 'callback')[0]).toEqual('The password must contain at least one digit');
86 | });
87 |
88 | it('call updateMessage()', function() {
89 | this.fv.updateStatus('password', this.fv.STATUS_INVALID, 'callback');
90 |
91 | this.fv.updateMessage('password', 'callback', 'The password is weak');
92 | expect(this.fv.getMessages('password', 'callback')[0]).toEqual('The password is weak');
93 |
94 | this.fv.updateMessage(this.$password, 'callback', 'The password is not strong');
95 | expect(this.fv.getMessages(this.$password, 'callback')[0]).toEqual('The password is not strong');
96 | });
97 | });
98 |
--------------------------------------------------------------------------------
/demo/selector2.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | FormValidation demo
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
51 |
52 |
100 |
101 |
--------------------------------------------------------------------------------
/src/js/validator/file.js:
--------------------------------------------------------------------------------
1 | /**
2 | * file validator
3 | *
4 | * @link http://formvalidation.io/validators/file/
5 | * @author https://twitter.com/nghuuphuoc
6 | * @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
7 | * @license http://formvalidation.io/license/
8 | */
9 | (function($) {
10 | FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
11 | 'en_US': {
12 | file: {
13 | 'default': 'Please choose a valid file'
14 | }
15 | }
16 | });
17 |
18 | FormValidation.Validator.file = {
19 | html5Attributes: {
20 | extension: 'extension',
21 | maxfiles: 'maxFiles',
22 | minfiles: 'minFiles',
23 | maxsize: 'maxSize',
24 | minsize: 'minSize',
25 | maxtotalsize: 'maxTotalSize',
26 | mintotalsize: 'minTotalSize',
27 | message: 'message',
28 | type: 'type'
29 | },
30 |
31 | /**
32 | * Validate upload file. Use HTML 5 API if the browser supports
33 | *
34 | * @param {FormValidation.Base} validator The validator plugin instance
35 | * @param {jQuery} $field Field element
36 | * @param {Object} options Can consist of the following keys:
37 | * - extension: The allowed extensions, separated by a comma
38 | * - maxFiles: The maximum number of files
39 | * - minFiles: The minimum number of files
40 | * - maxSize: The maximum size in bytes
41 | * - minSize: The minimum size in bytes
42 | * - maxTotalSize: The maximum size in bytes for all files
43 | * - minTotalSize: The minimum size in bytes for all files
44 | * - message: The invalid message
45 | * - type: The allowed MIME type, separated by a comma
46 | * @returns {Boolean}
47 | */
48 | validate: function(validator, $field, options) {
49 | var value = validator.getFieldValue($field, 'file');
50 | if (value === '') {
51 | return true;
52 | }
53 |
54 | var ext,
55 | extensions = options.extension ? options.extension.toLowerCase().split(',') : null,
56 | types = options.type ? options.type.toLowerCase().split(',') : null,
57 | html5 = (window.File && window.FileList && window.FileReader);
58 |
59 | if (html5) {
60 | // Get FileList instance
61 | var files = $field.get(0).files,
62 | total = files.length,
63 | totalSize = 0;
64 |
65 | if ((options.maxFiles && total > parseInt(options.maxFiles, 10)) // Check the maxFiles
66 | || (options.minFiles && total < parseInt(options.minFiles, 10))) // Check the minFiles
67 | {
68 | return false;
69 | }
70 |
71 | for (var i = 0; i < total; i++) {
72 | totalSize += files[i].size;
73 | ext = files[i].name.substr(files[i].name.lastIndexOf('.') + 1);
74 |
75 | if ((options.minSize && files[i].size < parseInt(options.minSize, 10)) // Check the minSize
76 | || (options.maxSize && files[i].size > parseInt(options.maxSize, 10)) // Check the maxSize
77 | || (extensions && $.inArray(ext.toLowerCase(), extensions) === -1) // Check file extension
78 | || (files[i].type && types && $.inArray(files[i].type.toLowerCase(), types) === -1)) // Check file type
79 | {
80 | return false;
81 | }
82 | }
83 |
84 | if ((options.maxTotalSize && totalSize > parseInt(options.maxTotalSize, 10)) // Check the maxTotalSize
85 | || (options.minTotalSize && totalSize < parseInt(options.minTotalSize, 10))) // Check the minTotalSize
86 | {
87 | return false;
88 | }
89 | } else {
90 | // Check file extension
91 | ext = value.substr(value.lastIndexOf('.') + 1);
92 | if (extensions && $.inArray(ext.toLowerCase(), extensions) === -1) {
93 | return false;
94 | }
95 | }
96 |
97 | return true;
98 | }
99 | };
100 | }(jQuery));
101 |
--------------------------------------------------------------------------------
/test/spec/validator/meid.js:
--------------------------------------------------------------------------------
1 | describe('meid', function() {
2 | beforeEach(function() {
3 | $([
4 | ''
9 | ].join('\n')).appendTo('body');
10 |
11 | $('#meidForm').formValidation();
12 |
13 | this.fv = $('#meidForm').data('formValidation');
14 | this.$meid = this.fv.getFieldElements('meid');
15 | });
16 |
17 | afterEach(function() {
18 | $('#meidForm').formValidation('destroy').remove();
19 | });
20 |
21 | it('Valid MEID (14 hex, check digit)', function() {
22 | this.fv.resetForm();
23 | this.$meid.val('A00000049259B16');
24 | this.fv.validate();
25 | expect(this.fv.isValid()).toBeTruthy();
26 | });
27 |
28 | it('Valid MEID (14 hex, dashes, check digit)', function() {
29 | this.fv.resetForm();
30 | this.$meid.val('A0-000004-9259B1-6');
31 | this.fv.validate();
32 | expect(this.fv.isValid()).toBeTruthy();
33 | });
34 |
35 | it('Valid MEID (14 hex, spaces, check digit)', function() {
36 | this.fv.resetForm();
37 | this.$meid.val('A0 000004 9259B1 6');
38 | this.fv.validate();
39 | expect(this.fv.isValid()).toBeTruthy();
40 | });
41 |
42 | it('Valid MEID (18 dec, check digit)', function() {
43 | this.fv.resetForm();
44 | this.$meid.val('2936087365007037100');
45 | this.fv.validate();
46 | expect(this.fv.isValid()).toBeTruthy();
47 | });
48 |
49 | it('Valid MEID (18 dec, dashes, check digit)', function() {
50 | this.fv.resetForm();
51 | this.$meid.val('29360-87365-0070-3710-0');
52 | this.fv.validate();
53 | expect(this.fv.isValid()).toBeTruthy();
54 | });
55 |
56 | it('Valid MEID (18 dec, spaces, check digit)', function() {
57 | this.fv.resetForm();
58 | this.$meid.val('29360 87365 0070 3710 0');
59 | this.fv.validate();
60 | expect(this.fv.isValid()).toBeTruthy();
61 | });
62 |
63 | it('Valid MEID (14 hex)', function() {
64 | this.fv.resetForm();
65 | this.$meid.val('AF0123450ABCDE');
66 | this.fv.validate();
67 | expect(this.fv.isValid()).toBeTruthy();
68 | });
69 |
70 | it('Valid MEID (14 hex, dashes)', function() {
71 | this.fv.resetForm();
72 | this.$meid.val('AF-012345-0ABCDE');
73 | this.fv.validate();
74 | expect(this.fv.isValid()).toBeTruthy();
75 | });
76 |
77 | it('Valid MEID (14 hex, spaces)', function() {
78 | this.fv.resetForm();
79 | this.$meid.val('AF 012345 0ABCDE');
80 | this.fv.validate();
81 | expect(this.fv.isValid()).toBeTruthy();
82 | });
83 |
84 | it('Valid MEID (18 dec)', function() {
85 | this.fv.resetForm();
86 | this.$meid.val('293608736500703710');
87 | this.fv.validate();
88 | expect(this.fv.isValid()).toBeTruthy();
89 | });
90 |
91 | it('Valid MEID (18 dec, dashes)', function() {
92 | this.fv.resetForm();
93 | this.$meid.val('29360-87365-0070-3710');
94 | this.fv.validate();
95 | expect(this.fv.isValid()).toBeTruthy();
96 | });
97 |
98 | it('Valid MEID (18 dec, spaces)', function() {
99 | this.fv.resetForm();
100 | this.$meid.val('29360 87365 0070 3710');
101 | this.fv.validate();
102 | expect(this.fv.isValid()).toBeTruthy();
103 | });
104 |
105 | it('Invalid MEID (14 hex, bad check digit)', function() {
106 | this.fv.resetForm();
107 | this.$meid.val('A00000049259B15');
108 | this.fv.validate();
109 | expect(this.fv.isValid()).toBeFalsy();
110 | });
111 |
112 | it('Invalid MEID (13 hex)', function() {
113 | this.fv.resetForm();
114 | this.$meid.val('A00000049259B');
115 | this.fv.validate();
116 | expect(this.fv.isValid()).toBeFalsy();
117 | });
118 |
119 | it('Invalid MEID (18 dec, bad check digit)', function() {
120 | this.fv.resetForm();
121 | this.$meid.val('2936087365007037101');
122 | this.fv.validate();
123 | expect(this.fv.isValid()).toBeFalsy();
124 | });
125 |
126 | it('Invalid MEID (17 dec)', function() {
127 | this.fv.resetForm();
128 | this.$meid.val('29360873650070371');
129 | this.fv.validate();
130 | expect(this.fv.isValid()).toBeFalsy();
131 | });
132 | });
133 |
--------------------------------------------------------------------------------
/demo/mailgun.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | FormValidation demo
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
39 |
40 |
104 |
105 |
--------------------------------------------------------------------------------