-
-
Save rlucha/d387c51c0d2755703b08 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* AngularJS service to validate spanish document id. | |
* Returns the type of document and checks its validity. | |
* | |
* Usage: | |
* angular | |
* .module('myApp', [ 'validate-spanish-id' ]) | |
* .controller('myController', function(ValidateSpanishID){ | |
* ValidateSpanishID.validate( str ); | |
* }) | |
* | |
* | |
* > ValidateSpanishID.validate( '12345678Z' ); | |
* // { type: 'dni', valid: true } | |
* | |
* > ValidateSpanishID.validate( 'B83375575' ); | |
* // { type: 'cif', valid: false } | |
* | |
* The algorithm is adapted from other solutions found at: | |
* - https://gist.github.com/afgomez/5691823 | |
* - http://www.compartecodigo.com/javascript/validar-nif-cif-nie-segun-ley-vigente-31.html | |
* - http://es.wikipedia.org/wiki/C%C3%B3digo_de_identificaci%C3%B3n_fiscal | |
*/ | |
(function() { | |
'use strict'; | |
angular | |
.module('validate-spanish-id', []) | |
.service('ValidateSpanishID', [ function() { | |
this.DNI_REGEX = /^(\d{8})([A-Z])$/; | |
this.CIF_REGEX = /^([ABCDEFGHJKLMNPQRSUVW])(\d{7})([0-9A-J])$/; | |
this.NIE_REGEX = /^[XYZ]\d{7,8}[A-Z]$/; | |
this.validate = function( str ) { | |
// If no valid value passed | |
if (!str) { | |
str = ''; | |
} | |
// Ensure upcase and remove whitespace | |
str = str.toUpperCase().replace(/\s/, ''); | |
var valid = false; | |
var type = this.idType( str ); | |
switch (type) { | |
case 'dni': | |
valid = this.validateDNI( str ); | |
break; | |
case 'nie': | |
valid = this.validateNIE( str ); | |
break; | |
case 'cif': | |
valid = this.validateCIF( str ); | |
break; | |
} | |
return { | |
type: type, | |
valid: valid | |
}; | |
}; | |
this.idType = function( str ) { | |
if ( str.match( this.DNI_REGEX ) ) { | |
return 'dni'; | |
} | |
else if ( str.match( this.CIF_REGEX ) ) { | |
return 'cif'; | |
} | |
else if ( str.match( this.NIE_REGEX ) ) { | |
return 'nie'; | |
} | |
else { | |
return ''; | |
} | |
}; | |
this.validateDNI = function( dni ) { | |
var dni_letters = "TRWAGMYFPDXBNJZSQVHLCKE"; | |
var letter = dni_letters.charAt( parseInt( dni, 10 ) % 23 ); | |
return letter == dni.charAt(8); | |
}; | |
this.validateNIE = function( nie ) { | |
// Change the initial letter for the corresponding number and validate as DNI | |
var nie_prefix = nie.charAt( 0 ); | |
switch (nie_prefix) { | |
case 'X': | |
nie_prefix = 0; | |
break; | |
case 'Y': | |
nie_prefix = 1; | |
break; | |
case 'Z': | |
nie_prefix = 2; | |
break; | |
} | |
return this.validateDNI( nie_prefix + nie.substr(1) ); | |
}; | |
this.validateCIF = function( cif ) { | |
var match = cif.match( this.CIF_REGEX ); | |
var letter = match[1], | |
number = match[2], | |
control = match[3]; | |
var even_sum = 0; | |
var odd_sum = 0; | |
var n; | |
for ( var i = 0; i < number.length; i++) { | |
n = parseInt( number[i], 10 ); | |
// Odd positions (Even index equals to odd position. i=0 equals first position) | |
if ( i % 2 === 0 ) { | |
// Odd positions are multiplied first. | |
n *= 2; | |
// If the multiplication is bigger than 10 we need to adjust | |
odd_sum += n < 10 ? n : n - 9; | |
// Even positions | |
// Just sum them | |
} else { | |
even_sum += n; | |
} | |
} | |
var control_digit = (10 - (even_sum + odd_sum).toString().substr(-1) ); | |
var control_letter = 'JABCDEFGHI'.substr( control_digit, 1 ); | |
// Control must be a digit | |
if ( letter.match( /[ABEH]/ ) ) { | |
return control == control_digit; | |
// Control must be a letter | |
} else if ( letter.match( /[KPQS]/ ) ) { | |
return control == control_letter; | |
// Can be either | |
} else { | |
return control == control_digit || control == control_letter; | |
} | |
}; | |
}]) | |
; | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment