UNPKG

intl-tel-input-libphonenumber

Version:
361 lines (331 loc) 15 kB
'use strict'; var i18n = require('libphonenumber-umd'); module.exports = { // copied this from i18n.phonenumbers.PhoneNumberType in https://code.google.com/p/libphonenumber/source/browse/trunk/javascript/i18n/phonenumbers/phonenumberutil.js and put the keys in quotes to force closure compiler to preserve the keys // TODO: there must be a way to just tell closure compiler to preserve the keys on i18n.phonenumbers.PhoneNumberType and just export that numberType: { "FIXED_LINE": 0, "MOBILE": 1, // In some regions (e.g. the USA), it is impossible to distinguish between // fixed-line and mobile numbers by looking at the phone number itself. "FIXED_LINE_OR_MOBILE": 2, // Freephone lines "TOLL_FREE": 3, "PREMIUM_RATE": 4, // The cost of this call is shared between the caller and the recipient, and // is hence typically less than PREMIUM_RATE calls. See // http://en.wikipedia.org/wiki/Shared_Cost_Service for more information. "SHARED_COST": 5, // Voice over IP numbers. This includes TSoIP (Telephony Service over IP). "VOIP": 6, // A personal number is associated with a particular person, and may be routed // to either a MOBILE or FIXED_LINE number. Some more information can be found // here: http://en.wikipedia.org/wiki/Personal_Numbers "PERSONAL_NUMBER": 7, "PAGER": 8, // Used for 'Universal Access Numbers' or 'Company Numbers'. They may be // further routed to specific offices, but allow one number to be used for a // company. "UAN": 9, // Used for 'Voice Mail Access Numbers'. "VOICEMAIL": 10, // A phone number is of type UNKNOWN when it does not fit any of the known // patterns for a specific region. "UNKNOWN": -1 }, // copied this from i18n.phonenumbers.PhoneNumberUtil.ValidationResult in https://code.google.com/p/libphonenumber/source/browse/trunk/javascript/i18n/phonenumbers/phonenumberutil.js and again put the keys in quotes. // Also: added NOT_A_NUMBER to match i18n.phonenumbers.Error.NOT_A_NUMBER validationError: { "IS_POSSIBLE": 0, "INVALID_COUNTRY_CODE": 1, "TOO_SHORT": 2, "TOO_LONG": 3, "NOT_A_NUMBER": 4 }, // copied this from https://github.com/googlei18n/libphonenumber/blob/master/javascript/i18n/phonenumbers/phonenumberutil.js#L883 numberFormat: { "E164": 0, "INTERNATIONAL": 1, "NATIONAL": 2, "RFC3966": 3 }, // get an example number for the given country code getExampleNumber: function (countryCode, national, numberType) { try { var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance(); var numberObj = phoneUtil.getExampleNumberForType(countryCode, numberType); var format = (national) ? i18n.phonenumbers.PhoneNumberFormat.NATIONAL : i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL; return phoneUtil.format(numberObj, format); } catch (e) { return ""; } }, // format the given number to the given type formatNumberByType: function (number, countryCode, type) { try { var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance(); var numberObj = phoneUtil.parseAndKeepRawInput(number, countryCode); type = (typeof type == "undefined") ? i18n.phonenumbers.PhoneNumberFormat.E164 : type; return phoneUtil.format(numberObj, type); } catch (e) { return ""; } }, // check if given number is valid isValidNumber: function (number, countryCode) { try { var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance(); var numberObj = phoneUtil.parseAndKeepRawInput(number, countryCode); return phoneUtil.isValidNumber(numberObj); } catch (e) { return false; } }, // get more info if the validation has failed e.g. too long/too short getValidationError: function (number, countryCode) { try { var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance(); var numberObj = phoneUtil.parseAndKeepRawInput(number, countryCode); return phoneUtil.isPossibleNumberWithReason(numberObj); } catch (e) { //console.log(e); // here I convert thrown errors into ValidationResult enums (if possible) if (e == i18n.phonenumbers.Error.INVALID_COUNTRY_CODE) { return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.INVALID_COUNTRY_CODE; } if (e == i18n.phonenumbers.Error.NOT_A_NUMBER) { return 4; } if (e == i18n.phonenumbers.Error.TOO_SHORT_AFTER_IDD || e == i18n.phonenumbers.Error.TOO_SHORT_NSN) { return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_SHORT; } if (e == i18n.phonenumbers.Error.TOO_LONG) { return i18n.phonenumbers.PhoneNumberUtil.ValidationResult.TOO_LONG; } // broken return -99; } }, // format the given number (optionally add any formatting suffix e.g. a hyphen) formatNumber: function (val, countryCode, addSuffix, allowExtension, isAllowedKey) { try { var clean = val.replace(/\D/g, ""), // NOTE: we use AsYouTypeFormatter because the default format function can't handle incomplete numbers e.g. "+17024" formats to "+1 7024" as opposed to "+1 702-4" formatter = new i18n.phonenumbers.AsYouTypeFormatter(countryCode), // if clean is empty, we still need this to be a string otherwise we get errors later result = "", next, extSuffix = " ext. "; if (val.substr(0, 1) == "+") { clean = "+" + clean; } for (var i = 0; i < clean.length; i++) { // TODO: improve this so don't just pump in every digit every time - we should just cache this formatter object, and just call inputDigit once each time the user enters a new digit next = formatter.inputDigit(clean.charAt(i)); // if adding this char didn't change the length, or made it smaller (and there's no longer any spaces): that means that formatting failed which means the number was no longer a potentially valid number, so if we're allowing extensions: assume the rest is the ext if (allowExtension && result && next.length <= result.length && next.indexOf(" ") == -1) { // set flag for extension next = -1; break; } result = next; } // for some reason libphonenumber formats "+44" to "+44 ", but doesn't do the same with "+1" if (result.charAt(result.length - 1) == " ") { result = result.substr(0, result.length - 1); } // check if there's a suffix to add (unless there's an ext) if (addSuffix && !val.split(extSuffix)[1]) { // hack to get formatting suffix var test = formatter.inputDigit('5'); // again the "+44 " problem... (also affects "+45" apparently) if (test.charAt(test.length - 1) == " ") { test = test.substr(0, test.length - 1); } // if adding a '5' introduces a formatting char - check if the penultimate char is not-a-number var penultimate = test.substr(test.length - 2, 1); // Note: never use isNaN without parseFloat if (isNaN(parseFloat(penultimate))) { // return the new value (minus that last '5' we just added) return test.substr(0, test.length - 1); } else if (allowExtension && result && test.length <= result.length && test.indexOf(" ") == -1 && !isAllowedKey) { // else if the next digit would break the formating, and we're allowing extensions, AND this is not an allowed key: add the suffix // NOTE: we must check this is not an allowed key because if it was that means it was the last digit in a valid number and we dont want to add the "ext" suffix in that case. This whole condition is just here to catch the case that: after typing a valid number, they try to type "ext" - this will not automatically add it for them. return result + extSuffix; } } // if the clean number contains an extension we need to add it if (next == -1) { result += extSuffix + clean.substring(i, clean.length); } return result; } catch (e) { return val; } }, // get the type of the given number e.g. fixed-line/mobile getNumberType: function (number, countryCode) { try { var phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance(); var numberObj = phoneUtil.parseAndKeepRawInput(number, countryCode); return phoneUtil.getNumberType(numberObj) } catch (e) { // broken return -99; } } }; // //module.exports = { // // // copied this from https://github.com/googlei18n/libphonenumber/blob/master/javascript/i18n/phonenumbers/phonenumberutil.js#L883 // numberFormat: { // "E164": 0, // "INTERNATIONAL": 1, // "NATIONAL": 2, // "RFC3966": 3 // }, // // // copied this from i18n.phonenumbers.PhoneNumberType in https://code.google.com/p/libphonenumber/source/browse/trunk/javascript/i18n/phonenumbers/phonenumberutil.js and put the keys in quotes to force closure compiler to preserve the keys // // TODO: there must be a way to just tell closure compiler to preserve the keys on i18n.phonenumbers.PhoneNumberType and just export that // numberType: { // "FIXED_LINE": 0, // "MOBILE": 1, // // In some regions (e.g. the USA), it is impossible to distinguish between // // fixed-line and mobile numbers by looking at the phone number itself. // "FIXED_LINE_OR_MOBILE": 2, // // Freephone lines // "TOLL_FREE": 3, // "PREMIUM_RATE": 4, // // The cost of this call is shared between the caller and the recipient, and // // is hence typically less than PREMIUM_RATE calls. See // // http://en.wikipedia.org/wiki/Shared_Cost_Service for more information. // "SHARED_COST": 5, // // Voice over IP numbers. This includes TSoIP (Telephony Service over IP). // "VOIP": 6, // // A personal number is associated with a particular person, and may be routed // // to either a MOBILE or FIXED_LINE number. Some more information can be found // // here: http://en.wikipedia.org/wiki/Personal_Numbers // "PERSONAL_NUMBER": 7, // "PAGER": 8, // // Used for 'Universal Access Numbers' or 'Company Numbers'. They may be // // further routed to specific offices, but allow one number to be used for a // // company. // "UAN": 9, // // Used for 'Voice Mail Access Numbers'. // "VOICEMAIL": 10, // // A phone number is of type UNKNOWN when it does not fit any of the known // // patterns for a specific region. // "UNKNOWN": -1 // }, // // // copied this from i18n.phonenumbers.PhoneNumberUtil.ValidationResult in https://code.google.com/p/libphonenumber/source/browse/trunk/javascript/i18n/phonenumbers/phonenumberutil.js and again put the keys in quotes. // // Also: added NOT_A_NUMBER to match i18n.phonenumbers.Error.NOT_A_NUMBER // validationError: { // "IS_POSSIBLE": 0, // "INVALID_COUNTRY_CODE": 1, // "TOO_SHORT": 2, // "TOO_LONG": 3, // "NOT_A_NUMBER": 4 // }, // // formatNumber: function (number, countryCode, format) { // var phoneUtil, numberObj; // try { // phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance(); // numberObj = phoneUtil.parseAndKeepRawInput(number, countryCode); // format = (typeof format == "undefined") ? // i18n.phonenumbers.PhoneNumberFormat.E164 : format; // return phoneUtil.format(numberObj, format); // } // catch (e) { // return number; // } // }, // // getExampleNumber: function (countryCode, national, numberType) { // var phoneUtil, numberObj,format; // try { // phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance(); // numberObj = phoneUtil.getExampleNumberForType(countryCode, numberType); // format = (national) ? // i18n.phonenumbers.PhoneNumberFormat.NATIONAL : // i18n.phonenumbers.PhoneNumberFormat.INTERNATIONAL; // return phoneUtil.format(numberObj, format); // } // catch (e) { // return ""; // } // }, // getExtension: function (number, countryCode) { // var phoneUtil, numberObj; // try { // phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance(); // numberObj = phoneUtil.parseAndKeepRawInput(number, countryCode); // return numberObj.getExtension(); // } // catch (e) { // return ""; // } // }, // getNumberType: function (number, countryCode) { // var phoneUtil, numberObj; // try { // phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance(); // numberObj = phoneUtil.parseAndKeepRawInput(number, countryCode); // return phoneUtil.getNumberType(numberObj); // } // catch (e) { // // broken // return -99; // } // }, // getValidationError: function (number, countryCode) { // var phoneUtil, numberObj, error, validation; // try { // phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance(); // numberObj = phoneUtil.parseAndKeepRawInput(number, countryCode); // return phoneUtil.isPossibleNumberWithReason(numberObj); // } // catch (e) { // error = i18n.phonenumbers.Error; // validation = i18n.phonenumbers.PhoneNumberUtil.ValidationResult; // // switch (e) { // case error.INVALID_COUNTRY_CODE: // return validation.INVALID_COUNTRY_CODE; // // case error.NOT_A_NUMBER: // return 4; // // case error.TOO_SHORT_NSN: // case error.TOO_SHORT_AFTER_IDD: // return validation.TOO_SHORT; // // case error.TOO_LONG: // return validation.TOO_LONG; // // } // // // broken // return -99; // } // }, // // isValidNumber: function (number, countryCode) { // var phoneUtil, numberObj; // try { // phoneUtil = i18n.phonenumbers.PhoneNumberUtil.getInstance(); // numberObj = phoneUtil.parseAndKeepRawInput(number, countryCode); // return phoneUtil.isValidNumber(numberObj); // } // catch (e) { // return false; // } // } // //};