diff --git a/.travis.yml b/.travis.yml
index d9fa4ca..19844a2 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,5 +1,6 @@
language: node_js
node_js:
+ - "0.12"
- "0.11"
- "0.10"
before_script:
diff --git a/Gruntfile.js b/Gruntfile.js
index 3b7ebc2..7602aea 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -79,6 +79,17 @@ module.exports = function (grunt) {
}
},
+ browserify: {
+ dist: {
+ options: {
+ transform: ['debowerify']
+ },
+ files: {
+ '.tmp/ng-iban.js': '.tmp/ng-iban.js'
+ }
+ }
+ },
+
karma: {
unit: {
configFile: 'test/karma.conf.coffee',
@@ -90,6 +101,7 @@ module.exports = function (grunt) {
grunt.registerTask('test', [
'clean:tmp',
'coffee',
+ 'browserify',
'connect:test',
'karma'
]);
@@ -100,4 +112,4 @@ module.exports = function (grunt) {
'ngAnnotate',
'uglify'
]);
-}
+};
diff --git a/README.adoc b/README.adoc
new file mode 100644
index 0000000..af98830
--- /dev/null
+++ b/README.adoc
@@ -0,0 +1,30 @@
+:figure-caption!:
+
+image::https://travis-ci.org/mmjmanders/ng-iban.svg?branch=master[title="travis status", alt="travis status", link="https://travis-ci.org/mmjmanders/ng-iban"]
+
+image::https://app.wercker.com/status/eb4337041c62e162c5dd7af43122647c/m[title="wercker status", alt="wercker status", link="https://app.wercker.com/project/bykey/eb4337041c62e162c5dd7af43122647c"]
+
+= ng-iban - validate input fields as IBAN
+The goal is to provide an easy way to validate an input field as an IBAN number with https://angularjs.org/[AngularJS].
+From version `0.4.0` the module uses https://github.com/arhs/iban.js[iban.js] for validation.
+
+== Usage
+First add
+
+* `AngularJS`
+* `ng-iban`
+
+to your HTML file.
+
+Make sure you require `mm.iban` as a dependency of your AngularJS module.
+
+== Installation
+`bower install ng-iban`
+
+=== directive
+[source,html]
+----
+
+----
+
+To use this directive the `ngModel` directive must also be used because this directive depends on it.
diff --git a/README.md b/README.md
deleted file mode 100644
index ebfd0fa..0000000
--- a/README.md
+++ /dev/null
@@ -1,102 +0,0 @@
-[![Build Status](https://travis-ci.org/mmjmanders/ng-iban.svg?branch=master)](https://travis-ci.org/mmjmanders/ng-iban)
-
-# ng-iban - validate input fields as IBAN
-The goals is to provide an easy way to validate an input field as an IBAN number with [AngularJS](https://angularjs.org/).
-
-## Usage
-First add
-
-- `AngularJS`
-- `ng-iban`
-
-to your HTML file.
-
-Make sure you require `mm.iban` as a dependency of your AngularJS module.
-
-## Installation
-`bower install ng-iban`
-
-### directive
-```html
-
-```
-
-or
-
-```html
-
-```
-
-where `[Country code]` is one of the country codes from the table below.
-
-To use this directive the `ngModel` directive must also be used because this directive depends on it.
-
-## Predefined countries
-Country | Country code | IBAN format | IBAN length | IBAN example
-------- | ------------ | ----------- | ----------- | ------------
-Albania | AL | AL[0-9]{2}[0-9]{8}[A-Z0-9]{16} | 28 | AL47212110090000000235698741
-Andorra | AD | AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12} | 24 | AD1200012030200359100100
-Austria | AT | AT[0-9]{2}[0-9]{5}[0-9]{11} | 20 | AT611904300234573201
-Azerbaijan, Republic of | AZ | AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20} | 28 | AZ21NABZ00000000137010001944
-Bahrain | BH | BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14} | 22 | BH67BMAG00001299123456
-Belgium | BE | BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2} | 16 | BE68539007547034
-Bosnia and Herzegovina | BA | BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2} | 20 | BA391290079401028494
-Brazil | BR | BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z]{1}[A-Z0-9]{1} | 29 | BR7724891749412660603618210F3
-Bulgaria | BG | BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8} | 22 | BG80BNBG96611020345678
-Costa Rica | CR | CR[0-9]{2}[0-9]{3}[0-9]{14} | 21 | CR0515202001026284066
-Croatia | HR | HR[0-9]{2}[0-9]{7}[0-9]{10} | 21 | HR1210010051863000160
-Cyprus | CY | CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16} | 28 | CY17002001280000001200527600
-Czech Republic | CZ | CZ[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10} | 24 | CZ6508000000192000145399
-Denmark | DK | DK[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1} | 18 | DK5000400440116243
-Dominican Republic | DO | DO[0-9]{2}[A-Z0-9]{4}[0-9]{20} | 28 | DO28BAGR00000001212453611324
-Estonia | EE | EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1} | 20 | EE382200221020145685
-Faroe Islands | FO | FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1} | 18 | FO6264600001631634
-Finland | FI | FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1} | 18 | FI2112345600000785
-France | FR | FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2} | 27 | FR1420041010050500013M02606
-Georgia | GE | GE[0-9]{2}[A-Z]{2}[0-9]{16} | 22 | GE29NB0000000101904917
-Germany | DE | DE[0-9]{2}[0-9]{8}[0-9]{10} | 22 | DE89370400440532013000
-Gibraltar | GI | GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15} | 23 | GI75NWBK000000007099453
-Greece | GR | GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16} | 27 | GR1601101250000000012300695
-Greenland | GL | GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1} | 18 | GL8964710001000206
-Guatemala | GT | GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20} | 28 | GT82TRAJ01020000001210029690
-Hungary | HU | HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1} | 28 | HU42117730161111101800000000
-Iceland | IS | IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10} | 26 | IS140159260076545510730339
-Ireland | IE | IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8} | 22 | IE29AIBK93115212345678
-Israel | IL | IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13} | 23 | IL620108000000099999999
-Italy | IT | IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12} | 27 | IT60X0542811101000000123456
-Kazakhstan | KZ | KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13} | 20 | KZ86125KZT5004100100
-Kuwait | KW | KW[0-9]{2}[A-Z]{4}[A-Z0-9]{22} | 30 | KW81CBKU0000000000001234560101
-Latvia | LV | LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13} | 21 | LV80BANK0000435195001
-Lebanon | LB | LB[0-9]{2}[0-9]{4}[A-Z0-9]{20} | 28 | LB62099900000001001901229114
-Liechtenstein (Principality of) | LI | LI[0-9]{2}[0-9]{5}[A-Z0-9]{12} | 21 | LI21088100002324013AA
-Lithuania | LT | LT[0-9]{2}[0-9]{5}[0-9]{11} | 20 | LT121000011101001000
-Luxembourg | LU | LU[0-9]{2}[0-9]{3}[A-Z0-9]{13} | 20 | LU280019400644750000
-Macedonia | MK | MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2} | 19 | MK07250120000058984
-Malta | MT | MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18} | 31 | MT84MALT011000012345MTLCAST001S
-Mauritania | MR | MR[0-9]{2}[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2} | 27 | MR1300020001010000123456753
-Mauritius | MU | MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3} | 30 | MU17BOMM0101101030300200000MUR
-Moldova, Republic of | MD | MD[0-9]{2}[A-Z0-9]{20} | 24 | MD24AG000225100013104168
-Monaco | MC | MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2} | 27 | MC5811222000010123456789030
-Montenegro | ME | ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2} | 22 | ME25505000012345678951
-Netherlands | NL | NL[0-9]{2}[A-Z]{4}[0-9]{10} | 18 | NL91ABNA0417164300
-Norway | NO | NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1} | 15 | NO9386011117947
-Pakistan | PK | PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16} | 24 | PK36SCBL0000001123456702
-Poland | PL | PL[0-9]{2}[0-9]{8}[0-9]{16} | 28 | PL61109010140000071219812874
-Palestinian Territory, Occupied | PS | PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21} | 29 | PS92PALS000000000400123456702
-Portugal | PT | PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2} | 25 | PT50000201231234567890154
-Qatar | QA | QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21} | 29 | QA58DOHB00001234567890ABCDEFG
-Romania | RO | RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16} | 24 | RO49AAAA1B31007593840000
-San Marino | SM | SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12} | 27 | SM86U0322509800000000270100
-Saudi Arabia | SA | SA[0-9]{2}[0-9]{2}[A-Z0-9]{18} | 24 | SA0380000000608010167519
-Serbia | RS | RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2} | 22 | RS35260005601001611379
-Slovak Republic | SK | SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10} | 24 | SK3112000000198742637541
-Slovenia | SI | SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2} | 19 | SI56263300012039086
-Spain | ES | ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10} | 24 | ES9121000418450200051332
-Sweden | SE | SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1} | 24 | SE4550000000058398257466
-Switzerland | CH | CH[0-9]{2}[0-9]{5}[A-Z0-9]{12} | 21 | CH9300762011623852957
-Timor-Leste | TL | TL[0-9]{2}[0-9]{3}[0-9]{14}[0-9]{2} | 23 | TL380080012345678910157
-Tunisia | TN | TN[0-9]{2}[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2} | 24 | TN5910006035183598478831
-Turkey | TR | TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16} | 26 | TR330006100519786457841326
-United Arab Emirates | AE | AE[0-9]{2}[0-9]{3}[0-9]{16} | 23 | AE070331234567890123456
-United Kingdom | GB | GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8} | 22 | GB29NWBK60161331926819
-Virgin Islands, British | VG | VG[0-9]{2}[A-Z]{4}[0-9]{16} | 24 | VG96VPVG0000012345678901
diff --git a/bower.json b/bower.json
index 37aa93f..83c108c 100644
--- a/bower.json
+++ b/bower.json
@@ -1,6 +1,6 @@
{
"name": "ng-iban",
- "version": "0.3.2",
+ "version": "0.4.0",
"authors": [
"Mark Manders "
],
@@ -25,6 +25,7 @@
"angular": ">=1 <2"
},
"devDependencies": {
- "angular-mocks": ">=1 <2"
+ "angular-mocks": ">=1 <2",
+ "iban": "~0.0.5"
}
}
diff --git a/dist/ng-iban.js b/dist/ng-iban.js
index c3b8e57..a368f0e 100644
--- a/dist/ng-iban.js
+++ b/dist/ng-iban.js
@@ -1,273 +1,13 @@
+(function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o= A && code <= Z) {
- return code - A + 10;
- } else {
- return n;
- }
- }).join('');
- while (remainder.length > 2) {
- block = remainder.slice(0, 9);
- remainder = __modulo(parseInt(block, 10), 97) + remainder.slice(block.length);
- }
- return __modulo(parseInt(remainder, 10), 97) === 1;
+ return self.IBAN.isValid(iban);
};
ctrl.$parsers.unshift(function(viewValue) {
var parsed, valid;
@@ -342,6 +63,410 @@
});
}
};
- }]);
+ });
}).call(this);
+
+},{"./..\\bower_components\\iban\\iban.js":2}],2:[function(require,module,exports){
+(function(exports){
+
+ // Array.prototype.map polyfill
+ // code from https://developer.mozilla.org/en-US/docs/JavaScript/Reference/Global_Objects/Array/map
+ if (!Array.prototype.map){
+ Array.prototype.map = function(fun /*, thisArg */){
+ "use strict";
+
+ if (this === void 0 || this === null)
+ throw new TypeError();
+
+ var t = Object(this);
+ var len = t.length >>> 0;
+ if (typeof fun !== "function")
+ throw new TypeError();
+
+ var res = new Array(len);
+ var thisArg = arguments.length >= 2 ? arguments[1] : void 0;
+ for (var i = 0; i < len; i++)
+ {
+ // NOTE: Absolute correctness would demand Object.defineProperty
+ // be used. But this method is fairly new, and failure is
+ // possible only if Object.prototype or Array.prototype
+ // has a property |i| (very unlikely), so use a less-correct
+ // but more portable alternative.
+ if (i in t)
+ res[i] = fun.call(thisArg, t[i], i, t);
+ }
+
+ return res;
+ };
+ }
+
+ var A = 'A'.charCodeAt(0),
+ Z = 'Z'.charCodeAt(0);
+
+ /**
+ * Prepare an IBAN for mod 97 computation by moving the first 4 chars to the end and transforming the letters to
+ * numbers (A = 10, B = 11, ..., Z = 35), as specified in ISO13616.
+ *
+ * @param {string} iban the IBAN
+ * @returns {string} the prepared IBAN
+ */
+ function iso13616Prepare(iban) {
+ iban = iban.toUpperCase();
+ iban = iban.substr(4) + iban.substr(0,4);
+
+ return iban.split('').map(function(n){
+ var code = n.charCodeAt(0);
+ if (code >= A && code <= Z){
+ // A = 10, B = 11, ... Z = 35
+ return code - A + 10;
+ } else {
+ return n;
+ }
+ }).join('');
+ }
+
+ /**
+ * Calculates the MOD 97 10 of the passed IBAN as specified in ISO7064.
+ *
+ * @param iban
+ * @returns {number}
+ */
+ function iso7064Mod97_10(iban) {
+ var remainder = iban,
+ block;
+
+ while (remainder.length > 2){
+ block = remainder.slice(0, 9);
+ remainder = parseInt(block, 10) % 97 + remainder.slice(block.length);
+ }
+
+ return parseInt(remainder, 10) % 97;
+ }
+
+ /**
+ * Parse the BBAN structure used to configure each IBAN Specification and returns a matching regular expression.
+ * A structure is composed of blocks of 3 characters (one letter and 2 digits). Each block represents
+ * a logical group in the typical representation of the BBAN. For each group, the letter indicates which characters
+ * are allowed in this group and the following 2-digits number tells the length of the group.
+ *
+ * @param {string} structure the structure to parse
+ * @returns {RegExp}
+ */
+ function parseStructure(structure){
+ // split in blocks of 3 chars
+ var regex = structure.match(/(.{3})/g).map(function(block){
+
+ // parse each structure block (1-char + 2-digits)
+ var format,
+ pattern = block.slice(0, 1),
+ repeats = parseInt(block.slice(1), 10);
+
+ switch (pattern){
+ case "A": format = "0-9A-Za-z"; break;
+ case "B": format = "0-9A-Z"; break;
+ case "C": format = "A-Za-z"; break;
+ case "F": format = "0-9"; break;
+ case "L": format = "a-z"; break;
+ case "U": format = "A-Z"; break;
+ case "W": format = "0-9a-z"; break;
+ }
+
+ return '([' + format + ']{' + repeats + '})';
+ });
+
+ return new RegExp('^' + regex.join('') + '$');
+ }
+
+ /**
+ * Create a new Specification for a valid IBAN number.
+ *
+ * @param countryCode the code of the country
+ * @param length the length of the IBAN
+ * @param structure the structure of the undernying BBAN (for validation and formatting)
+ * @param example an example valid IBAN
+ * @constructor
+ */
+ function Specification(countryCode, length, structure, example){
+
+ this.countryCode = countryCode;
+ this.length = length;
+ this.structure = structure;
+ this.example = example;
+ }
+
+ /**
+ * Lazy-loaded regex (parse the structure and construct the regular expression the first time we need it for validation)
+ */
+ Specification.prototype._regex = function(){
+ return this._cachedRegex || (this._cachedRegex = parseStructure(this.structure))
+ };
+
+ /**
+ * Check if the passed iban is valid according to this specification.
+ *
+ * @param {String} iban the iban to validate
+ * @returns {boolean} true if valid, false otherwise
+ */
+ Specification.prototype.isValid = function(iban){
+ return this.length == iban.length
+ && this.countryCode === iban.slice(0,2)
+ && this._regex().test(iban.slice(4))
+ && iso7064Mod97_10(iso13616Prepare(iban)) == 1;
+ };
+
+ /**
+ * Convert the passed IBAN to a country-specific BBAN.
+ *
+ * @param iban the IBAN to convert
+ * @param separator the separator to use between BBAN blocks
+ * @returns {string} the BBAN
+ */
+ Specification.prototype.toBBAN = function(iban, separator) {
+ return this._regex().exec(iban.slice(4)).slice(1).join(separator);
+ };
+
+ /**
+ * Convert the passed BBAN to an IBAN for this country specification.
+ * Please note that "generation of the IBAN shall be the exclusive responsibility of the bank/branch servicing the account".
+ * This method implements the preferred algorithm described in http://en.wikipedia.org/wiki/International_Bank_Account_Number#Generating_IBAN_check_digits
+ *
+ * @param bban the BBAN to convert to IBAN
+ * @returns {string} the IBAN
+ */
+ Specification.prototype.fromBBAN = function(bban) {
+ if (!this.isValidBBAN(bban)){
+ throw new Error('Invalid BBAN');
+ }
+
+ var remainder = iso7064Mod97_10(iso13616Prepare(this.countryCode + '00' + bban)),
+ checkDigit = ('0' + (98 - remainder)).slice(-2);
+
+ return this.countryCode + checkDigit + bban;
+ };
+
+ /**
+ * Check of the passed BBAN is valid.
+ * This function only checks the format of the BBAN (length and matching the letetr/number specs) but does not
+ * verify the check digit.
+ *
+ * @param bban the BBAN to validate
+ * @returns {boolean} true if the passed bban is a valid BBAN according to this specification, false otherwise
+ */
+ Specification.prototype.isValidBBAN = function(bban) {
+ return this.length - 4 == bban.length
+ && this._regex().test(bban);
+ };
+
+ var countries = {};
+
+ function addSpecification(IBAN){
+ countries[IBAN.countryCode] = IBAN;
+ }
+
+ addSpecification(new Specification("AD", 24, "F04F04A12", "AD1200012030200359100100"));
+ addSpecification(new Specification("AE", 23, "F03F16", "AE070331234567890123456"));
+ addSpecification(new Specification("AL", 28, "F08A16", "AL47212110090000000235698741"));
+ addSpecification(new Specification("AT", 20, "F05F11", "AT611904300234573201"));
+ addSpecification(new Specification("AZ", 28, "U04A20", "AZ21NABZ00000000137010001944"));
+ addSpecification(new Specification("BA", 20, "F03F03F08F02", "BA391290079401028494"));
+ addSpecification(new Specification("BE", 16, "F03F07F02", "BE68539007547034"));
+ addSpecification(new Specification("BG", 22, "U04F04F02A08", "BG80BNBG96611020345678"));
+ addSpecification(new Specification("BH", 22, "U04A14", "BH67BMAG00001299123456"));
+ addSpecification(new Specification("BR", 29, "F08F05F10U01A01", "BR9700360305000010009795493P1"));
+ addSpecification(new Specification("CH", 21, "F05A12", "CH9300762011623852957"));
+ addSpecification(new Specification("CR", 21, "F03F14", "CR0515202001026284066"));
+ addSpecification(new Specification("CY", 28, "F03F05A16", "CY17002001280000001200527600"));
+ addSpecification(new Specification("CZ", 24, "F04F06F10", "CZ6508000000192000145399"));
+ addSpecification(new Specification("DE", 22, "F08F10", "DE89370400440532013000"));
+ addSpecification(new Specification("DK", 18, "F04F09F01", "DK5000400440116243"));
+ addSpecification(new Specification("DO", 28, "U04F20", "DO28BAGR00000001212453611324"));
+ addSpecification(new Specification("EE", 20, "F02F02F11F01", "EE382200221020145685"));
+ addSpecification(new Specification("ES", 24, "F04F04F01F01F10", "ES9121000418450200051332"));
+ addSpecification(new Specification("FI", 18, "F06F07F01", "FI2112345600000785"));
+ addSpecification(new Specification("FO", 18, "F04F09F01", "FO6264600001631634"));
+ addSpecification(new Specification("FR", 27, "F05F05A11F02", "FR1420041010050500013M02606"));
+ addSpecification(new Specification("GB", 22, "U04F06F08", "GB29NWBK60161331926819"));
+ addSpecification(new Specification("GE", 22, "U02F16", "GE29NB0000000101904917"));
+ addSpecification(new Specification("GI", 23, "U04A15", "GI75NWBK000000007099453"));
+ addSpecification(new Specification("GL", 18, "F04F09F01", "GL8964710001000206"));
+ addSpecification(new Specification("GR", 27, "F03F04A16", "GR1601101250000000012300695"));
+ addSpecification(new Specification("GT", 28, "A04A20", "GT82TRAJ01020000001210029690"));
+ addSpecification(new Specification("HR", 21, "F07F10", "HR1210010051863000160"));
+ addSpecification(new Specification("HU", 28, "F03F04F01F15F01", "HU42117730161111101800000000"));
+ addSpecification(new Specification("IE", 22, "U04F06F08", "IE29AIBK93115212345678"));
+ addSpecification(new Specification("IL", 23, "F03F03F13", "IL620108000000099999999"));
+ addSpecification(new Specification("IS", 26, "F04F02F06F10", "IS140159260076545510730339"));
+ addSpecification(new Specification("IT", 27, "U01F05F05A12", "IT60X0542811101000000123456"));
+ addSpecification(new Specification("KW", 30, "U04A22", "KW81CBKU0000000000001234560101"));
+ addSpecification(new Specification("KZ", 20, "F03A13", "KZ86125KZT5004100100"));
+ addSpecification(new Specification("LB", 28, "F04A20", "LB62099900000001001901229114"));
+ addSpecification(new Specification("LI", 21, "F05A12", "LI21088100002324013AA"));
+ addSpecification(new Specification("LT", 20, "F05F11", "LT121000011101001000"));
+ addSpecification(new Specification("LU", 20, "F03A13", "LU280019400644750000"));
+ addSpecification(new Specification("LV", 21, "U04A13", "LV80BANK0000435195001"));
+ addSpecification(new Specification("MC", 27, "F05F05A11F02", "MC5811222000010123456789030"));
+ addSpecification(new Specification("MD", 24, "U02F18", "MD24AG000225100013104168"));
+ addSpecification(new Specification("ME", 22, "F03F13F02", "ME25505000012345678951"));
+ addSpecification(new Specification("MK", 19, "F03A10F02", "MK07250120000058984"));
+ addSpecification(new Specification("MR", 27, "F05F05F11F02", "MR1300020001010000123456753"));
+ addSpecification(new Specification("MT", 31, "U04F05A18", "MT84MALT011000012345MTLCAST001S"));
+ addSpecification(new Specification("MU", 30, "U04F02F02F12F03U03", "MU17BOMM0101101030300200000MUR"));
+ addSpecification(new Specification("NL", 18, "U04F10", "NL91ABNA0417164300"));
+ addSpecification(new Specification("NO", 15, "F04F06F01", "NO9386011117947"));
+ addSpecification(new Specification("PK", 24, "U04A16", "PK36SCBL0000001123456702"));
+ addSpecification(new Specification("PL", 28, "F08F16", "PL61109010140000071219812874"));
+ addSpecification(new Specification("PS", 29, "U04A21", "PS92PALS000000000400123456702"));
+ addSpecification(new Specification("PT", 25, "F04F04F11F02", "PT50000201231234567890154"));
+ addSpecification(new Specification("RO", 24, "U04A16", "RO49AAAA1B31007593840000"));
+ addSpecification(new Specification("RS", 22, "F03F13F02", "RS35260005601001611379"));
+ addSpecification(new Specification("SA", 24, "F02A18", "SA0380000000608010167519"));
+ addSpecification(new Specification("SE", 24, "F03F16F01", "SE4550000000058398257466"));
+ addSpecification(new Specification("SI", 19, "F05F08F02", "SI56263300012039086"));
+ addSpecification(new Specification("SK", 24, "F04F06F10", "SK3112000000198742637541"));
+ addSpecification(new Specification("SM", 27, "U01F05F05A12", "SM86U0322509800000000270100"));
+ addSpecification(new Specification("TN", 24, "F02F03F13F02", "TN5910006035183598478831"));
+ addSpecification(new Specification("TR", 26, "F05A01A16", "TR330006100519786457841326"));
+ addSpecification(new Specification("VG", 24, "U04F16", "VG96VPVG0000012345678901"));
+
+ // Angola
+ addSpecification(new Specification("AO", 25, "F21", "AO69123456789012345678901"));
+ // Burkina
+ addSpecification(new Specification("BF", 27, "F23", "BF2312345678901234567890123"));
+ // Burundi
+ addSpecification(new Specification("BI", 16, "F12", "BI41123456789012"));
+ // Benin
+ addSpecification(new Specification("BJ", 28, "F24", "BJ39123456789012345678901234"));
+ // Ivory
+ addSpecification(new Specification("CI", 28, "U01F23", "CI17A12345678901234567890123"));
+ // Cameron
+ addSpecification(new Specification("CM", 27, "F23", "CM9012345678901234567890123"));
+ // Cape Verde
+ addSpecification(new Specification("CV", 25, "F21", "CV30123456789012345678901"));
+ // Algeria
+ addSpecification(new Specification("DZ", 24, "F20", "DZ8612345678901234567890"));
+ // Iran
+ addSpecification(new Specification("IR", 26, "F22", "IR861234568790123456789012"));
+ // Jordan
+ addSpecification(new Specification("JO", 30, "A04F22", "JO15AAAA1234567890123456789012"));
+ // Madagascar
+ addSpecification(new Specification("MG", 27, "F23", "MG1812345678901234567890123"));
+ // Mali
+ addSpecification(new Specification("ML", 28, "U01F23", "ML15A12345678901234567890123"));
+ // Mozambique
+ addSpecification(new Specification("MZ", 25, "F21", "MZ25123456789012345678901"));
+ // Quatar
+ addSpecification(new Specification("QA", 29, "U04A21", "QA30AAAA123456789012345678901"));
+ // Senegal
+ addSpecification(new Specification("SN", 28, "U01F23", "SN52A12345678901234567890123"));
+ // Ukraine
+ addSpecification(new Specification("UA", 29, "F25", "UA511234567890123456789012345"));
+
+ var NON_ALPHANUM = /[^a-zA-Z0-9]/g,
+ EVERY_FOUR_CHARS =/(.{4})(?!$)/g;
+
+ /**
+ * Utility function to check if a variable is a String.
+ *
+ * @param v
+ * @returns {boolean} true if the passed variable is a String, false otherwise.
+ */
+ function isString(v){
+ return (typeof v == 'string' || v instanceof String);
+ }
+
+ /**
+ * Check if an IBAN is valid.
+ *
+ * @param {String} iban the IBAN to validate.
+ * @returns {boolean} true if the passed IBAN is valid, false otherwise
+ */
+ exports.isValid = function(iban){
+ if (!isString(iban)){
+ return false;
+ }
+ iban = this.electronicFormat(iban);
+ var countryStructure = countries[iban.slice(0,2)];
+ return !!countryStructure && countryStructure.isValid(iban);
+ };
+
+ /**
+ * Convert an IBAN to a BBAN.
+ *
+ * @param iban
+ * @param {String} [separator] the separator to use between the blocks of the BBAN, defaults to ' '
+ * @returns {string|*}
+ */
+ exports.toBBAN = function(iban, separator){
+ if (typeof separator == 'undefined'){
+ separator = ' ';
+ }
+ iban = this.electronicFormat(iban);
+ var countryStructure = countries[iban.slice(0,2)];
+ if (!countryStructure) {
+ throw new Error('No country with code ' + iban.slice(0,2));
+ }
+ return countryStructure.toBBAN(iban, separator);
+ };
+
+ /**
+ * Convert the passed BBAN to an IBAN for this country specification.
+ * Please note that "generation of the IBAN shall be the exclusive responsibility of the bank/branch servicing the account".
+ * This method implements the preferred algorithm described in http://en.wikipedia.org/wiki/International_Bank_Account_Number#Generating_IBAN_check_digits
+ *
+ * @param countryCode the country of the BBAN
+ * @param bban the BBAN to convert to IBAN
+ * @returns {string} the IBAN
+ */
+ exports.fromBBAN = function(countryCode, bban){
+ var countryStructure = countries[countryCode];
+ if (!countryStructure) {
+ throw new Error('No country with code ' + countryCode);
+ }
+ return countryStructure.fromBBAN(this.electronicFormat(bban));
+ };
+
+ /**
+ * Check the validity of the passed BBAN.
+ *
+ * @param countryCode the country of the BBAN
+ * @param bban the BBAN to check the validity of
+ */
+ exports.isValidBBAN = function(countryCode, bban){
+ if (!isString(bban)){
+ return false;
+ }
+ var countryStructure = countries[countryCode];
+ return countryStructure && countryStructure.isValidBBAN(this.electronicFormat(bban));
+ };
+
+ /**
+ *
+ * @param iban
+ * @param separator
+ * @returns {string}
+ */
+ exports.printFormat = function(iban, separator){
+ if (typeof separator == 'undefined'){
+ separator = ' ';
+ }
+ return this.electronicFormat(iban).replace(EVERY_FOUR_CHARS, "$1" + separator);
+ };
+
+ /**
+ *
+ * @param iban
+ * @returns {string}
+ */
+ exports.electronicFormat = function(iban){
+ return iban.replace(NON_ALPHANUM, '').toUpperCase();
+ };
+
+ /**
+ * An object containing all the known IBAN specifications.
+ */
+ exports.countries = countries;
+
+})(typeof exports == 'undefined' ? this.IBAN = {} : exports);
+
+},{}]},{},[1]);
diff --git a/dist/ng-iban.min.js b/dist/ng-iban.min.js
index aac8b9d..eeb40bb 100644
--- a/dist/ng-iban.min.js
+++ b/dist/ng-iban.min.js
@@ -1 +1 @@
-(function(){"use strict";var a=function(a,b){return(a%b+ +b)%b};angular.module("mm.iban",["ng"]).constant("ngIbanCountries",{AL:{name:"Albania",regex:/^AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}$/},AD:{name:"Andorra",regex:/^AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}$/},AT:{name:"Austria",regex:/^AT[0-9]{2}[0-9]{5}[0-9]{11}$/},AZ:{name:"Azerbaijan, Republic of",regex:/^AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}$/},BH:{name:"Bahrain",regex:/^BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}$/},BE:{name:"Belgium",regex:/^BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}$/},BA:{name:"Bosnia and Herzegovina",regex:/^BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}$/},BR:{name:"Brazil",regex:/^BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z]{1}[A-Z0-9]{1}$/},BG:{name:"Bulgaria",regex:/^BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}$/},CR:{name:"Costa Rica",regex:/^CR[0-9]{2}[0-9]{3}[0-9]{14}$/},HR:{name:"Croatia",regex:/^HR[0-9]{2}[0-9]{7}[0-9]{10}$/},CY:{name:"Cyprus",regex:/^CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}$/},CZ:{name:"Czech Republic",regex:/^CZ[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}$/},DK:{name:"Denmark",regex:/^DK[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}$/},DO:{name:"Dominican Republic",regex:/^DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}$/},EE:{name:"Estonia",regex:/^EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}$/},FO:{name:"Faroe Islands",regex:/^FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}$/},FI:{name:"Finland",regex:/^FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}$/},FR:{name:"France",regex:/^FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}$/},GE:{name:"Georgia",regex:/^GE[0-9]{2}[A-Z]{2}[0-9]{16}$/},DE:{name:"Germany",regex:/^DE[0-9]{2}[0-9]{8}[0-9]{10}$/},GI:{name:"Gibraltar",regex:/^GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}$/},GR:{name:"Greece",regex:/^GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}$/},GL:{name:"Greenland",regex:/^GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}$/},GT:{name:"Guatemala",regex:/^GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}$/},HU:{name:"Hungary",regex:/^HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}$/},IS:{name:"Iceland",regex:/^IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}$/},IE:{name:"Ireland",regex:/^IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}$/},IL:{name:"Israel",regex:/^IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}$/},IT:{name:"Italy",regex:/^IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}$/},KZ:{name:"Kazakhstan",regex:/^KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}$/},KW:{name:"Kuwait",regex:/^KW[0-9]{2}[A-Z]{4}[A-Z0-9]{22}$/},LV:{name:"Latvia",regex:/^LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}$/},LB:{name:"Lebanon",regex:/^LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}$/},LI:{name:"Liechtenstein (Principality of)",regex:/^LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}$/},LT:{name:"Lithuania",regex:/^LT[0-9]{2}[0-9]{5}[0-9]{11}$/},LU:{name:"Luxembourg",regex:/^LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}$/},MK:{name:"Macedonia",regex:/^MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}$/},MT:{name:"Malta",regex:/^MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}$/},MR:{name:"Mauritania",regex:/^MR[0-9]{2}[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}$/},MU:{name:"Mauritius",regex:/^MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}$/},MD:{name:"Moldova, Republic of",regex:/^MD[0-9]{2}[A-Z0-9]{20}$/},MC:{name:"Monaco",regex:/^MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}$/},ME:{name:"Montenegro",regex:/^ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}$/},NL:{name:"Netherlands",regex:/^NL[0-9]{2}[A-Z]{4}[0-9]{10}$/},NO:{name:"Norway",regex:/^NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}$/},PK:{name:"Pakistan",regex:/^PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}$/},PL:{name:"Poland",regex:/^PL[0-9]{2}[0-9]{8}[0-9]{16}$/},PS:{name:"Palestinian Territory, Occupied",regex:/^PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}$/},PT:{name:"Portugal",regex:/^PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}$/},QA:{name:"Qatar",regex:/^QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}$/},RO:{name:"Romania",regex:/^RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}$/},SM:{name:"San Marino",regex:/^SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}$/},SA:{name:"Saudi Arabia",regex:/^SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}$/},RS:{name:"Serbia",regex:/^RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}$/},SK:{name:"Slovak Republic",regex:/^SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}$/},SI:{name:"Slovenia",regex:/^SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}$/},ES:{name:"Spain",regex:/^ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}$/},SE:{name:"Sweden",regex:/^SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}$/},CH:{name:"Switzerland",regex:/^CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}$/},TL:{name:"Timor-Leste",regex:/^TL[0-9]{2}[0-9]{3}[0-9]{14}[0-9]{2}$/},TN:{name:"Tunisia",regex:/^TN[0-9]{2}[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}$/},TR:{name:"Turkey",regex:/^TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}$/},AE:{name:"United Arab Emirates",regex:/^AE[0-9]{2}[0-9]{3}[0-9]{16}$/},GB:{name:"United Kingdom",regex:/^GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}$/},VG:{name:"Virgin Islands, British",regex:/^VG[0-9]{2}[A-Z]{4}[0-9]{16}$/}}).directive("ngIban",["ngIbanCountries",function(b){return{restrict:"A",require:"ngModel",link:function(c,d,e,f){var g,h;return h=function(a){return null!=a?a.toUpperCase().replace(/\s/g,""):void 0},g=function(c){var d,f,g,i,j;if(!e.required&&!c)return!0;if(d="A".charCodeAt(0),f="Z".charCodeAt(0),i=h(c),!(""===e.ngIban||e.ngIban in b&&b[e.ngIban].regex.test(i)))return!1;for(i=i.substr(4)+i.substr(0,4),j=i.split("").map(function(a){var b;return b=a.charCodeAt(0),b>=d&&f>=b?b-d+10:a}).join("");j.length>2;)g=j.slice(0,9),j=a(parseInt(g,10),97)+j.slice(g.length);return 1===a(parseInt(j,10),97)},f.$parsers.unshift(function(a){var b,c;return null!=a?(c=g(a),f.$setValidity("iban",c),c?(b=h(a),b!==a&&(f.$setViewValue(b),f.$render()),b):void 0):void 0}),f.$formatters.unshift(function(a){var b,d;return null!=a?(d=g(a),f.$setValidity("iban",d),d?(b=h(a),b!==a&&(c[e.ngModel]=b),b):a):void 0})}}}])}).call(this);
\ No newline at end of file
+!function a(b,c,d){function e(g,h){if(!c[g]){if(!b[g]){var i="function"==typeof require&&require;if(!h&&i)return i(g,!0);if(f)return f(g,!0);var j=new Error("Cannot find module '"+g+"'");throw j.code="MODULE_NOT_FOUND",j}var k=c[g]={exports:{}};b[g][0].call(k.exports,function(a){var c=b[g][1][a];return e(c?c:a)},k,k.exports,a,b,c,d)}return c[g].exports}for(var f="function"==typeof require&&require,g=0;g=h&&i>=b?b-h+10:a}).join("")}function c(a){for(var b,c=a;c.length>2;)b=c.slice(0,9),c=parseInt(b,10)%97+c.slice(b.length);return parseInt(c,10)%97}function d(a){var b=a.match(/(.{3})/g).map(function(a){var b,c=a.slice(0,1),d=parseInt(a.slice(1),10);switch(c){case"A":b="0-9A-Za-z";break;case"B":b="0-9A-Z";break;case"C":b="A-Za-z";break;case"F":b="0-9";break;case"L":b="a-z";break;case"U":b="A-Z";break;case"W":b="0-9a-z"}return"(["+b+"]{"+d+"})"});return new RegExp("^"+b.join("")+"$")}function e(a,b,c,d){this.countryCode=a,this.length=b,this.structure=c,this.example=d}function f(a){j[a.countryCode]=a}function g(a){return"string"==typeof a||a instanceof String}Array.prototype.map||(Array.prototype.map=function(a){"use strict";if(void 0===this||null===this)throw new TypeError;var b=Object(this),c=b.length>>>0;if("function"!=typeof a)throw new TypeError;for(var d=new Array(c),e=arguments.length>=2?arguments[1]:void 0,f=0;c>f;f++)f in b&&(d[f]=a.call(e,b[f],f,b));return d});var h="A".charCodeAt(0),i="Z".charCodeAt(0);e.prototype._regex=function(){return this._cachedRegex||(this._cachedRegex=d(this.structure))},e.prototype.isValid=function(a){return this.length==a.length&&this.countryCode===a.slice(0,2)&&this._regex().test(a.slice(4))&&1==c(b(a))},e.prototype.toBBAN=function(a,b){return this._regex().exec(a.slice(4)).slice(1).join(b)},e.prototype.fromBBAN=function(a){if(!this.isValidBBAN(a))throw new Error("Invalid BBAN");var d=c(b(this.countryCode+"00"+a)),e=("0"+(98-d)).slice(-2);return this.countryCode+e+a},e.prototype.isValidBBAN=function(a){return this.length-4==a.length&&this._regex().test(a)};var j={};f(new e("AD",24,"F04F04A12","AD1200012030200359100100")),f(new e("AE",23,"F03F16","AE070331234567890123456")),f(new e("AL",28,"F08A16","AL47212110090000000235698741")),f(new e("AT",20,"F05F11","AT611904300234573201")),f(new e("AZ",28,"U04A20","AZ21NABZ00000000137010001944")),f(new e("BA",20,"F03F03F08F02","BA391290079401028494")),f(new e("BE",16,"F03F07F02","BE68539007547034")),f(new e("BG",22,"U04F04F02A08","BG80BNBG96611020345678")),f(new e("BH",22,"U04A14","BH67BMAG00001299123456")),f(new e("BR",29,"F08F05F10U01A01","BR9700360305000010009795493P1")),f(new e("CH",21,"F05A12","CH9300762011623852957")),f(new e("CR",21,"F03F14","CR0515202001026284066")),f(new e("CY",28,"F03F05A16","CY17002001280000001200527600")),f(new e("CZ",24,"F04F06F10","CZ6508000000192000145399")),f(new e("DE",22,"F08F10","DE89370400440532013000")),f(new e("DK",18,"F04F09F01","DK5000400440116243")),f(new e("DO",28,"U04F20","DO28BAGR00000001212453611324")),f(new e("EE",20,"F02F02F11F01","EE382200221020145685")),f(new e("ES",24,"F04F04F01F01F10","ES9121000418450200051332")),f(new e("FI",18,"F06F07F01","FI2112345600000785")),f(new e("FO",18,"F04F09F01","FO6264600001631634")),f(new e("FR",27,"F05F05A11F02","FR1420041010050500013M02606")),f(new e("GB",22,"U04F06F08","GB29NWBK60161331926819")),f(new e("GE",22,"U02F16","GE29NB0000000101904917")),f(new e("GI",23,"U04A15","GI75NWBK000000007099453")),f(new e("GL",18,"F04F09F01","GL8964710001000206")),f(new e("GR",27,"F03F04A16","GR1601101250000000012300695")),f(new e("GT",28,"A04A20","GT82TRAJ01020000001210029690")),f(new e("HR",21,"F07F10","HR1210010051863000160")),f(new e("HU",28,"F03F04F01F15F01","HU42117730161111101800000000")),f(new e("IE",22,"U04F06F08","IE29AIBK93115212345678")),f(new e("IL",23,"F03F03F13","IL620108000000099999999")),f(new e("IS",26,"F04F02F06F10","IS140159260076545510730339")),f(new e("IT",27,"U01F05F05A12","IT60X0542811101000000123456")),f(new e("KW",30,"U04A22","KW81CBKU0000000000001234560101")),f(new e("KZ",20,"F03A13","KZ86125KZT5004100100")),f(new e("LB",28,"F04A20","LB62099900000001001901229114")),f(new e("LI",21,"F05A12","LI21088100002324013AA")),f(new e("LT",20,"F05F11","LT121000011101001000")),f(new e("LU",20,"F03A13","LU280019400644750000")),f(new e("LV",21,"U04A13","LV80BANK0000435195001")),f(new e("MC",27,"F05F05A11F02","MC5811222000010123456789030")),f(new e("MD",24,"U02F18","MD24AG000225100013104168")),f(new e("ME",22,"F03F13F02","ME25505000012345678951")),f(new e("MK",19,"F03A10F02","MK07250120000058984")),f(new e("MR",27,"F05F05F11F02","MR1300020001010000123456753")),f(new e("MT",31,"U04F05A18","MT84MALT011000012345MTLCAST001S")),f(new e("MU",30,"U04F02F02F12F03U03","MU17BOMM0101101030300200000MUR")),f(new e("NL",18,"U04F10","NL91ABNA0417164300")),f(new e("NO",15,"F04F06F01","NO9386011117947")),f(new e("PK",24,"U04A16","PK36SCBL0000001123456702")),f(new e("PL",28,"F08F16","PL61109010140000071219812874")),f(new e("PS",29,"U04A21","PS92PALS000000000400123456702")),f(new e("PT",25,"F04F04F11F02","PT50000201231234567890154")),f(new e("RO",24,"U04A16","RO49AAAA1B31007593840000")),f(new e("RS",22,"F03F13F02","RS35260005601001611379")),f(new e("SA",24,"F02A18","SA0380000000608010167519")),f(new e("SE",24,"F03F16F01","SE4550000000058398257466")),f(new e("SI",19,"F05F08F02","SI56263300012039086")),f(new e("SK",24,"F04F06F10","SK3112000000198742637541")),f(new e("SM",27,"U01F05F05A12","SM86U0322509800000000270100")),f(new e("TN",24,"F02F03F13F02","TN5910006035183598478831")),f(new e("TR",26,"F05A01A16","TR330006100519786457841326")),f(new e("VG",24,"U04F16","VG96VPVG0000012345678901")),f(new e("AO",25,"F21","AO69123456789012345678901")),f(new e("BF",27,"F23","BF2312345678901234567890123")),f(new e("BI",16,"F12","BI41123456789012")),f(new e("BJ",28,"F24","BJ39123456789012345678901234")),f(new e("CI",28,"U01F23","CI17A12345678901234567890123")),f(new e("CM",27,"F23","CM9012345678901234567890123")),f(new e("CV",25,"F21","CV30123456789012345678901")),f(new e("DZ",24,"F20","DZ8612345678901234567890")),f(new e("IR",26,"F22","IR861234568790123456789012")),f(new e("JO",30,"A04F22","JO15AAAA1234567890123456789012")),f(new e("MG",27,"F23","MG1812345678901234567890123")),f(new e("ML",28,"U01F23","ML15A12345678901234567890123")),f(new e("MZ",25,"F21","MZ25123456789012345678901")),f(new e("QA",29,"U04A21","QA30AAAA123456789012345678901")),f(new e("SN",28,"U01F23","SN52A12345678901234567890123")),f(new e("UA",29,"F25","UA511234567890123456789012345"));var k=/[^a-zA-Z0-9]/g,l=/(.{4})(?!$)/g;a.isValid=function(a){if(!g(a))return!1;a=this.electronicFormat(a);var b=j[a.slice(0,2)];return!!b&&b.isValid(a)},a.toBBAN=function(a,b){"undefined"==typeof b&&(b=" "),a=this.electronicFormat(a);var c=j[a.slice(0,2)];if(!c)throw new Error("No country with code "+a.slice(0,2));return c.toBBAN(a,b)},a.fromBBAN=function(a,b){var c=j[a];if(!c)throw new Error("No country with code "+a);return c.fromBBAN(this.electronicFormat(b))},a.isValidBBAN=function(a,b){if(!g(b))return!1;var c=j[a];return c&&c.isValidBBAN(this.electronicFormat(b))},a.printFormat=function(a,b){return"undefined"==typeof b&&(b=" "),this.electronicFormat(a).replace(l,"$1"+b)},a.electronicFormat=function(a){return a.replace(k,"").toUpperCase()},a.countries=j}("undefined"==typeof c?this.IBAN={}:c)},{}]},{},[1]);
\ No newline at end of file
diff --git a/package.json b/package.json
index 6090952..9566a2d 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "ng-iban",
- "version": "0.3.2",
+ "version": "0.4.0",
"description": "IBAN directive for AngularJS",
"main": "./dist/ng-iban.js",
"scripts": {
@@ -23,7 +23,9 @@
},
"devDependencies": {
"coffee-script": "^1.7.1",
+ "debowerify": "^1.3.1",
"grunt": "^0.4.5",
+ "grunt-browserify": "^3.8.0",
"grunt-contrib-clean": "^0.5.0",
"grunt-contrib-coffee": "^0.10.1",
"grunt-contrib-connect": "^0.8.0",
diff --git a/src/ng-iban.coffee b/src/ng-iban.coffee
index 26da0b7..7d55d95 100644
--- a/src/ng-iban.coffee
+++ b/src/ng-iban.coffee
@@ -1,207 +1,12 @@
'use strict'
+@IBAN = require 'iban'
+
+self = @
+
angular
.module 'mm.iban', ['ng']
- .constant 'ngIbanCountries',
- AL:
- name: 'Albania'
- regex: /^AL[0-9]{2}[0-9]{8}[A-Z0-9]{16}$/
- AD:
- name: 'Andorra'
- regex: /^AD[0-9]{2}[0-9]{4}[0-9]{4}[A-Z0-9]{12}$/
- AT:
- name: 'Austria'
- regex: /^AT[0-9]{2}[0-9]{5}[0-9]{11}$/
- AZ:
- name: 'Azerbaijan, Republic of'
- regex: /^AZ[0-9]{2}[A-Z]{4}[A-Z0-9]{20}$/
- BH:
- name: 'Bahrain'
- regex: /^BH[0-9]{2}[A-Z]{4}[A-Z0-9]{14}$/
- BE:
- name: 'Belgium'
- regex: /^BE[0-9]{2}[0-9]{3}[0-9]{7}[0-9]{2}$/
- BA:
- name: 'Bosnia and Herzegovina'
- regex: /^BA[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{8}[0-9]{2}$/
- BR:
- name: 'Brazil'
- regex: /^BR[0-9]{2}[0-9]{8}[0-9]{5}[0-9]{10}[A-Z]{1}[A-Z0-9]{1}$/
- BG:
- name: 'Bulgaria'
- regex: /^BG[0-9]{2}[A-Z]{4}[0-9]{4}[0-9]{2}[A-Z0-9]{8}$/
- CR:
- name: 'Costa Rica'
- regex: /^CR[0-9]{2}[0-9]{3}[0-9]{14}$/
- HR:
- name: 'Croatia'
- regex: /^HR[0-9]{2}[0-9]{7}[0-9]{10}$/
- CY:
- name: 'Cyprus'
- regex: /^CY[0-9]{2}[0-9]{3}[0-9]{5}[A-Z0-9]{16}$/
- CZ:
- name: 'Czech Republic'
- regex: /^CZ[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}$/
- DK:
- name: 'Denmark'
- regex: /^DK[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}$/
- DO:
- name: 'Dominican Republic'
- regex: /^DO[0-9]{2}[A-Z0-9]{4}[0-9]{20}$/
- EE:
- name: 'Estonia'
- regex: /^EE[0-9]{2}[0-9]{2}[0-9]{2}[0-9]{11}[0-9]{1}$/
- FO:
- name: 'Faroe Islands'
- regex: /^FO[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}$/
- FI:
- name: 'Finland'
- regex: /^FI[0-9]{2}[0-9]{6}[0-9]{7}[0-9]{1}$/
- FR:
- name: 'France'
- regex: /^FR[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}$/
- GE:
- name: 'Georgia'
- regex: /^GE[0-9]{2}[A-Z]{2}[0-9]{16}$/
- DE:
- name: 'Germany'
- regex: /^DE[0-9]{2}[0-9]{8}[0-9]{10}$/
- GI:
- name: 'Gibraltar'
- regex: /^GI[0-9]{2}[A-Z]{4}[A-Z0-9]{15}$/
- GR:
- name: 'Greece'
- regex: /^GR[0-9]{2}[0-9]{3}[0-9]{4}[A-Z0-9]{16}$/
- GL:
- name: 'Greenland'
- regex: /^GL[0-9]{2}[0-9]{4}[0-9]{9}[0-9]{1}$/
- GT:
- name: 'Guatemala'
- regex: /^GT[0-9]{2}[A-Z0-9]{4}[A-Z0-9]{20}$/
- HU:
- name: 'Hungary'
- regex: /^HU[0-9]{2}[0-9]{3}[0-9]{4}[0-9]{1}[0-9]{15}[0-9]{1}$/
- IS:
- name: 'Iceland'
- regex: /^IS[0-9]{2}[0-9]{4}[0-9]{2}[0-9]{6}[0-9]{10}$/
- IE:
- name: 'Ireland'
- regex: /^IE[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}$/
- IL:
- name: 'Israel'
- regex: /^IL[0-9]{2}[0-9]{3}[0-9]{3}[0-9]{13}$/
- IT:
- name: 'Italy'
- regex: /^IT[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}$/
- KZ:
- name: 'Kazakhstan'
- regex: /^KZ[0-9]{2}[0-9]{3}[A-Z0-9]{13}$/
- KW:
- name: 'Kuwait'
- regex: /^KW[0-9]{2}[A-Z]{4}[A-Z0-9]{22}$/
- LV:
- name: 'Latvia'
- regex: /^LV[0-9]{2}[A-Z]{4}[A-Z0-9]{13}$/
- LB:
- name: 'Lebanon'
- regex: /^LB[0-9]{2}[0-9]{4}[A-Z0-9]{20}$/
- LI:
- name: 'Liechtenstein (Principality of)'
- regex: /^LI[0-9]{2}[0-9]{5}[A-Z0-9]{12}$/
- LT:
- name: 'Lithuania'
- regex: /^LT[0-9]{2}[0-9]{5}[0-9]{11}$/
- LU:
- name: 'Luxembourg'
- regex: /^LU[0-9]{2}[0-9]{3}[A-Z0-9]{13}$/
- MK:
- name: 'Macedonia'
- regex: /^MK[0-9]{2}[0-9]{3}[A-Z0-9]{10}[0-9]{2}$/
- MT:
- name: 'Malta'
- regex: /^MT[0-9]{2}[A-Z]{4}[0-9]{5}[A-Z0-9]{18}$/
- MR:
- name: 'Mauritania'
- regex: /^MR[0-9]{2}[0-9]{5}[0-9]{5}[0-9]{11}[0-9]{2}$/
- MU:
- name: 'Mauritius'
- regex: /^MU[0-9]{2}[A-Z]{4}[0-9]{2}[0-9]{2}[0-9]{12}[0-9]{3}[A-Z]{3}$/
- MD:
- name: 'Moldova, Republic of'
- regex: /^MD[0-9]{2}[A-Z0-9]{20}$/
- MC:
- name: 'Monaco'
- regex: /^MC[0-9]{2}[0-9]{5}[0-9]{5}[A-Z0-9]{11}[0-9]{2}$/
- ME:
- name: 'Montenegro'
- regex: /^ME[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}$/
- NL:
- name: 'Netherlands'
- regex: /^NL[0-9]{2}[A-Z]{4}[0-9]{10}$/
- NO:
- name: 'Norway'
- regex: /^NO[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{1}$/
- PK:
- name: 'Pakistan'
- regex: /^PK[0-9]{2}[A-Z]{4}[A-Z0-9]{16}$/
- PL:
- name: 'Poland'
- regex: /^PL[0-9]{2}[0-9]{8}[0-9]{16}$/
- PS:
- name: 'Palestinian Territory, Occupied'
- regex: /^PS[0-9]{2}[A-Z]{4}[A-Z0-9]{21}$/
- PT:
- name: 'Portugal'
- regex: /^PT[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{11}[0-9]{2}$/
- QA:
- name: 'Qatar'
- regex: /^QA[0-9]{2}[A-Z]{4}[A-Z0-9]{21}$/
- RO:
- name: 'Romania'
- regex: /^RO[0-9]{2}[A-Z]{4}[A-Z0-9]{16}$/
- SM:
- name: 'San Marino'
- regex: /^SM[0-9]{2}[A-Z]{1}[0-9]{5}[0-9]{5}[A-Z0-9]{12}$/
- SA:
- name: 'Saudi Arabia'
- regex: /^SA[0-9]{2}[0-9]{2}[A-Z0-9]{18}$/
- RS:
- name: 'Serbia'
- regex: /^RS[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}$/
- SK:
- name: 'Slovak Republic'
- regex: /^SK[0-9]{2}[0-9]{4}[0-9]{6}[0-9]{10}$/
- SI:
- name: 'Slovenia'
- regex: /^SI[0-9]{2}[0-9]{5}[0-9]{8}[0-9]{2}$/
- ES:
- name: 'Spain'
- regex: /^ES[0-9]{2}[0-9]{4}[0-9]{4}[0-9]{1}[0-9]{1}[0-9]{10}$/
- SE:
- name: 'Sweden'
- regex: /^SE[0-9]{2}[0-9]{3}[0-9]{16}[0-9]{1}$/
- CH:
- name: 'Switzerland'
- regex: /^CH[0-9]{2}[0-9]{5}[A-Z0-9]{12}$/
- TL:
- name: 'Timor-Leste'
- regex: /^TL[0-9]{2}[0-9]{3}[0-9]{14}[0-9]{2}$/
- TN:
- name: 'Tunisia'
- regex: /^TN[0-9]{2}[0-9]{2}[0-9]{3}[0-9]{13}[0-9]{2}$/
- TR:
- name: 'Turkey'
- regex: /^TR[0-9]{2}[0-9]{5}[A-Z0-9]{1}[A-Z0-9]{16}$/
- AE:
- name: 'United Arab Emirates'
- regex: /^AE[0-9]{2}[0-9]{3}[0-9]{16}$/
- GB:
- name: 'United Kingdom'
- regex: /^GB[0-9]{2}[A-Z]{4}[0-9]{6}[0-9]{8}$/
- VG:
- name: 'Virgin Islands, British'
- regex: /^VG[0-9]{2}[A-Z]{4}[0-9]{16}$/
- .directive 'ngIban', (ngIbanCountries) ->
+ .directive 'ngIban', ->
restrict: 'A'
require: 'ngModel'
link: (scope, elem, attrs, ctrl) ->
@@ -210,24 +15,9 @@ angular
isValidIban = (value) ->
return true if not(attrs.required or value)
- A = 'A'.charCodeAt 0
- Z = 'Z'.charCodeAt 0
iban = parseIban(value)
- return false if attrs.ngIban isnt '' and (not !!(attrs.ngIban of ngIbanCountries) or not ngIbanCountries[attrs.ngIban].regex.test iban)
-
- iban = iban.substr(4) + iban.substr 0, 4
-
- remainder = iban.split('').map (n) ->
- code = n.charCodeAt 0
- if code >= A and code <= Z then code - A + 10 else n
- .join ''
-
- while remainder.length > 2
- block = remainder.slice 0, 9
- remainder = parseInt(block, 10) %% 97 + remainder.slice block.length
-
- parseInt(remainder, 10) %% 97 is 1
+ self.IBAN.isValid iban
ctrl.$parsers.unshift (viewValue) ->
if viewValue?
diff --git a/test/karma.conf.coffee b/test/karma.conf.coffee
index 17cbfb2..a918e15 100644
--- a/test/karma.conf.coffee
+++ b/test/karma.conf.coffee
@@ -13,7 +13,7 @@ module.exports = (config) ->
files: [
'bower_components/angular/angular.js'
'bower_components/angular-mocks/angular-mocks.js'
- 'src/**/*.coffee'
+ '.tmp/**/*.js'
'test/spec/**/*.coffee'
],
diff --git a/test/spec/ng-iban.coffee b/test/spec/ng-iban.coffee
index 10c4376..633b426 100644
--- a/test/spec/ng-iban.coffee
+++ b/test/spec/ng-iban.coffee
@@ -16,8 +16,7 @@ describe 'Directive: iban', ->
compile('')(scope)
form = scope.form
@@ -63,12 +62,6 @@ describe 'Directive: iban', ->
expect(scope.iban).toEqual undefined
expect(form.iban.$valid).toBe false
- it 'invalidcountry should fail with invalid country code', ->
- form.invalidcountry.$setViewValue 'NL91 ABNA 0417 1643 00'
- scope.$digest()
- expect(scope.invalidcountry).toEqual undefined
- expect(form.invalidcountry.$valid).toBe false
-
it 'country should pass with valid IBAN', ->
form.country.$setViewValue 'NL91 ABNA 0417 1643 00'
scope.$digest()
diff --git a/wercker.yml b/wercker.yml
index 2ea83e9..ee480c5 100644
--- a/wercker.yml
+++ b/wercker.yml
@@ -1,10 +1,7 @@
-box: wercker/nodejs
+box: olger/box-yeoman
build:
steps:
- npm-install
- - npm-install:
- options: bower
- - plasticine/bower-install@0.0.4:
- tasks: bower-install
- - wercker/grunt@1.0.0:
- tasks: test
+ - olger/yeoman-bower-install
+ - grunt:
+ tasks: default