diff --git a/js/libphonenumber-util.js b/js/libphonenumber-util.js
index da399b93..4a57716b 100644
--- a/js/libphonenumber-util.js
+++ b/js/libphonenumber-util.js
@@ -34,20 +34,19 @@
return (cc !== 0) ? cc : "";
},
- verifyNumber: function(number, regionCode) {
- var parsedNumber = libphonenumber.parse(number, regionCode);
+ parseNumber: function(number, defaultRegionCode) {
+ try {
+ var parsedNumber = libphonenumber.parse(number, defaultRegionCode);
- if(!regionCode || regionCode == 'ZZ') {
- regionCode = libphonenumber.getRegionCodeForNumber(parsedNumber);
- }
-
- var isValidNumber = libphonenumber.isValidNumber(parsedNumber);
- var isValidNumberForRegion = libphonenumber.isValidNumberForRegion(parsedNumber, regionCode);
-
- if (isValidNumber && isValidNumberForRegion) {
- return libphonenumber.format(parsedNumber, libphonenumber.PhoneNumberFormat.E164);
- } else {
- throw new Error("The number seems not to be valid.");
+ return {
+ isValidNumber: libphonenumber.isValidNumber(parsedNumber),
+ regionCode: libphonenumber.getRegionCodeForNumber(parsedNumber),
+ countryCode: '' + parsedNumber.getCountryCode(),
+ nationalNumber: '' + parsedNumber.getNationalNumber(),
+ e164: libphonenumber.format(parsedNumber, libphonenumber.PhoneNumberFormat.E164)
+ };
+ } catch (ex) {
+ return { error: ex, isValidNumber: false };
}
},
diff --git a/js/models/conversations.js b/js/models/conversations.js
index 775ecb10..aad418f9 100644
--- a/js/models/conversations.js
+++ b/js/models/conversations.js
@@ -42,7 +42,6 @@
conversation: this
});
- this.on('change:id change:name', this.updateTokens);
this.on('change:avatar', this.updateAvatarUrl);
this.on('destroy', this.revokeAvatarUrl);
},
@@ -56,20 +55,20 @@
return "Invalid conversation type: " + attributes.type;
}
- if (!attributes.tokens) {
- return this.updateTokens();
- }
+ var error = this.validateNumber();
+ if (error) { return error; }
+
+ this.updateTokens();
},
validateNumber: function() {
- try {
- this.id = libphonenumber.util.verifyNumber(this.id);
- } catch (ex) {
- if (ex === "Invalid country calling code") {
- var regionCode = storage.get('regionCode');
- this.id = libphonenumber.util.verifyNumber(this.id, regionCode);
+ if (this.isPrivate()) {
+ var regionCode = storage.get('regionCode');
+ var number = libphonenumber.util.parseNumber(this.id, regionCode);
+ if (number.isValidNumber) {
+ this.set({ id: number.e164 });
} else {
- throw ex;
+ return number.error || "Invalid phone number";
}
}
},
@@ -78,26 +77,17 @@
var tokens = [];
var name = this.get('name');
if (typeof name === 'string') {
- tokens = name.trim().toLowerCase().split(/[\s\-_\(\)\+]+/);
+ tokens.push(name.toLowerCase());
+ tokens = tokens.concat(name.trim().toLowerCase().split(/[\s\-_\(\)\+]+/));
}
-
if (this.isPrivate()) {
- try {
- this.validateNumber();
- var number = libphonenumber.util.splitCountryCode(this.id);
- var international_number = '' + number.country_code + number.national_number;
- var national_number = '' + number.national_number;
-
- this.set({
- id: this.id,
- e164_number: this.id,
- national_number: national_number,
- international_number: international_number
- });
- tokens = tokens.concat(this.id, national_number, international_number);
- } catch(ex) {
- return ex;
- }
+ var regionCode = storage.get('regionCode');
+ var number = libphonenumber.util.parseNumber(this.id, regionCode);
+ tokens.push(
+ this.id,
+ number.nationalNumber,
+ number.countryCode + number.nationalNumber
+ );
}
this.set({tokens: tokens});
},
diff --git a/js/views/phone-input-view.js b/js/views/phone-input-view.js
index 812d5736..48c981e0 100644
--- a/js/views/phone-input-view.js
+++ b/js/views/phone-input-view.js
@@ -22,20 +22,18 @@
validateNumber: function() {
var input = this.$('input.number');
- try {
- var regionCode = this.$('li.active').attr('data-country-code').toUpperCase();
- var number = input.val();
-
- var parsedNumber = libphonenumber.util.verifyNumber(number, regionCode);
+ var regionCode = this.$('li.active').attr('data-country-code').toUpperCase();
+ var number = input.val();
+ var parsedNumber = libphonenumber.util.parseNumber(number, regionCode);
+ if (parsedNumber.isValidNumber) {
this.$('.number-container').removeClass('invalid');
this.$('.number-container').addClass('valid');
- return parsedNumber;
- } catch(e) {
+ return parsedNumber.e164;
+ } else {
this.$('.number-container').removeClass('valid');
- } finally {
- input.trigger('validation');
}
+ input.trigger('validation');
}
});
})();
diff --git a/test/index.html b/test/index.html
index 372690b3..2e92128e 100644
--- a/test/index.html
+++ b/test/index.html
@@ -127,6 +127,7 @@
+
diff --git a/test/libphonenumber_util_test.js b/test/libphonenumber_util_test.js
new file mode 100644
index 00000000..9e98bead
--- /dev/null
+++ b/test/libphonenumber_util_test.js
@@ -0,0 +1,29 @@
+/*
+ * vim: ts=4:sw=4:expandtab
+ */
+
+(function () {
+ 'use strict';
+ describe('libphonenumber util', function() {
+ describe('parseNumber', function() {
+ it('numbers with + are valid without providing regionCode', function() {
+ var result = libphonenumber.util.parseNumber('+14155555555');
+ assert.isTrue(result.isValidNumber);
+ assert.strictEqual(result.nationalNumber, '4155555555');
+ assert.strictEqual(result.e164, '+14155555555');
+ assert.strictEqual(result.regionCode, 'US');
+ assert.strictEqual(result.countryCode, '1');
+ });
+ it('variant numbers with the right regionCode are valid', function() {
+ [ '4155555555', '14155555555', '+14155555555', ].forEach(function(number) {
+ var result = libphonenumber.util.parseNumber(number, 'US');
+ assert.isTrue(result.isValidNumber);
+ assert.strictEqual(result.nationalNumber, '4155555555');
+ assert.strictEqual(result.e164, '+14155555555');
+ assert.strictEqual(result.regionCode, 'US');
+ assert.strictEqual(result.countryCode, '1');
+ });
+ });
+ });
+ });
+})();
diff --git a/test/models/conversations_test.js b/test/models/conversations_test.js
index bd4f7876..4e130f6f 100644
--- a/test/models/conversations_test.js
+++ b/test/models/conversations_test.js
@@ -153,6 +153,43 @@
convo.revokeAvatarUrl();
assert.notOk(convo.avatarUrl);
});
+
+ describe('phone number parsing', function() {
+ after(function() { storage.remove('regionCode'); });
+ function checkAttributes(number) {
+ var convo = new Whisper.ConversationCollection().add({type: 'private'});
+ convo.set('id', number);
+ convo.validate(convo.attributes);
+ assert.strictEqual(convo.get('id'), '+14155555555', number);
+ }
+ it('processes the phone number when validating', function() {
+ [ '+14155555555', ].forEach(checkAttributes);
+ });
+ it('defaults to the local regionCode', function() {
+ storage.put('regionCode', 'US');
+ [ '14155555555', '4155555555' ].forEach(checkAttributes);
+ });
+ it('works with common phone number formats', function() {
+ storage.put('regionCode', 'US');
+ [
+ '415 555 5555',
+ '415-555-5555',
+ '(415) 555 5555',
+ '(415) 555-5555',
+ '1 415 555 5555',
+ '1 415-555-5555',
+ '1 (415) 555 5555',
+ '1 (415) 555-5555',
+ '+1 415 555 5555',
+ '+1 415-555-5555',
+ '+1 (415) 555 5555',
+ '+1 (415) 555-5555',
+
+ ].forEach(checkAttributes);
+ });
+ });
+ });
+
});
})();;