id.js 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510
  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 Czech national identification number (RC)
  191. * Examples:
  192. * - Valid: 7103192745, 991231123
  193. * - Invalid: 1103492745, 590312123
  194. *
  195. * @param {String} value The ID
  196. * @returns {Boolean}
  197. */
  198. _cz: function(value) {
  199. if (!/^\d{9,10}$/.test(value)) {
  200. return false;
  201. }
  202. var year = 1900 + parseInt(value.substr(0, 2)),
  203. month = parseInt(value.substr(2, 2)) % 50 % 20,
  204. day = parseInt(value.substr(4, 2));
  205. if (value.length == 9) {
  206. if (year >= 1980) {
  207. year -= 100;
  208. }
  209. if (year > 1953) {
  210. return false;
  211. }
  212. } else if (year < 1954) {
  213. year += 100;
  214. }
  215. if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) {
  216. return false;
  217. }
  218. // Check that the birth date is not in the future
  219. if (value.length == 10) {
  220. var check = parseInt(value.substr(0, 9), 10) % 11;
  221. if (year < 1985) {
  222. check = check % 10;
  223. }
  224. return (check == value.substr(9, 1));
  225. }
  226. return true;
  227. },
  228. /**
  229. * Validate Danish Personal Identification number (CPR)
  230. * Examples:
  231. * - Valid: 2110625629, 211062-5629
  232. * - Invalid: 511062-5629
  233. *
  234. * @see https://en.wikipedia.org/wiki/Personal_identification_number_(Denmark)
  235. * @param {String} value The ID
  236. * @returns {Boolean}
  237. */
  238. _dk: function(value) {
  239. if (!/^[0-9]{6}[-]{0,1}[0-9]{4}$/.test(value)) {
  240. return false;
  241. }
  242. value = value.replace(/-/g, '');
  243. var day = parseInt(value.substr(0, 2), 10),
  244. month = parseInt(value.substr(2, 2), 10),
  245. year = parseInt(value.substr(4, 2), 10);
  246. switch (true) {
  247. case ('5678'.indexOf(value.charAt(6)) != -1 && year >= 58):
  248. year += 1800;
  249. break;
  250. case ('0123'.indexOf(value.charAt(6)) != -1):
  251. case ('49'.indexOf(value.charAt(6)) != -1 && year >= 37):
  252. year += 1900;
  253. break;
  254. default:
  255. year += 2000;
  256. break;
  257. }
  258. return $.fn.bootstrapValidator.helpers.date(year, month, day);
  259. },
  260. /**
  261. * Validate Slovak national identifier number (RC)
  262. * Examples:
  263. * - Valid: 7103192745, 991231123
  264. * - Invalid: 7103192746, 1103492745
  265. *
  266. * @param {String} value The ID
  267. * @returns {Boolean}
  268. */
  269. _sk: function(value) {
  270. // Slovakia uses the same format as Czech Republic
  271. return this._cz(value);
  272. },
  273. /**
  274. * Validate Spanish personal identity code (DNI)
  275. * Support i) DNI (for Spanish citizens) and ii) NIE (for foreign people)
  276. *
  277. * Examples:
  278. * - Valid: i) 54362315K, 54362315-K; ii) X2482300W, X-2482300W, X-2482300-W
  279. * - Invalid: i) 54362315Z; ii) X-2482300A
  280. *
  281. * @see https://en.wikipedia.org/wiki/National_identification_number#Spain
  282. * @param {String} value The ID
  283. * @returns {Boolean}
  284. */
  285. _es: function(value) {
  286. if (!/^[0-9A-Z]{8}[-]{0,1}[0-9A-Z]$/.test(value) // DNI
  287. && !/^[XYZ][-]{0,1}[0-9]{7}[-]{0,1}[0-9A-Z]$/.test(value)) { // NIE
  288. return false;
  289. }
  290. value = value.replace(/-/g, '');
  291. var index = 'XYZ'.indexOf(value.charAt(0));
  292. if (index != -1) {
  293. // It is NIE number
  294. value = index + value.substr(1) + '';
  295. }
  296. var check = parseInt(value.substr(0, 8), 10);
  297. check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23];
  298. return (check == value.substr(8, 1));
  299. },
  300. /**
  301. * Validate Croatian personal identification number (OIB)
  302. * Examples:
  303. * - Valid: 33392005961
  304. * - Invalid: 33392005962
  305. *
  306. * @param {String} value The ID
  307. * @returns {Boolean}
  308. */
  309. _hr: function(value) {
  310. if (!/^[0-9]{11}$/.test(value)) {
  311. return false;
  312. }
  313. return $.fn.bootstrapValidator.helpers.mod_11_10(value);
  314. },
  315. /**
  316. * Validate Irish Personal Public Service Number (PPS)
  317. * Examples:
  318. * - Valid: 6433435F, 6433435FT, 6433435FW, 6433435OA, 6433435IH, 1234567TW, 1234567FA
  319. * - Invalid: 6433435E, 6433435VH
  320. *
  321. * @see https://en.wikipedia.org/wiki/Personal_Public_Service_Number
  322. * @param {String} value The ID
  323. * @returns {Boolean}
  324. */
  325. _ie: function(value) {
  326. if (!/^\d{7}[A-W][AHWTX]?$/.test(value)) {
  327. return false;
  328. }
  329. var getCheckDigit = function(value) {
  330. while (value.length < 7) {
  331. value = '0' + value;
  332. }
  333. var alphabet = 'WABCDEFGHIJKLMNOPQRSTUV',
  334. sum = 0;
  335. for (var i = 0; i < 7; i++) {
  336. sum += parseInt(value.charAt(i)) * (8 - i);
  337. }
  338. sum += 9 * alphabet.indexOf(value.substr(7));
  339. return alphabet[sum % 23];
  340. };
  341. // 2013 format
  342. if (value.length == 9 && ('A' == value.charAt(8) || 'H' == value.charAt(8))) {
  343. return value.charAt(7) == getCheckDigit(value.substr(0, 7) + value.substr(8) + '');
  344. }
  345. // The old format
  346. else {
  347. return value.charAt(7) == getCheckDigit(value.substr(0, 7));
  348. }
  349. },
  350. /**
  351. * Validate Dutch national identification number (BSN)
  352. * Examples:
  353. * - Valid: 111222333, 941331490, 9413.31.490
  354. * - Invalid: 111252333
  355. *
  356. * @see https://nl.wikipedia.org/wiki/Burgerservicenummer
  357. * @param {String} value The ID
  358. * @returns {Boolean}
  359. */
  360. _nl: function(value) {
  361. while (value.length < 9) {
  362. value = '0' + value;
  363. }
  364. if (!/^[0-9]{4}[.]{0,1}[0-9]{2}[.]{0,1}[0-9]{3}$/.test(value)) {
  365. return false;
  366. }
  367. value = value.replace(/\./g, '');
  368. if (parseInt(value, 10) == 0) {
  369. return false;
  370. }
  371. var sum = 0,
  372. length = value.length;
  373. for (var i = 0; i < length - 1; i++) {
  374. sum += (9 - i) * parseInt(value.charAt(i));
  375. }
  376. sum = sum % 11;
  377. if (sum == 10) {
  378. sum = 0;
  379. }
  380. return (sum == value.charAt(length - 1));
  381. },
  382. /**
  383. * Validate Romanian numerical personal code (CNP)
  384. * Examples:
  385. * - Valid: 1630615123457, 1800101221144
  386. * - Invalid: 8800101221144, 1632215123457, 1630615123458
  387. *
  388. * @see http://en.wikipedia.org/wiki/National_identification_number#Romania
  389. * @param {String} value The ID
  390. * @returns {Boolean}
  391. */
  392. _ro: function(value) {
  393. if (!/^[0-9]{13}$/.test(value)) {
  394. return false;
  395. }
  396. var gender = parseInt(value.charAt(0));
  397. if (gender == 0 || gender == 7 || gender == 8) {
  398. return false;
  399. }
  400. // Determine the date of birth
  401. var year = parseInt(value.substr(1, 2), 10),
  402. month = parseInt(value.substr(3, 2), 10),
  403. day = parseInt(value.substr(5, 2), 10),
  404. // The year of date is determined base on the gender
  405. centuries = {
  406. '1': 1900, // Male born between 1900 and 1999
  407. '2': 1900, // Female born between 1900 and 1999
  408. '3': 1800, // Male born between 1800 and 1899
  409. '4': 1800, // Female born between 1800 and 1899
  410. '5': 2000, // Male born after 2000
  411. '6': 2000 // Female born after 2000
  412. };
  413. if (day > 31 && month > 12) {
  414. return false;
  415. }
  416. if (gender != 9) {
  417. year = centuries[gender + ''] + year;
  418. if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) {
  419. return false;
  420. }
  421. }
  422. // Validate the check digit
  423. var sum = 0,
  424. weight = [2, 7, 9, 1, 4, 6, 3, 5, 8, 2, 7, 9],
  425. length = value.length;
  426. for (var i = 0; i < length - 1; i++) {
  427. sum += parseInt(value.charAt(i)) * weight[i];
  428. }
  429. sum = sum % 11;
  430. if (sum == 10) {
  431. sum = 1;
  432. }
  433. return (sum == value.charAt(length - 1));
  434. },
  435. /**
  436. * Validate Swedish personal identity number (personnummer)
  437. * Examples:
  438. * - Valid: 8112289874, 811228-9874, 811228+9874
  439. * - Invalid: 811228-9873
  440. *
  441. * @see http://en.wikipedia.org/wiki/Personal_identity_number_(Sweden)
  442. * @param {String} value The ID
  443. * @returns {Boolean}
  444. */
  445. _se: function(value) {
  446. if (!/^[0-9]{10}$/.test(value) && !/^[0-9]{6}[-|+][0-9]{4}$/.test(value)) {
  447. return false;
  448. }
  449. value = value.replace(/[^0-9]/g, '');
  450. var year = parseInt(value.substr(0, 2)) + 1900,
  451. month = parseInt(value.substr(2, 2)),
  452. day = parseInt(value.substr(4, 2));
  453. if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) {
  454. return false;
  455. }
  456. // Validate the last check digit
  457. return $.fn.bootstrapValidator.helpers.luhn(value);
  458. },
  459. /**
  460. * Validate San Marino citizen number
  461. *
  462. * @see http://en.wikipedia.org/wiki/National_identification_number#San_Marino
  463. * @param {String} value The ID
  464. * @returns {Boolean}
  465. */
  466. _sm: function(value) {
  467. return /^\d{5}$/.test(value);
  468. }
  469. };
  470. }(window.jQuery));