formvalidation
Version:
The best jQuery plugin to validate form fields. Support Bootstrap, Foundation, Pure, SemanticUI, UIKit and custom frameworks
1,288 lines (1,227 loc) • 56.2 kB
JavaScript
/**
* id validator
*
* @link http://formvalidation.io/validators/id/
* @author https://twitter.com/nghuuphuoc
* @copyright (c) 2013 - 2015 Nguyen Huu Phuoc
* @license http://formvalidation.io/license/
*/
(function($) {
FormValidation.I18n = $.extend(true, FormValidation.I18n || {}, {
'en_US': {
id: {
'default': 'Please enter a valid identification number',
country: 'Please enter a valid identification number in %s',
countries: {
BA: 'Bosnia and Herzegovina',
BG: 'Bulgaria',
BR: 'Brazil',
CH: 'Switzerland',
CL: 'Chile',
CN: 'China',
CZ: 'Czech Republic',
DK: 'Denmark',
EE: 'Estonia',
ES: 'Spain',
FI: 'Finland',
HR: 'Croatia',
IE: 'Ireland',
IS: 'Iceland',
LT: 'Lithuania',
LV: 'Latvia',
ME: 'Montenegro',
MK: 'Macedonia',
NL: 'Netherlands',
PL: 'Poland',
RO: 'Romania',
RS: 'Serbia',
SE: 'Sweden',
SI: 'Slovenia',
SK: 'Slovakia',
SM: 'San Marino',
TH: 'Thailand',
ZA: 'South Africa'
}
}
}
});
FormValidation.Validator.id = {
html5Attributes: {
message: 'message',
country: 'country'
},
// Supported country codes
COUNTRY_CODES: [
'BA', 'BG', 'BR', 'CH', 'CL', 'CN', 'CZ', 'DK', 'EE', 'ES', 'FI', 'HR', 'IE', 'IS', 'LT', 'LV', 'ME', 'MK', 'NL',
'PL', 'RO', 'RS', 'SE', 'SI', 'SK', 'SM', 'TH', 'ZA'
],
/**
* Validate identification number in different countries
*
* @see http://en.wikipedia.org/wiki/National_identification_number
* @param {FormValidation.Base} validator The validator plugin instance
* @param {jQuery} $field Field element
* @param {Object} options Consist of key:
* - message: The invalid message
* - country: The ISO 3166-1 country code. It can be
* - One of country code defined in COUNTRY_CODES
* - Name of field which its value defines the country code
* - Name of callback function that returns the country code
* - A callback function that returns the country code
* @returns {Boolean|Object}
*/
validate: function(validator, $field, options) {
var value = validator.getFieldValue($field, 'id');
if (value === '') {
return true;
}
var locale = validator.getLocale(),
country = options.country;
if (!country) {
country = value.substr(0, 2);
} else if (typeof country !== 'string' || $.inArray(country.toUpperCase(), this.COUNTRY_CODES) === -1) {
// Determine the country code
country = validator.getDynamicOption($field, country);
}
if ($.inArray(country, this.COUNTRY_CODES) === -1) {
return true;
}
var method = ['_', country.toLowerCase()].join('');
return this[method](value)
? true
: {
valid: false,
message: FormValidation.Helper.format(options.message || FormValidation.I18n[locale].id.country, FormValidation.I18n[locale].id.countries[country.toUpperCase()])
};
},
/**
* Validate Unique Master Citizen Number which uses in
* - Bosnia and Herzegovina (country code: BA)
* - Macedonia (MK)
* - Montenegro (ME)
* - Serbia (RS)
* - Slovenia (SI)
*
* @see http://en.wikipedia.org/wiki/Unique_Master_Citizen_Number
* @param {String} value The ID
* @param {String} countryCode The ISO country code, can be BA, MK, ME, RS, SI
* @returns {Boolean}
*/
_validateJMBG: function(value, countryCode) {
if (!/^\d{13}$/.test(value)) {
return false;
}
var day = parseInt(value.substr(0, 2), 10),
month = parseInt(value.substr(2, 2), 10),
year = parseInt(value.substr(4, 3), 10),
rr = parseInt(value.substr(7, 2), 10),
k = parseInt(value.substr(12, 1), 10);
// Validate date of birth
// FIXME: Validate the year of birth
if (day > 31 || month > 12) {
return false;
}
// Validate checksum
var sum = 0;
for (var i = 0; i < 6; i++) {
sum += (7 - i) * (parseInt(value.charAt(i), 10) + parseInt(value.charAt(i + 6), 10));
}
sum = 11 - sum % 11;
if (sum === 10 || sum === 11) {
sum = 0;
}
if (sum !== k) {
return false;
}
// Validate political region
// rr is the political region of birth, which can be in ranges:
// 10-19: Bosnia and Herzegovina
// 20-29: Montenegro
// 30-39: Croatia (not used anymore)
// 41-49: Macedonia
// 50-59: Slovenia (only 50 is used)
// 70-79: Central Serbia
// 80-89: Serbian province of Vojvodina
// 90-99: Kosovo
switch (countryCode.toUpperCase()) {
case 'BA':
return (10 <= rr && rr <= 19);
case 'MK':
return (41 <= rr && rr <= 49);
case 'ME':
return (20 <= rr && rr <= 29);
case 'RS':
return (70 <= rr && rr <= 99);
case 'SI':
return (50 <= rr && rr <= 59);
default:
return true;
}
},
_ba: function(value) {
return this._validateJMBG(value, 'BA');
},
_mk: function(value) {
return this._validateJMBG(value, 'MK');
},
_me: function(value) {
return this._validateJMBG(value, 'ME');
},
_rs: function(value) {
return this._validateJMBG(value, 'RS');
},
/**
* Examples: 0101006500006
*/
_si: function(value) {
return this._validateJMBG(value, 'SI');
},
/**
* Validate Bulgarian national identification number (EGN)
* Examples:
* - Valid: 7523169263, 8032056031, 803205 603 1, 8001010008, 7501020018, 7552010005, 7542011030
* - Invalid: 8019010008
*
* @see http://en.wikipedia.org/wiki/Uniform_civil_number
* @param {String} value The ID
* @returns {Boolean}
*/
_bg: function(value) {
if (!/^\d{10}$/.test(value) && !/^\d{6}\s\d{3}\s\d{1}$/.test(value)) {
return false;
}
value = value.replace(/\s/g, '');
// Check the birth date
var year = parseInt(value.substr(0, 2), 10) + 1900,
month = parseInt(value.substr(2, 2), 10),
day = parseInt(value.substr(4, 2), 10);
if (month > 40) {
year += 100;
month -= 40;
} else if (month > 20) {
year -= 100;
month -= 20;
}
if (!FormValidation.Helper.date(year, month, day)) {
return false;
}
var sum = 0,
weight = [2, 4, 8, 5, 10, 9, 7, 3, 6];
for (var i = 0; i < 9; i++) {
sum += parseInt(value.charAt(i), 10) * weight[i];
}
sum = (sum % 11) % 10;
return (sum + '' === value.substr(9, 1));
},
/**
* Validate Brazilian national identification number (CPF)
* Examples:
* - Valid: 39053344705, 390.533.447-05, 111.444.777-35
* - Invalid: 231.002.999-00
*
* @see http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas
* @param {String} value The ID
* @returns {Boolean}
*/
_br: function(value) {
value = value.replace(/\D/g, '');
if (!/^\d{11}$/.test(value) || /^1{11}|2{11}|3{11}|4{11}|5{11}|6{11}|7{11}|8{11}|9{11}|0{11}$/.test(value)) {
return false;
}
var d1 = 0;
for (var i = 0; i < 9; i++) {
d1 += (10 - i) * parseInt(value.charAt(i), 10);
}
d1 = 11 - d1 % 11;
if (d1 === 10 || d1 === 11) {
d1 = 0;
}
if (d1 + '' !== value.charAt(9)) {
return false;
}
var d2 = 0;
for (i = 0; i < 10; i++) {
d2 += (11 - i) * parseInt(value.charAt(i), 10);
}
d2 = 11 - d2 % 11;
if (d2 === 10 || d2 === 11) {
d2 = 0;
}
return (d2 + '' === value.charAt(10));
},
/**
* Validate Swiss Social Security Number (AHV-Nr/No AVS)
* Examples:
* - Valid: 756.1234.5678.95, 7561234567895
*
* @see http://en.wikipedia.org/wiki/National_identification_number#Switzerland
* @see http://www.bsv.admin.ch/themen/ahv/00011/02185/index.html?lang=de
* @param {String} value The ID
* @returns {Boolean}
*/
_ch: function(value) {
if (!/^756[\.]{0,1}[0-9]{4}[\.]{0,1}[0-9]{4}[\.]{0,1}[0-9]{2}$/.test(value)) {
return false;
}
value = value.replace(/\D/g, '').substr(3);
var length = value.length,
sum = 0,
weight = (length === 8) ? [3, 1] : [1, 3];
for (var i = 0; i < length - 1; i++) {
sum += parseInt(value.charAt(i), 10) * weight[i % 2];
}
sum = 10 - sum % 10;
return (sum + '' === value.charAt(length - 1));
},
/**
* Validate Chilean national identification number (RUN/RUT)
* Examples:
* - Valid: 76086428-5, 22060449-7, 12531909-2
*
* @see http://en.wikipedia.org/wiki/National_identification_number#Chile
* @see https://palena.sii.cl/cvc/dte/ee_empresas_emisoras.html for samples
* @param {String} value The ID
* @returns {Boolean}
*/
_cl: function(value) {
if (!/^\d{7,8}[-]{0,1}[0-9K]$/i.test(value)) {
return false;
}
value = value.replace(/\-/g, '');
while (value.length < 9) {
value = '0' + value;
}
var sum = 0,
weight = [3, 2, 7, 6, 5, 4, 3, 2];
for (var i = 0; i < 8; i++) {
sum += parseInt(value.charAt(i), 10) * weight[i];
}
sum = 11 - sum % 11;
if (sum === 11) {
sum = 0;
} else if (sum === 10) {
sum = 'K';
}
return sum + '' === value.charAt(8).toUpperCase();
},
/**
* Validate Chinese citizen identification number
*
* Rules:
* - For current 18-digit system (since 1st Oct 1999, defined by GB11643—1999 national standard):
* - Digit 0-5: Must be a valid administrative division code of China PR.
* - Digit 6-13: Must be a valid YYYYMMDD date of birth. A future date is tolerated.
* - Digit 14-16: Order code, any integer.
* - Digit 17: An ISO 7064:1983, MOD 11-2 checksum.
* Both upper/lower case of X are tolerated.
* - For deprecated 15-digit system:
* - Digit 0-5: Must be a valid administrative division code of China PR.
* - Digit 6-11: Must be a valid YYMMDD date of birth, indicating the year of 19XX.
* - Digit 12-14: Order code, any integer.
* Lists of valid administrative division codes of China PR can be seen here:
* <http://www.stats.gov.cn/tjsj/tjbz/xzqhdm/>
* Published and maintained by National Bureau of Statistics of China PR.
* NOTE: Current and deprecated codes MUST BOTH be considered valid.
* Many Chinese citizens born in once existed administrative divisions!
*
* @see http://en.wikipedia.org/wiki/Resident_Identity_Card#Identity_card_number
* @param {String} value The ID
* @returns {Boolean}
*/
_cn: function(value) {
// Basic format check (18 or 15 digits, considering X in checksum)
value = value.trim();
if (!/^\d{15}$/.test(value) && !/^\d{17}[\dXx]{1}$/.test(value)) {
return false;
}
// Check China PR Administrative division code
var adminDivisionCodes = {
11: {
0: [0],
1: [[0, 9], [11, 17]],
2: [0, 28, 29]
},
12: {
0: [0],
1: [[0, 16]],
2: [0, 21, 23, 25]
},
13: {
0: [0],
1: [[0, 5], 7, 8, 21, [23, 33], [81, 85]],
2: [[0, 5], [7, 9], [23, 25], 27, 29, 30, 81, 83],
3: [[0, 4], [21, 24]],
4: [[0, 4], 6, 21, [23, 35], 81],
5: [[0, 3], [21, 35], 81, 82],
6: [[0, 4], [21, 38], [81, 84]],
7: [[0, 3], 5, 6, [21, 33]],
8: [[0, 4], [21, 28]],
9: [[0, 3], [21, 30], [81, 84]],
10: [[0, 3], [22, 26], 28, 81, 82],
11: [[0, 2], [21, 28], 81, 82]
},
14: {
0: [0],
1: [0, 1, [5, 10], [21, 23], 81],
2: [[0, 3], 11, 12, [21, 27]],
3: [[0, 3], 11, 21, 22],
4: [[0, 2], 11, 21, [23, 31], 81],
5: [[0, 2], 21, 22, 24, 25, 81],
6: [[0, 3], [21, 24]],
7: [[0, 2], [21, 29], 81],
8: [[0, 2], [21, 30], 81, 82],
9: [[0, 2], [21, 32], 81],
10: [[0, 2], [21, 34], 81, 82],
11: [[0, 2], [21, 30], 81, 82],
23: [[0, 3], 22, 23, [25, 30], 32, 33]
},
15: {
0: [0],
1: [[0, 5], [21, 25]],
2: [[0, 7], [21, 23]],
3: [[0, 4]],
4: [[0, 4], [21, 26], [28, 30]],
5: [[0, 2], [21, 26], 81],
6: [[0, 2], [21, 27]],
7: [[0, 3], [21, 27], [81, 85]],
8: [[0, 2], [21, 26]],
9: [[0, 2], [21, 29], 81],
22: [[0, 2], [21, 24]],
25: [[0, 2], [22, 31]],
26: [[0, 2], [24, 27], [29, 32], 34],
28: [0, 1, [22, 27]],
29: [0, [21, 23]]
},
21: {
0: [0],
1: [[0, 6], [11, 14], [22, 24], 81],
2: [[0, 4], [11, 13], 24, [81, 83]],
3: [[0, 4], 11, 21, 23, 81],
4: [[0, 4], 11, [21, 23]],
5: [[0, 5], 21, 22],
6: [[0, 4], 24, 81, 82],
7: [[0, 3], 11, 26, 27, 81, 82],
8: [[0, 4], 11, 81, 82],
9: [[0, 5], 11, 21, 22],
10: [[0, 5], 11, 21, 81],
11: [[0, 3], 21, 22],
12: [[0, 2], 4, 21, 23, 24, 81, 82],
13: [[0, 3], 21, 22, 24, 81, 82],
14: [[0, 4], 21, 22, 81]
},
22: {
0: [0],
1: [[0, 6], 12, 22, [81, 83]],
2: [[0, 4], 11, 21, [81, 84]],
3: [[0, 3], 22, 23, 81, 82],
4: [[0, 3], 21, 22],
5: [[0, 3], 21, 23, 24, 81, 82],
6: [[0, 2], 4, 5, [21, 23], 25, 81],
7: [[0, 2], [21, 24], 81],
8: [[0, 2], 21, 22, 81, 82],
24: [[0, 6], 24, 26]
},
23: {
0: [0],
1: [[0, 12], 21, [23, 29], [81, 84]],
2: [[0, 8], 21, [23, 25], 27, [29, 31], 81],
3: [[0, 7], 21, 81, 82],
4: [[0, 7], 21, 22],
5: [[0, 3], 5, 6, [21, 24]],
6: [[0, 6], [21, 24]],
7: [[0, 16], 22, 81],
8: [[0, 5], 11, 22, 26, 28, 33, 81, 82],
9: [[0, 4], 21],
10: [[0, 5], 24, 25, 81, [83, 85]],
11: [[0, 2], 21, 23, 24, 81, 82],
12: [[0, 2], [21, 26], [81, 83]],
27: [[0, 4], [21, 23]]
},
31: {
0: [0],
1: [0, 1, [3, 10], [12, 20]],
2: [0, 30]
},
32: {
0: [0],
1: [[0, 7], 11, [13, 18], 24, 25],
2: [[0, 6], 11, 81, 82],
3: [[0, 5], 11, 12, [21, 24], 81, 82],
4: [[0, 2], 4, 5, 11, 12, 81, 82],
5: [[0, 9], [81, 85]],
6: [[0, 2], 11, 12, 21, 23, [81, 84]],
7: [0, 1, 3, 5, 6, [21, 24]],
8: [[0, 4], 11, 26, [29, 31]],
9: [[0, 3], [21, 25], 28, 81, 82],
10: [[0, 3], 11, 12, 23, 81, 84, 88],
11: [[0, 2], 11, 12, [81, 83]],
12: [[0, 4], [81, 84]],
13: [[0, 2], 11, [21, 24]]
},
33: {
0: [0],
1: [[0, 6], [8, 10], 22, 27, 82, 83, 85],
2: [0, 1, [3, 6], 11, 12, 25, 26, [81, 83]],
3: [[0, 4], 22, 24, [26, 29], 81, 82],
4: [[0, 2], 11, 21, 24, [81, 83]],
5: [[0, 3], [21, 23]],
6: [[0, 2], 21, 24, [81, 83]],
7: [[0, 3], 23, 26, 27, [81, 84]],
8: [[0, 3], 22, 24, 25, 81],
9: [[0, 3], 21, 22],
10: [[0, 4], [21, 24], 81, 82],
11: [[0, 2], [21, 27], 81]
},
34: {
0: [0],
1: [[0, 4], 11, [21, 24], 81],
2: [[0, 4], 7, 8, [21, 23], 25],
3: [[0, 4], 11, [21, 23]],
4: [[0, 6], 21],
5: [[0, 4], 6, [21, 23]],
6: [[0, 4], 21],
7: [[0, 3], 11, 21],
8: [[0, 3], 11, [22, 28], 81],
10: [[0, 4], [21, 24]],
11: [[0, 3], 22, [24, 26], 81, 82],
12: [[0, 4], 21, 22, 25, 26, 82],
13: [[0, 2], [21, 24]],
14: [[0, 2], [21, 24]],
15: [[0, 3], [21, 25]],
16: [[0, 2], [21, 23]],
17: [[0, 2], [21, 23]],
18: [[0, 2], [21, 25], 81]
},
35: {
0: [0],
1: [[0, 5], 11, [21, 25], 28, 81, 82],
2: [[0, 6], [11, 13]],
3: [[0, 5], 22],
4: [[0, 3], 21, [23, 30], 81],
5: [[0, 5], 21, [24, 27], [81, 83]],
6: [[0, 3], [22, 29], 81],
7: [[0, 2], [21, 25], [81, 84]],
8: [[0, 2], [21, 25], 81],
9: [[0, 2], [21, 26], 81, 82]
},
36: {
0: [0],
1: [[0, 5], 11, [21, 24]],
2: [[0, 3], 22, 81],
3: [[0, 2], 13, [21, 23]],
4: [[0, 3], 21, [23, 30], 81, 82],
5: [[0, 2], 21],
6: [[0, 2], 22, 81],
7: [[0, 2], [21, 35], 81, 82],
8: [[0, 3], [21, 30], 81],
9: [[0, 2], [21, 26], [81, 83]],
10: [[0, 2], [21, 30]],
11: [[0, 2], [21, 30], 81]
},
37: {
0: [0],
1: [[0, 5], 12, 13, [24, 26], 81],
2: [[0, 3], 5, [11, 14], [81, 85]],
3: [[0, 6], [21, 23]],
4: [[0, 6], 81],
5: [[0, 3], [21, 23]],
6: [[0, 2], [11, 13], 34, [81, 87]],
7: [[0, 5], 24, 25, [81, 86]],
8: [[0, 2], 11, [26, 32], [81, 83]],
9: [[0, 3], 11, 21, 23, 82, 83],
10: [[0, 2], [81, 83]],
11: [[0, 3], 21, 22],
12: [[0, 3]],
13: [[0, 2], 11, 12, [21, 29]],
14: [[0, 2], [21, 28], 81, 82],
15: [[0, 2], [21, 26], 81],
16: [[0, 2], [21, 26]],
17: [[0, 2], [21, 28]]
},
41: {
0: [0],
1: [[0, 6], 8, 22, [81, 85]],
2: [[0, 5], 11, [21, 25]],
3: [[0, 7], 11, [22, 29], 81],
4: [[0, 4], 11, [21, 23], 25, 81, 82],
5: [[0, 3], 5, 6, 22, 23, 26, 27, 81],
6: [[0, 3], 11, 21, 22],
7: [[0, 4], 11, 21, [24, 28], 81, 82],
8: [[0, 4], 11, [21, 23], 25, [81, 83]],
9: [[0, 2], 22, 23, [26, 28]],
10: [[0, 2], [23, 25], 81, 82],
11: [[0, 4], [21, 23]],
12: [[0, 2], 21, 22, 24, 81, 82],
13: [[0, 3], [21, 30], 81],
14: [[0, 3], [21, 26], 81],
15: [[0, 3], [21, 28]],
16: [[0, 2], [21, 28], 81],
17: [[0, 2], [21, 29]],
90: [0, 1]
},
42: {
0: [0],
1: [[0, 7], [11, 17]],
2: [[0, 5], 22, 81],
3: [[0, 3], [21, 25], 81],
5: [[0, 6], [25, 29], [81, 83]],
6: [[0, 2], 6, 7, [24, 26], [82, 84]],
7: [[0, 4]],
8: [[0, 2], 4, 21, 22, 81],
9: [[0, 2], [21, 23], 81, 82, 84],
10: [[0, 3], [22, 24], 81, 83, 87],
11: [[0, 2], [21, 27], 81, 82],
12: [[0, 2], [21, 24], 81],
13: [[0, 3], 21, 81],
28: [[0, 2], 22, 23, [25, 28]],
90: [0, [4, 6], 21]
},
43: {
0: [0],
1: [[0, 5], 11, 12, 21, 22, 24, 81],
2: [[0, 4], 11, 21, [23, 25], 81],
3: [[0, 2], 4, 21, 81, 82],
4: [0, 1, [5, 8], 12, [21, 24], 26, 81, 82],
5: [[0, 3], 11, [21, 25], [27, 29], 81],
6: [[0, 3], 11, 21, 23, 24, 26, 81, 82],
7: [[0, 3], [21, 26], 81],
8: [[0, 2], 11, 21, 22],
9: [[0, 3], [21, 23], 81],
10: [[0, 3], [21, 28], 81],
11: [[0, 3], [21, 29]],
12: [[0, 2], [21, 30], 81],
13: [[0, 2], 21, 22, 81, 82],
31: [0, 1, [22, 27], 30]
},
44: {
0: [0],
1: [[0, 7], [11, 16], 83, 84],
2: [[0, 5], 21, 22, 24, 29, 32, 33, 81, 82],
3: [0, 1, [3, 8]],
4: [[0, 4]],
5: [0, 1, [6, 15], 23, 82, 83],
6: [0, 1, [4, 8]],
7: [0, 1, [3, 5], 81, [83, 85]],
8: [[0, 4], 11, 23, 25, [81, 83]],
9: [[0, 3], 23, [81, 83]],
12: [[0, 3], [23, 26], 83, 84],
13: [[0, 3], [22, 24], 81],
14: [[0, 2], [21, 24], 26, 27, 81],
15: [[0, 2], 21, 23, 81],
16: [[0, 2], [21, 25]],
17: [[0, 2], 21, 23, 81],
18: [[0, 3], 21, 23, [25, 27], 81, 82],
19: [0],
20: [0],
51: [[0, 3], 21, 22],
52: [[0, 3], 21, 22, 24, 81],
53: [[0, 2], [21, 23], 81]
},
45: {
0: [0],
1: [[0, 9], [21, 27]],
2: [[0, 5], [21, 26]],
3: [[0, 5], 11, 12, [21, 32]],
4: [0, 1, [3, 6], 11, [21, 23], 81],
5: [[0, 3], 12, 21],
6: [[0, 3], 21, 81],
7: [[0, 3], 21, 22],
8: [[0, 4], 21, 81],
9: [[0, 3], [21, 24], 81],
10: [[0, 2], [21, 31]],
11: [[0, 2], [21, 23]],
12: [[0, 2], [21, 29], 81],
13: [[0, 2], [21, 24], 81],
14: [[0, 2], [21, 25], 81]
},
46: {
0: [0],
1: [0, 1, [5, 8]],
2: [0, 1],
3: [0, [21, 23]],
90: [[0, 3], [5, 7], [21, 39]]
},
50: {
0: [0],
1: [[0, 19]],
2: [0, [22, 38], [40, 43]],
3: [0, [81, 84]]
},
51: {
0: [0],
1: [0, 1, [4, 8], [12, 15], [21, 24], 29, 31, 32, [81, 84]],
3: [[0, 4], 11, 21, 22],
4: [[0, 3], 11, 21, 22],
5: [[0, 4], 21, 22, 24, 25],
6: [0, 1, 3, 23, 26, [81, 83]],
7: [0, 1, 3, 4, [22, 27], 81],
8: [[0, 2], 11, 12, [21, 24]],
9: [[0, 4], [21, 23]],
10: [[0, 2], 11, 24, 25, 28],
11: [[0, 2], [11, 13], 23, 24, 26, 29, 32, 33, 81],
13: [[0, 4], [21, 25], 81],
14: [[0, 2], [21, 25]],
15: [[0, 3], [21, 29]],
16: [[0, 3], [21, 23], 81],
17: [[0, 3], [21, 25], 81],
18: [[0, 3], [21, 27]],
19: [[0, 3], [21, 23]],
20: [[0, 2], 21, 22, 81],
32: [0, [21, 33]],
33: [0, [21, 38]],
34: [0, 1, [22, 37]]
},
52: {
0: [0],
1: [[0, 3], [11, 15], [21, 23], 81],
2: [0, 1, 3, 21, 22],
3: [[0, 3], [21, 30], 81, 82],
4: [[0, 2], [21, 25]],
5: [[0, 2], [21, 27]],
6: [[0, 3], [21, 28]],
22: [0, 1, [22, 30]],
23: [0, 1, [22, 28]],
24: [0, 1, [22, 28]],
26: [0, 1, [22, 36]],
27: [[0, 2], 22, 23, [25, 32]]
},
53: {
0: [0],
1: [[0, 3], [11, 14], 21, 22, [24, 29], 81],
3: [[0, 2], [21, 26], 28, 81],
4: [[0, 2], [21, 28]],
5: [[0, 2], [21, 24]],
6: [[0, 2], [21, 30]],
7: [[0, 2], [21, 24]],
8: [[0, 2], [21, 29]],
9: [[0, 2], [21, 27]],
23: [0, 1, [22, 29], 31],
25: [[0, 4], [22, 32]],
26: [0, 1, [21, 28]],
27: [0, 1, [22, 30]], 28: [0, 1, 22, 23],
29: [0, 1, [22, 32]],
31: [0, 2, 3, [22, 24]],
34: [0, [21, 23]],
33: [0, 21, [23, 25]],
35: [0, [21, 28]]
},
54: {
0: [0],
1: [[0, 2], [21, 27]],
21: [0, [21, 29], 32, 33],
22: [0, [21, 29], [31, 33]],
23: [0, 1, [22, 38]],
24: [0, [21, 31]],
25: [0, [21, 27]],
26: [0, [21, 27]]
},
61: {
0: [0],
1: [[0, 4], [11, 16], 22, [24, 26]],
2: [[0, 4], 22],
3: [[0, 4], [21, 24], [26, 31]],
4: [[0, 4], [22, 31], 81],
5: [[0, 2], [21, 28], 81, 82],
6: [[0, 2], [21, 32]],
7: [[0, 2], [21, 30]],
8: [[0, 2], [21, 31]],
9: [[0, 2], [21, 29]],
10: [[0, 2], [21, 26]]
},
62: {
0: [0],
1: [[0, 5], 11, [21, 23]],
2: [0, 1],
3: [[0, 2], 21],
4: [[0, 3], [21, 23]],
5: [[0, 3], [21, 25]],
6: [[0, 2], [21, 23]],
7: [[0, 2], [21, 25]],
8: [[0, 2], [21, 26]],
9: [[0, 2], [21, 24], 81, 82],
10: [[0, 2], [21, 27]],
11: [[0, 2], [21, 26]],
12: [[0, 2], [21, 28]],
24: [0, 21, [24, 29]],
26: [0, 21, [23, 30]],
29: [0, 1, [21, 27]],
30: [0, 1, [21, 27]]
},
63: {
0: [0],
1: [[0, 5], [21, 23]],
2: [0, 2, [21, 25]],
21: [0, [21, 23], [26, 28]],
22: [0, [21, 24]],
23: [0, [21, 24]],
25: [0, [21, 25]],
26: [0, [21, 26]],
27: [0, 1, [21, 26]],
28: [[0, 2], [21, 23]]
},
64: {
0: [0],
1: [0, 1, [4, 6], 21, 22, 81],
2: [[0, 3], 5, [21, 23]],
3: [[0, 3], [21, 24], 81],
4: [[0, 2], [21, 25]],
5: [[0, 2], 21, 22]
},
65: {
0: [0],
1: [[0, 9], 21],
2: [[0, 5]],
21: [0, 1, 22, 23],
22: [0, 1, 22, 23],
23: [[0, 3], [23, 25], 27, 28],
28: [0, 1, [22, 29]],
29: [0, 1, [22, 29]],
30: [0, 1, [22, 24]], 31: [0, 1, [21, 31]],
32: [0, 1, [21, 27]],
40: [0, 2, 3, [21, 28]],
42: [[0, 2], 21, [23, 26]],
43: [0, 1, [21, 26]],
90: [[0, 4]], 27: [[0, 2], 22, 23]
},
71: { 0: [0] },
81: { 0: [0] },
82: { 0: [0] }
};
var provincial = parseInt(value.substr(0, 2), 10),
prefectural = parseInt(value.substr(2, 2), 10),
county = parseInt(value.substr(4, 2), 10);
if (!adminDivisionCodes[provincial] || !adminDivisionCodes[provincial][prefectural]) {
return false;
}
var inRange = false,
rangeDef = adminDivisionCodes[provincial][prefectural];
for (var i = 0; i < rangeDef.length; i++) {
if (($.isArray(rangeDef[i]) && rangeDef[i][0] <= county && county <= rangeDef[i][1])
|| (!$.isArray(rangeDef[i]) && county === rangeDef[i]))
{
inRange = true;
break;
}
}
if (!inRange) {
return false;
}
// Check date of birth
var dob;
if (value.length === 18) {
dob = value.substr(6, 8);
} else /* length == 15 */ {
dob = '19' + value.substr(6, 6);
}
var year = parseInt(dob.substr(0, 4), 10),
month = parseInt(dob.substr(4, 2), 10),
day = parseInt(dob.substr(6, 2), 10);
if (!FormValidation.Helper.date(year, month, day)) {
return false;
}
// Check checksum (18-digit system only)
if (value.length === 18) {
var sum = 0,
weight = [7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2];
for (i = 0; i < 17; i++) {
sum += parseInt(value.charAt(i), 10) * weight[i];
}
sum = (12 - (sum % 11)) % 11;
var checksum = (value.charAt(17).toUpperCase() !== 'X') ? parseInt(value.charAt(17), 10) : 10;
return checksum === sum;
}
return true;
},
/**
* Validate Czech national identification number (RC)
* Examples:
* - Valid: 7103192745, 991231123
* - Invalid: 1103492745, 590312123
*
* @param {String} value The ID
* @returns {Boolean}
*/
_cz: function(value) {
if (!/^\d{9,10}$/.test(value)) {
return false;
}
var year = 1900 + parseInt(value.substr(0, 2), 10),
month = parseInt(value.substr(2, 2), 10) % 50 % 20,
day = parseInt(value.substr(4, 2), 10);
if (value.length === 9) {
if (year >= 1980) {
year -= 100;
}
if (year > 1953) {
return false;
}
} else if (year < 1954) {
year += 100;
}
if (!FormValidation.Helper.date(year, month, day)) {
return false;
}
// Check that the birth date is not in the future
if (value.length === 10) {
var check = parseInt(value.substr(0, 9), 10) % 11;
if (year < 1985) {
check = check % 10;
}
return (check + '' === value.substr(9, 1));
}
return true;
},
/**
* Validate Danish Personal Identification number (CPR)
* Examples:
* - Valid: 2110625629, 211062-5629
* - Invalid: 511062-5629
*
* @see https://en.wikipedia.org/wiki/Personal_identification_number_(Denmark)
* @param {String} value The ID
* @returns {Boolean}
*/
_dk: function(value) {
if (!/^[0-9]{6}[-]{0,1}[0-9]{4}$/.test(value)) {
return false;
}
value = value.replace(/-/g, '');
var day = parseInt(value.substr(0, 2), 10),
month = parseInt(value.substr(2, 2), 10),
year = parseInt(value.substr(4, 2), 10);
switch (true) {
case ('5678'.indexOf(value.charAt(6)) !== -1 && year >= 58):
year += 1800;
break;
case ('0123'.indexOf(value.charAt(6)) !== -1):
case ('49'.indexOf(value.charAt(6)) !== -1 && year >= 37):
year += 1900;
break;
default:
year += 2000;
break;
}
return FormValidation.Helper.date(year, month, day);
},
/**
* Validate Estonian Personal Identification Code (isikukood)
* Examples:
* - Valid: 37605030299
*
* @see http://et.wikipedia.org/wiki/Isikukood
* @param {String} value The ID
* @returns {Boolean}
*/
_ee: function(value) {
// Use the same format as Lithuanian Personal Code
return this._lt(value);
},
/**
* Validate Spanish personal identity code (DNI)
* Support i) DNI (for Spanish citizens), ii) NIE (for foreign people)
* and iii) CIF (for legal entities)
*
* Examples:
* - Valid:
* i) 54362315K, 54362315-K
* ii) X2482300W, X-2482300W, X-2482300-W
* iii) A58818501, A-58818501
* - Invalid:
* i) 54362315Z
* ii) X-2482300A
* iii) K58818501, G58818507
*
* @see https://en.wikipedia.org/wiki/National_identification_number#Spain
* @param {String} value The ID
* @returns {Boolean}
*/
_es: function(value) {
var isDNI = /^[0-9]{8}[-]{0,1}[A-HJ-NP-TV-Z]$/.test(value),
isNIE = /^[XYZ][-]{0,1}[0-9]{7}[-]{0,1}[A-HJ-NP-TV-Z]$/.test(value),
isCIF = /^[A-HNPQS][-]{0,1}[0-9]{7}[-]{0,1}[0-9A-J]$/.test(value);
if (!isDNI && !isNIE && !isCIF) {
return false;
}
value = value.replace(/-/g, '');
var check;
if (isDNI || isNIE) {
var index = 'XYZ'.indexOf(value.charAt(0));
if (index !== -1) {
// It is NIE number
value = index + value.substr(1) + '';
}
check = parseInt(value.substr(0, 8), 10);
check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23];
return (check === value.substr(8, 1));
} else {
check = value.substr(1, 7);
var letter = value[0],
control = value.substr(-1),
sum = 0;
// The digits in the even positions are added to the sum directly.
// The ones in the odd positions are multiplied by 2 and then added to the sum.
// If the result of multiplying by 2 is 10 or higher, add the two digits
// together and add that to the sum instead
for (var i = 0; i < check.length; i++) {
if (i % 2 !== 0) {
sum += parseInt(check[i], 10);
} else {
var tmp = '' + (parseInt(check[i], 10) * 2);
sum += parseInt(tmp[0], 10);
if (tmp.length === 2) {
sum += parseInt(tmp[1], 10);
}
}
}
// The control digit is calculated from the last digit of the sum.
// If that last digit is not 0, subtract it from 10
var lastDigit = sum - (Math.floor(sum / 10) * 10);
if (lastDigit !== 0) {
lastDigit = 10 - lastDigit;
}
if ('KQS'.indexOf(letter) !== -1) {
// If the CIF starts with a K, Q or S, the control digit must be a letter
return (control === 'JABCDEFGHI'[lastDigit]);
} else if ('ABEH'.indexOf(letter) !== -1) {
// If it starts with A, B, E or H, it has to be a number
return (control === ('' + lastDigit));
} else {
// In any other case, it doesn't matter
return (control === ('' + lastDigit) || control === 'JABCDEFGHI'[lastDigit]);
}
}
},
/**
* Validate Finnish Personal Identity Code (HETU)
* Examples:
* - Valid: 311280-888Y, 131052-308T
* - Invalid: 131052-308U, 310252-308Y
*
* @param {String} value The ID
* @returns {Boolean}
*/
_fi: function(value) {
if (!/^[0-9]{6}[-+A][0-9]{3}[0-9ABCDEFHJKLMNPRSTUVWXY]$/.test(value)) {
return false;
}
var day = parseInt(value.substr(0, 2), 10),
month = parseInt(value.substr(2, 2), 10),
year = parseInt(value.substr(4, 2), 10),
centuries = {
'+': 1800,
'-': 1900,
'A': 2000
};
year = centuries[value.charAt(6)] + year;
if (!FormValidation.Helper.date(year, month, day)) {
return false;
}
var individual = parseInt(value.substr(7, 3), 10);
if (individual < 2) {
return false;
}
var n = value.substr(0, 6) + value.substr(7, 3) + '';
n = parseInt(n, 10);
return '0123456789ABCDEFHJKLMNPRSTUVWXY'.charAt(n % 31) === value.charAt(10);
},
/**
* Validate Croatian personal identification number (OIB)
* Examples:
* - Valid: 33392005961
* - Invalid: 33392005962
*
* @param {String} value The ID
* @returns {Boolean}
*/
_hr: function(value) {
if (!/^[0-9]{11}$/.test(value)) {
return false;
}
return FormValidation.Helper.mod11And10(value);
},
/**
* Validate Irish Personal Public Service Number (PPS)
* Examples:
* - Valid: 6433435F, 6433435FT, 6433435FW, 6433435OA, 6433435IH, 1234567TW, 1234567FA
* - Invalid: 6433435E, 6433435VH
*
* @see https://en.wikipedia.org/wiki/Personal_Public_Service_Number
* @param {String} value The ID
* @returns {Boolean}
*/
_ie: function(value) {
if (!/^\d{7}[A-W][AHWTX]?$/.test(value)) {
return false;
}
var getCheckDigit = function(value) {
while (value.length < 7) {
value = '0' + value;
}
var alphabet = 'WABCDEFGHIJKLMNOPQRSTUV',
sum = 0;
for (var i = 0; i < 7; i++) {
sum += parseInt(value.charAt(i), 10) * (8 - i);
}
sum += 9 * alphabet.indexOf(value.substr(7));
return alphabet[sum % 23];
};
// 2013 format
if (value.length === 9 && ('A' === value.charAt(8) || 'H' === value.charAt(8))) {
return value.charAt(7) === getCheckDigit(value.substr(0, 7) + value.substr(8) + '');
}
// The old format
else {
return value.charAt(7) === getCheckDigit(value.substr(0, 7));
}
},
/**
* Validate Iceland national identification number (Kennitala)
* Examples:
* - Valid: 120174-3399, 1201743399, 0902862349
*
* @see http://en.wikipedia.org/wiki/Kennitala
* @param {String} value The ID
* @returns {Boolean}
*/
_is: function(value) {
if (!/^[0-9]{6}[-]{0,1}[0-9]{4}$/.test(value)) {
return false;
}
value = value.replace(/-/g, '');
var day = parseInt(value.substr(0, 2), 10),
month = parseInt(value.substr(2, 2), 10),
year = parseInt(value.substr(4, 2), 10),
century = parseInt(value.charAt(9), 10);
year = (century === 9) ? (1900 + year) : ((20 + century) * 100 + year);
if (!FormValidation.Helper.date(year, month, day, true)) {
return false;
}
// Validate the check digit
var sum = 0,
weight = [3, 2, 7, 6, 5, 4, 3, 2];
for (var i = 0; i < 8; i++) {
sum += parseInt(value.charAt(i), 10) * weight[i];
}
sum = 11 - sum % 11;
return (sum + '' === value.charAt(8));
},
/**
* Validate Lithuanian Personal Code (Asmens kodas)
* Examples:
* - Valid: 38703181745
* - Invalid: 38703181746, 78703181745, 38703421745
*
* @see http://en.wikipedia.org/wiki/National_identification_number#Lithuania
* @see http://www.adomas.org/midi2007/pcode.html
* @param {String} value The ID
* @returns {Boolean}
*/
_lt: function(value) {
if (!/^[0-9]{11}$/.test(value)) {
return false;
}
var gender = parseInt(value.charAt(0), 10),
year = parseInt(value.substr(1, 2), 10),
month = parseInt(value.substr(3, 2), 10),
day = parseInt(value.substr(5, 2), 10),
century = (gender % 2 === 0) ? (17 + gender / 2) : (17 + (gender + 1) / 2);
year = century * 100 + year;
if (!FormValidation.Helper.date(year, month, day, true)) {
return false;
}
// Validate the check digit
var sum = 0,
weight = [1, 2, 3, 4, 5, 6, 7, 8, 9, 1];
for (var i = 0; i < 10; i++) {
sum += parseInt(value.charAt(i), 10) * weight[i];
}
sum = sum % 11;
if (sum !== 10) {
return sum + '' === value.charAt(10);
}
// Re-calculate the check digit
sum = 0;
weight = [3, 4, 5, 6, 7, 8, 9, 1, 2, 3];
for (i = 0; i < 10; i++) {
sum += parseInt(value.charAt(i), 10) * weight[i];
}
sum = sum % 11;
if (sum === 10) {
sum = 0;
}
return (sum + '' === value.charAt(10));
},
/**
* Validate Latvian Personal Code (Personas kods)
* Examples:
* - Valid: 161175-19997, 16117519997
* - Invalid: 161375-19997
*
* @see http://laacz.lv/2006/11/25/pk-parbaudes-algoritms/
* @param {String} value The ID
* @returns {Boolean}
*/
_lv: function(value) {
if (!/^[0-9]{6}[-]{0,1}[0-9]{5}$/.test(value)) {
return false;
}
value = value.replace(/\D/g, '');
// Check birth date
var day = parseInt(value.substr(0, 2), 10),
month = parseInt(value.substr(2, 2), 10),
year = parseInt(value.substr(4, 2), 10);
year = year + 1800 + parseInt(value.charAt(6), 10) * 100;
if (!FormValidation.Helper.date(year, month, day, true)) {
return false;
}
// Check personal code
var sum = 0,
weight = [10, 5, 8, 4, 2, 1, 6, 3, 7, 9];
for (var i = 0; i < 10; i++) {
sum += parseInt(value.charAt(i), 10) * weight[i];
}
sum = (sum + 1) % 11 % 10;
return (sum + '' === value.charAt(10));
},
/**
* Validate Dutch national identification number (BSN)
* Examples:
* - Valid: 111222333, 941331490, 9413.31.490
* - Invalid: 111252333
*
* @see https://nl.wikipedia.org/wiki/Burgerservicenummer
* @param {String} value The ID
* @returns {Boolean}
*/
_nl: function(value) {
while (value.length < 9) {
value = '0' + value;
}
if (!/^[0-9]{4}[.]{0,1}[0-9]{2}[.]{0,1}[0-9]{3}$/.test(value)) {
return false;
}
value = value.replace(/\./g, '');
if (parseInt(value, 10) === 0) {
return false;
}
var sum = 0,
length = value.length;
for (var i = 0; i < length - 1; i++) {
sum += (9 - i) * parseInt(value.charAt(i), 10);
}
sum = sum % 11;
if (sum === 10) {
sum = 0;
}
return (sum + '' === value.charAt(length - 1));
},
/**
* Validate Poland citizen number (PESEL)
*
* @see http://en.wikipedia.org/wiki/National_identification_number#Poland
* @see http://en.wikipedia.org/wiki/PESEL
* @param {String} value The ID
* @returns {Boolean}
*/
_pl: function(value) {
if (!/^[0-9]{11