id.js 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. (function($) {
  2. $.fn.bootstrapValidator.validators.id = {
  3. html5Attributes: {
  4. message: 'message',
  5. country: 'country'
  6. },
  7. /**
  8. * Validate identification number in different countries
  9. *
  10. * @see http://en.wikipedia.org/wiki/National_identification_number
  11. * @param {BootstrapValidator} validator The validator plugin instance
  12. * @param {jQuery} $field Field element
  13. * @param {Object} options Consist of key:
  14. * - message: The invalid message
  15. * - country: The ISO 3166-1 country code
  16. * @returns {Boolean}
  17. */
  18. validate: function(validator, $field, options) {
  19. var value = $field.val();
  20. if (value == '') {
  21. return true;
  22. }
  23. var country = options.country || value.substr(0, 2),
  24. method = ['_', country.toLowerCase()].join('');
  25. if (this[method] && 'function' == typeof this[method]) {
  26. return this[method](value);
  27. }
  28. return true;
  29. },
  30. /**
  31. * Validate Unique Master Citizen Number which uses in
  32. * - Bosnia and Herzegovina (country code: BA)
  33. * - Macedonia (MK)
  34. * - Montenegro (ME)
  35. * - Serbia (RS)
  36. * - Slovenia (SI)
  37. *
  38. * @see http://en.wikipedia.org/wiki/Unique_Master_Citizen_Number
  39. * @param {String} value The ID
  40. * @param {String} countryCode The ISO country code, can be BA, MK, ME, RS, SI
  41. * @returns {Boolean}
  42. */
  43. _validateJMBG: function(value, countryCode) {
  44. if (!/^\d{13}$/.test(value)) {
  45. return false;
  46. }
  47. var day = parseInt(value.substr(0, 2), 10),
  48. month = parseInt(value.substr(2, 2), 10),
  49. year = parseInt(value.substr(4, 3), 10),
  50. rr = parseInt(value.substr(7, 2), 10),
  51. k = parseInt(value.substr(12, 1), 10);
  52. // Validate date of birth
  53. // FIXME: Validate the year of birth
  54. if (day > 31 || month > 12) {
  55. return false;
  56. }
  57. // Validate checksum
  58. var sum = 0;
  59. for (var i = 0; i < 6; i++) {
  60. sum += (7 - i) * (parseInt(value.charAt(i)) + parseInt(value.charAt(i + 6)));
  61. }
  62. sum = 11 - sum % 11;
  63. if (sum == 10 || sum == 11) {
  64. sum = 0;
  65. }
  66. if (sum != k) {
  67. return false;
  68. }
  69. // Validate political region
  70. // rr is the political region of birth, which can be in ranges:
  71. // 10-19: Bosnia and Herzegovina
  72. // 20-29: Montenegro
  73. // 30-39: Croatia (not used anymore)
  74. // 41-49: Macedonia
  75. // 50-59: Slovenia (only 50 is used)
  76. // 70-79: Central Serbia
  77. // 80-89: Serbian province of Vojvodina
  78. // 90-99: Kosovo
  79. switch (countryCode.toUpperCase()) {
  80. case 'BA':
  81. return (10 <= rr && rr <= 19);
  82. case 'MK':
  83. return (41 <= rr && rr <= 49);
  84. case 'ME':
  85. return (20 <= rr && rr <= 29);
  86. case 'RS':
  87. return (70 <= rr && rr <= 99);
  88. case 'SI':
  89. return (50 <= rr && rr <= 59);
  90. default:
  91. return true;
  92. }
  93. return true;
  94. },
  95. _ba: function(value) {
  96. return this._validateJMBG(value, 'BA');
  97. },
  98. _mk: function(value) {
  99. return this._validateJMBG(value, 'MK');
  100. },
  101. _me: function(value) {
  102. return this._validateJMBG(value, 'ME');
  103. },
  104. _rs: function(value) {
  105. return this._validateJMBG(value, 'RS');
  106. },
  107. /**
  108. * Examples: 0101006500006
  109. */
  110. _si: function(value) {
  111. return this._validateJMBG(value, 'SI');
  112. },
  113. /**
  114. * Validate Bulgarian national identification number (EGN)
  115. * Examples:
  116. * - Valid: 7523169263, 8032056031, 803205 603 1, 8001010008, 7501020018, 7552010005, 7542011030
  117. * - Invalid: 8019010008
  118. *
  119. * @see http://en.wikipedia.org/wiki/Uniform_civil_number
  120. * @param {String} value The ID
  121. * @returns {Boolean}
  122. */
  123. _bg: function(value) {
  124. if (!/^\d{10}$/.test(value) && !/^\d{6}\s\d{3}\s\d{1}$/.test(value)) {
  125. return false;
  126. }
  127. value = value.replace(/\s/g, '');
  128. // Check the birth date
  129. var year = parseInt(value.substr(0, 2), 10) + 1900,
  130. month = parseInt(value.substr(2, 2), 10),
  131. day = parseInt(value.substr(4, 2), 10);
  132. if (month > 40) {
  133. year += 100;
  134. month -= 40;
  135. } else if (month > 20) {
  136. year -= 100;
  137. month -= 20;
  138. }
  139. if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) {
  140. return false;
  141. }
  142. var sum = 0,
  143. weight = [2, 4, 8, 5, 10, 9, 7, 3, 6];
  144. for (var i = 0; i < 9; i++) {
  145. sum += parseInt(value.charAt(i)) * weight[i];
  146. }
  147. sum = (sum % 11) % 10;
  148. return (sum == value.substr(9, 1));
  149. },
  150. /**
  151. * Validate Brazilian national identification number (CPF)
  152. * Examples:
  153. * - Valid: 39053344705, 390.533.447-05, 111.444.777-35
  154. * - Invalid: 231.002.999-00
  155. *
  156. * @see http://en.wikipedia.org/wiki/Cadastro_de_Pessoas_F%C3%ADsicas
  157. * @param {String} value The ID
  158. * @returns {Boolean}
  159. */
  160. _br: function(value) {
  161. if (/^1{11}|2{11}|3{11}|4{11}|5{11}|6{11}|7{11}|8{11}|9{11}|0{11}$/.test(value)) {
  162. return false;
  163. }
  164. if (!/^\d{11}$/.test(value) && !/^\d{3}\.\d{3}\.\d{3}-\d{2}$/.test(value)) {
  165. return false;
  166. }
  167. value = value.replace(/\./g, '').replace(/-/g, '');
  168. var d1 = 0;
  169. for (var i = 0; i < 9; i++) {
  170. d1 += (10 - i) * parseInt(value.charAt(i));
  171. }
  172. d1 = 11 - d1 % 11;
  173. if (d1 == 10 || d1 == 11) {
  174. d1 = 0;
  175. }
  176. if (d1 != value.charAt(9)) {
  177. return false;
  178. }
  179. var d2 = 0;
  180. for (i = 0; i < 10; i++) {
  181. d2 += (11 - i) * parseInt(value.charAt(i));
  182. }
  183. d2 = 11 - d2 % 11;
  184. if (d2 == 10 || d2 == 11) {
  185. d2 = 0;
  186. }
  187. return (d2 == value.charAt(10));
  188. },
  189. /**
  190. * Validate Chilean national identification number (RUN/RUT)
  191. * Examples:
  192. * - Valid: 76086428-5, 22060449-7, 12531909-2
  193. *
  194. * @see http://en.wikipedia.org/wiki/National_identification_number#Chile
  195. * @see https://palena.sii.cl/cvc/dte/ee_empresas_emisoras.html for samples
  196. * @param {String} value The ID
  197. * @returns {Boolean}
  198. */
  199. _cl: function(value) {
  200. if (!/^\d{7,8}[-]{0,1}[0-9K]$/.test(value)) {
  201. return false;
  202. }
  203. value = value.replace(/\D/g, '');
  204. while (value.length < 9) {
  205. value = '0' + value;
  206. }
  207. var sum = 0,
  208. weight = [3, 2, 7, 6, 5, 4, 3, 2];
  209. for (var i = 0; i < 8; i++) {
  210. sum += parseInt(value.charAt(i)) * weight[i];
  211. }
  212. sum = 11 - sum % 11;
  213. if (sum == 11) {
  214. sum = 0;
  215. } else if (sum == 10) {
  216. sum = 'K';
  217. }
  218. return sum == value.charAt(8);
  219. },
  220. /**
  221. * Validate Czech national identification number (RC)
  222. * Examples:
  223. * - Valid: 7103192745, 991231123
  224. * - Invalid: 1103492745, 590312123
  225. *
  226. * @param {String} value The ID
  227. * @returns {Boolean}
  228. */
  229. _cz: function(value) {
  230. if (!/^\d{9,10}$/.test(value)) {
  231. return false;
  232. }
  233. var year = 1900 + parseInt(value.substr(0, 2)),
  234. month = parseInt(value.substr(2, 2)) % 50 % 20,
  235. day = parseInt(value.substr(4, 2));
  236. if (value.length == 9) {
  237. if (year >= 1980) {
  238. year -= 100;
  239. }
  240. if (year > 1953) {
  241. return false;
  242. }
  243. } else if (year < 1954) {
  244. year += 100;
  245. }
  246. if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) {
  247. return false;
  248. }
  249. // Check that the birth date is not in the future
  250. if (value.length == 10) {
  251. var check = parseInt(value.substr(0, 9), 10) % 11;
  252. if (year < 1985) {
  253. check = check % 10;
  254. }
  255. return (check == value.substr(9, 1));
  256. }
  257. return true;
  258. },
  259. /**
  260. * Validate Danish Personal Identification number (CPR)
  261. * Examples:
  262. * - Valid: 2110625629, 211062-5629
  263. * - Invalid: 511062-5629
  264. *
  265. * @see https://en.wikipedia.org/wiki/Personal_identification_number_(Denmark)
  266. * @param {String} value The ID
  267. * @returns {Boolean}
  268. */
  269. _dk: function(value) {
  270. if (!/^[0-9]{6}[-]{0,1}[0-9]{4}$/.test(value)) {
  271. return false;
  272. }
  273. value = value.replace(/-/g, '');
  274. var day = parseInt(value.substr(0, 2), 10),
  275. month = parseInt(value.substr(2, 2), 10),
  276. year = parseInt(value.substr(4, 2), 10);
  277. switch (true) {
  278. case ('5678'.indexOf(value.charAt(6)) != -1 && year >= 58):
  279. year += 1800;
  280. break;
  281. case ('0123'.indexOf(value.charAt(6)) != -1):
  282. case ('49'.indexOf(value.charAt(6)) != -1 && year >= 37):
  283. year += 1900;
  284. break;
  285. default:
  286. year += 2000;
  287. break;
  288. }
  289. return $.fn.bootstrapValidator.helpers.date(year, month, day);
  290. },
  291. /**
  292. * Validate Spanish personal identity code (DNI)
  293. * Support i) DNI (for Spanish citizens) and ii) NIE (for foreign people)
  294. *
  295. * Examples:
  296. * - Valid: i) 54362315K, 54362315-K; ii) X2482300W, X-2482300W, X-2482300-W
  297. * - Invalid: i) 54362315Z; ii) X-2482300A
  298. *
  299. * @see https://en.wikipedia.org/wiki/National_identification_number#Spain
  300. * @param {String} value The ID
  301. * @returns {Boolean}
  302. */
  303. _es: function(value) {
  304. if (!/^[0-9A-Z]{8}[-]{0,1}[0-9A-Z]$/.test(value) // DNI
  305. && !/^[XYZ][-]{0,1}[0-9]{7}[-]{0,1}[0-9A-Z]$/.test(value)) { // NIE
  306. return false;
  307. }
  308. value = value.replace(/-/g, '');
  309. var index = 'XYZ'.indexOf(value.charAt(0));
  310. if (index != -1) {
  311. // It is NIE number
  312. value = index + value.substr(1) + '';
  313. }
  314. var check = parseInt(value.substr(0, 8), 10);
  315. check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23];
  316. return (check == value.substr(8, 1));
  317. },
  318. /**
  319. * Validate Finnish Personal Identity Code (HETU)
  320. * Examples:
  321. * - Valid: 311280-888Y, 131052-308T
  322. * - Invalid: 131052-308U, 310252-308Y
  323. *
  324. * @param {String} value The ID
  325. * @returns {Boolean}
  326. */
  327. _fi: function(value) {
  328. if (!/^[0-9]{6}[-+A][0-9]{3}[0-9ABCDEFHJKLMNPRSTUVWXY]$/.test(value)) {
  329. return false;
  330. }
  331. var day = parseInt(value.substr(0, 2), 10),
  332. month = parseInt(value.substr(2, 2), 10),
  333. year = parseInt(value.substr(4, 2), 10),
  334. centuries = {
  335. '+': 1800,
  336. '-': 1900,
  337. 'A': 2000
  338. };
  339. year = centuries[value.charAt(6)] + year;
  340. if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) {
  341. return false;
  342. }
  343. var individual = parseInt(value.substr(7, 3));
  344. if (individual < 2) {
  345. return false;
  346. }
  347. var n = value.substr(0, 6) + value.substr(7, 3) + '';
  348. n = parseInt(n);
  349. return '0123456789ABCDEFHJKLMNPRSTUVWXY'.charAt(n % 31) == value.charAt(10);
  350. },
  351. /**
  352. * Validate Croatian personal identification number (OIB)
  353. * Examples:
  354. * - Valid: 33392005961
  355. * - Invalid: 33392005962
  356. *
  357. * @param {String} value The ID
  358. * @returns {Boolean}
  359. */
  360. _hr: function(value) {
  361. if (!/^[0-9]{11}$/.test(value)) {
  362. return false;
  363. }
  364. return $.fn.bootstrapValidator.helpers.mod_11_10(value);
  365. },
  366. /**
  367. * Validate Irish Personal Public Service Number (PPS)
  368. * Examples:
  369. * - Valid: 6433435F, 6433435FT, 6433435FW, 6433435OA, 6433435IH, 1234567TW, 1234567FA
  370. * - Invalid: 6433435E, 6433435VH
  371. *
  372. * @see https://en.wikipedia.org/wiki/Personal_Public_Service_Number
  373. * @param {String} value The ID
  374. * @returns {Boolean}
  375. */
  376. _ie: function(value) {
  377. if (!/^\d{7}[A-W][AHWTX]?$/.test(value)) {
  378. return false;
  379. }
  380. var getCheckDigit = function(value) {
  381. while (value.length < 7) {
  382. value = '0' + value;
  383. }
  384. var alphabet = 'WABCDEFGHIJKLMNOPQRSTUV',
  385. sum = 0;
  386. for (var i = 0; i < 7; i++) {
  387. sum += parseInt(value.charAt(i)) * (8 - i);
  388. }
  389. sum += 9 * alphabet.indexOf(value.substr(7));
  390. return alphabet[sum % 23];
  391. };
  392. // 2013 format
  393. if (value.length == 9 && ('A' == value.charAt(8) || 'H' == value.charAt(8))) {
  394. return value.charAt(7) == getCheckDigit(value.substr(0, 7) + value.substr(8) + '');
  395. }
  396. // The old format
  397. else {
  398. return value.charAt(7) == getCheckDigit(value.substr(0, 7));
  399. }
  400. },
  401. /**
  402. * Validate Dutch national identification number (BSN)
  403. * Examples:
  404. * - Valid: 111222333, 941331490, 9413.31.490
  405. * - Invalid: 111252333
  406. *
  407. * @see https://nl.wikipedia.org/wiki/Burgerservicenummer
  408. * @param {String} value The ID
  409. * @returns {Boolean}
  410. */
  411. _nl: function(value) {
  412. while (value.length < 9) {
  413. value = '0' + value;
  414. }
  415. if (!/^[0-9]{4}[.]{0,1}[0-9]{2}[.]{0,1}[0-9]{3}$/.test(value)) {
  416. return false;
  417. }
  418. value = value.replace(/\./g, '');
  419. if (parseInt(value, 10) == 0) {
  420. return false;
  421. }
  422. var sum = 0,
  423. length = value.length;
  424. for (var i = 0; i < length - 1; i++) {
  425. sum += (9 - i) * parseInt(value.charAt(i));
  426. }
  427. sum = sum % 11;
  428. if (sum == 10) {
  429. sum = 0;
  430. }
  431. return (sum == value.charAt(length - 1));
  432. },
  433. /**
  434. * Validate Romanian numerical personal code (CNP)
  435. * Examples:
  436. * - Valid: 1630615123457, 1800101221144
  437. * - Invalid: 8800101221144, 1632215123457, 1630615123458
  438. *
  439. * @see http://en.wikipedia.org/wiki/National_identification_number#Romania
  440. * @param {String} value The ID
  441. * @returns {Boolean}
  442. */
  443. _ro: function(value) {
  444. if (!/^[0-9]{13}$/.test(value)) {
  445. return false;
  446. }
  447. var gender = parseInt(value.charAt(0));
  448. if (gender == 0 || gender == 7 || gender == 8) {
  449. return false;
  450. }
  451. // Determine the date of birth
  452. var year = parseInt(value.substr(1, 2), 10),
  453. month = parseInt(value.substr(3, 2), 10),
  454. day = parseInt(value.substr(5, 2), 10),
  455. // The year of date is determined base on the gender
  456. centuries = {
  457. '1': 1900, // Male born between 1900 and 1999
  458. '2': 1900, // Female born between 1900 and 1999
  459. '3': 1800, // Male born between 1800 and 1899
  460. '4': 1800, // Female born between 1800 and 1899
  461. '5': 2000, // Male born after 2000
  462. '6': 2000 // Female born after 2000
  463. };
  464. if (day > 31 && month > 12) {
  465. return false;
  466. }
  467. if (gender != 9) {
  468. year = centuries[gender + ''] + year;
  469. if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) {
  470. return false;
  471. }
  472. }
  473. // Validate the check digit
  474. var sum = 0,
  475. weight = [2, 7, 9, 1, 4, 6, 3, 5, 8, 2, 7, 9],
  476. length = value.length;
  477. for (var i = 0; i < length - 1; i++) {
  478. sum += parseInt(value.charAt(i)) * weight[i];
  479. }
  480. sum = sum % 11;
  481. if (sum == 10) {
  482. sum = 1;
  483. }
  484. return (sum == value.charAt(length - 1));
  485. },
  486. /**
  487. * Validate Swedish personal identity number (personnummer)
  488. * Examples:
  489. * - Valid: 8112289874, 811228-9874, 811228+9874
  490. * - Invalid: 811228-9873
  491. *
  492. * @see http://en.wikipedia.org/wiki/Personal_identity_number_(Sweden)
  493. * @param {String} value The ID
  494. * @returns {Boolean}
  495. */
  496. _se: function(value) {
  497. if (!/^[0-9]{10}$/.test(value) && !/^[0-9]{6}[-|+][0-9]{4}$/.test(value)) {
  498. return false;
  499. }
  500. value = value.replace(/[^0-9]/g, '');
  501. var year = parseInt(value.substr(0, 2)) + 1900,
  502. month = parseInt(value.substr(2, 2)),
  503. day = parseInt(value.substr(4, 2));
  504. if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) {
  505. return false;
  506. }
  507. // Validate the last check digit
  508. return $.fn.bootstrapValidator.helpers.luhn(value);
  509. },
  510. /**
  511. * Validate Slovak national identifier number (RC)
  512. * Examples:
  513. * - Valid: 7103192745, 991231123
  514. * - Invalid: 7103192746, 1103492745
  515. *
  516. * @param {String} value The ID
  517. * @returns {Boolean}
  518. */
  519. _sk: function(value) {
  520. // Slovakia uses the same format as Czech Republic
  521. return this._cz(value);
  522. },
  523. /**
  524. * Validate San Marino citizen number
  525. *
  526. * @see http://en.wikipedia.org/wiki/National_identification_number#San_Marino
  527. * @param {String} value The ID
  528. * @returns {Boolean}
  529. */
  530. _sm: function(value) {
  531. return /^\d{5}$/.test(value);
  532. },
  533. /**
  534. * Validate South African ID
  535. * Example:
  536. * - Valid: 8001015009087
  537. * - Invalid: 8001015009287, 8001015009086
  538. *
  539. * @see http://en.wikipedia.org/wiki/National_identification_number#South_Africa
  540. * @param {String} value The ID
  541. * @returns {Boolean}
  542. */
  543. _za: function(value) {
  544. if (!/^[0-9]{10}[0|1][8|9][0-9]$/.test(value)) {
  545. return false;
  546. }
  547. var year = parseInt(value.substr(0, 2)),
  548. currentYear = new Date().getFullYear() % 100,
  549. month = parseInt(value.substr(2, 2)),
  550. day = parseInt(value.substr(4, 2));
  551. year = (year >= currentYear) ? (year + 1900) : (year + 2000);
  552. if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) {
  553. return false;
  554. }
  555. // Validate the last check digit
  556. return $.fn.bootstrapValidator.helpers.luhn(value);
  557. }
  558. };
  559. }(window.jQuery));