(function($) { $.fn.bootstrapValidator.validators.id = { html5Attributes: { message: 'message', country: 'country' }, /** * Validate identification number in different countries * * @see http://en.wikipedia.org/wiki/National_identification_number * @param {BootstrapValidator} 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 * @returns {Boolean} */ validate: function(validator, $field, options) { var value = $field.val(); if (value == '') { return true; } var country = options.country || value.substr(0, 2), method = ['_', country.toLowerCase()].join(''); if (this[method] && 'function' == typeof this[method]) { return this[method](value); } return true; }, /** * 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)) + parseInt(value.charAt(i + 6))); } 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; } 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 (!$.fn.bootstrapValidator.helpers.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)) * 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) { if (/^1{11}|2{11}|3{11}|4{11}|5{11}|6{11}|7{11}|8{11}|9{11}|0{11}$/.test(value)) { return false; } if (!/^\d{11}$/.test(value) && !/^\d{3}\.\d{3}\.\d{3}-\d{2}$/.test(value)) { return false; } value = value.replace(/\./g, '').replace(/-/g, ''); var d1 = 0; for (var i = 0; i < 9; i++) { d1 += (10 - i) * parseInt(value.charAt(i)); } 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)); } d2 = 11 - d2 % 11; if (d2 == 10 || d2 == 11) { d2 = 0; } return (d2 == value.charAt(10)); }, /** * 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]$/.test(value)) { return false; } value = value.replace(/\D/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)) * weight[i]; } sum = 11 - sum % 11; if (sum == 11) { sum = 0; } else if (sum == 10) { sum = 'K'; } return sum == value.charAt(8); }, /** * 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)), month = parseInt(value.substr(2, 2)) % 50 % 20, day = parseInt(value.substr(4, 2)); if (value.length == 9) { if (year >= 1980) { year -= 100; } if (year > 1953) { return false; } } else if (year < 1954) { year += 100; } if (!$.fn.bootstrapValidator.helpers.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 $.fn.bootstrapValidator.helpers.date(year, month, day); }, /** * Validate Spanish personal identity code (DNI) * Support i) DNI (for Spanish citizens) and ii) NIE (for foreign people) * * Examples: * - Valid: i) 54362315K, 54362315-K; ii) X2482300W, X-2482300W, X-2482300-W * - Invalid: i) 54362315Z; ii) X-2482300A * * @see https://en.wikipedia.org/wiki/National_identification_number#Spain * @param {String} value The ID * @returns {Boolean} */ _es: function(value) { if (!/^[0-9A-Z]{8}[-]{0,1}[0-9A-Z]$/.test(value) // DNI && !/^[XYZ][-]{0,1}[0-9]{7}[-]{0,1}[0-9A-Z]$/.test(value)) { // NIE return false; } value = value.replace(/-/g, ''); var index = 'XYZ'.indexOf(value.charAt(0)); if (index != -1) { // It is NIE number value = index + value.substr(1) + ''; } var check = parseInt(value.substr(0, 8), 10); check = 'TRWAGMYFPDXBNJZSQVHLCKE'[check % 23]; return (check == value.substr(8, 1)); }, /** * 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 (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { return false; } var individual = parseInt(value.substr(7, 3)); if (individual < 2) { return false; } var n = value.substr(0, 6) + value.substr(7, 3) + ''; n = parseInt(n); 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 $.fn.bootstrapValidator.helpers.mod_11_10(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)) * (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 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)); } sum = sum % 11; if (sum == 10) { sum = 0; } return (sum == value.charAt(length - 1)); }, /** * Validate Romanian numerical personal code (CNP) * Examples: * - Valid: 1630615123457, 1800101221144 * - Invalid: 8800101221144, 1632215123457, 1630615123458 * * @see http://en.wikipedia.org/wiki/National_identification_number#Romania * @param {String} value The ID * @returns {Boolean} */ _ro: function(value) { if (!/^[0-9]{13}$/.test(value)) { return false; } var gender = parseInt(value.charAt(0)); if (gender == 0 || gender == 7 || gender == 8) { return false; } // Determine the date of birth var year = parseInt(value.substr(1, 2), 10), month = parseInt(value.substr(3, 2), 10), day = parseInt(value.substr(5, 2), 10), // The year of date is determined base on the gender centuries = { '1': 1900, // Male born between 1900 and 1999 '2': 1900, // Female born between 1900 and 1999 '3': 1800, // Male born between 1800 and 1899 '4': 1800, // Female born between 1800 and 1899 '5': 2000, // Male born after 2000 '6': 2000 // Female born after 2000 }; if (day > 31 && month > 12) { return false; } if (gender != 9) { year = centuries[gender + ''] + year; if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { return false; } } // Validate the check digit var sum = 0, weight = [2, 7, 9, 1, 4, 6, 3, 5, 8, 2, 7, 9], length = value.length; for (var i = 0; i < length - 1; i++) { sum += parseInt(value.charAt(i)) * weight[i]; } sum = sum % 11; if (sum == 10) { sum = 1; } return (sum == value.charAt(length - 1)); }, /** * Validate Swedish personal identity number (personnummer) * Examples: * - Valid: 8112289874, 811228-9874, 811228+9874 * - Invalid: 811228-9873 * * @see http://en.wikipedia.org/wiki/Personal_identity_number_(Sweden) * @param {String} value The ID * @returns {Boolean} */ _se: function(value) { if (!/^[0-9]{10}$/.test(value) && !/^[0-9]{6}[-|+][0-9]{4}$/.test(value)) { return false; } value = value.replace(/[^0-9]/g, ''); var year = parseInt(value.substr(0, 2)) + 1900, month = parseInt(value.substr(2, 2)), day = parseInt(value.substr(4, 2)); if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { return false; } // Validate the last check digit return $.fn.bootstrapValidator.helpers.luhn(value); }, /** * Validate Slovak national identifier number (RC) * Examples: * - Valid: 7103192745, 991231123 * - Invalid: 7103192746, 1103492745 * * @param {String} value The ID * @returns {Boolean} */ _sk: function(value) { // Slovakia uses the same format as Czech Republic return this._cz(value); }, /** * Validate San Marino citizen number * * @see http://en.wikipedia.org/wiki/National_identification_number#San_Marino * @param {String} value The ID * @returns {Boolean} */ _sm: function(value) { return /^\d{5}$/.test(value); }, /** * Validate South African ID * Example: * - Valid: 8001015009087 * - Invalid: 8001015009287, 8001015009086 * * @see http://en.wikipedia.org/wiki/National_identification_number#South_Africa * @param {String} value The ID * @returns {Boolean} */ _za: function(value) { if (!/^[0-9]{10}[0|1][8|9][0-9]$/.test(value)) { return false; } var year = parseInt(value.substr(0, 2)), currentYear = new Date().getFullYear() % 100, month = parseInt(value.substr(2, 2)), day = parseInt(value.substr(4, 2)); year = (year >= currentYear) ? (year + 1900) : (year + 2000); if (!$.fn.bootstrapValidator.helpers.date(year, month, day)) { return false; } // Validate the last check digit return $.fn.bootstrapValidator.helpers.luhn(value); } }; }(window.jQuery));