From f5bac2f1e1a51b83d215a07f9d5d87db337873f3 Mon Sep 17 00:00:00 2001 From: Daniel Narvaez Date: Wed, 06 Feb 2013 14:30:36 +0000 Subject: Get the build to work --- (limited to 'shared/js/simple_phone_matcher.js') diff --git a/shared/js/simple_phone_matcher.js b/shared/js/simple_phone_matcher.js new file mode 100644 index 0000000..249c551 --- /dev/null +++ b/shared/js/simple_phone_matcher.js @@ -0,0 +1,366 @@ +/* -*- Mode: Java; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- / +/* vim: set shiftwidth=2 tabstop=2 autoindent cindent expandtab: */ + +'use strict'; + +/** + * A simple lib to match internaional phone number with local + * and user formatted phone numbers. + * + * Adding this feature to gecko is discussed here: + * https://bugzilla.mozilla.org/show_bug.cgi?id=743363 + * + */ + +var SimplePhoneMatcher = { + mcc: '724', // Assuming a Brazilian mcc by default, can be changed. + + // Used to remove all the formatting from a phone number. + sanitizedNumber: function spm_sanitizedNumber(number) { + var join = this._formattingChars.join('|\\'); + var regexp = new RegExp('(\\' + join + ')', 'g'); + return number.replace(regexp, ''); + }, + + // Generate variants of a phone number (with prefix, without...). + // The variants are sorted from the shortest to the longest. + generateVariants: function spm_generateVariants(number) { + var sanitizedNumber = this.sanitizedNumber(number); + + var variants = []; + + variants = variants.concat(this._internationalPrefixes(sanitizedNumber), + this._trunkPrefixes(sanitizedNumber), + this._carrierPrefixes(sanitizedNumber), + this._areaPrefixes(sanitizedNumber)); + + return variants.sort(function shortestFirst(a, b) { + return a.length > b.length; + }); + }, + + // Find the best (ie longest) match between the variants for a number + // and matches. + // |matches| is an array of arrays + // This way we can easily go trough the results of a mozContacts request: + // array (contacts) of arrays (phone numbers). + // => { + // bestMatchIndex: i, + // localIndex: j + // } + // ie. bestMatchIndex will be the index in the contact arrays, localIndex + // the index in the phone numbers array of this contact + bestMatch: function spm_bestMatchIndex(variants, matches) { + var bestMatchIndex = null; + var bestLocalIndex = null; + var bestMatchLength = 0; + + matches.forEach(function(match, matchIndex) { + match.forEach(function(number, localIndex) { + var sanitizedNumber = this.sanitizedNumber(number); + + variants.forEach(function match(variant) { + if (variant.indexOf(sanitizedNumber) !== -1 || + sanitizedNumber.indexOf(variant) !== -1) { + var length = sanitizedNumber.length; + + if (length > bestMatchLength) { + bestMatchLength = length; + bestMatchIndex = matchIndex; + bestLocalIndex = localIndex; + } + } + }); + }, this); + }, this); + + return { + bestMatchIndex: bestMatchIndex, + localIndex: bestLocalIndex + }; + }, + + _formattingChars: ['\s', '-', '.', '(', ')'], + + _mccWith00Prefix: ['208', '214', '234', '235', '724'], + _mccWith011Prefix: ['310', '311', '312', '313', '314', '315', '316'], + + // https://en.wikipedia.org/wiki/Country_calling_code + // https://en.wikipedia.org/wiki/Trunk_code + // This is an array of objects composed by { p: , t: } + _countryPrefixes: [ + // North American Numbering Plan countries and territories + // US, CA, AG, AI, AS, BB, BM, BS, DM, DO, GD, GU, JM, KN, KY, + // LC, MP, MS, PR, SX, TC, TT, VC, VG, VI + {p: '1', t: false}, + + // BS BB AI + {p: '1242', t: false}, {p: '1246', t: false}, {p: '1264', t: false}, + // AG VG VI KY BM + {p: '1268', t: false}, {p: '1284', t: false}, {p: '1340', t: false}, {p: '1345', t: false}, {p: '1441', t: false}, + // GD TC MS MP GU + {p: '1473', t: false}, {p: '1649', t: false}, {p: '1664', t: false}, {p: '1670', t: false}, {p: '1671', t: false}, + // AS SX LC DM VC + {p: '1684', t: false}, {p: '1721', t: false}, {p: '1758', t: false}, {p: '1767', t: false}, {p: '1784', t: false}, + // PR DO DO DO TT + {p: '1787', t: false}, {p: '1809', t: false}, {p: '1829', t: false}, {p: '1849', t: false}, {p: '1868', t: false}, + // KN JM PR + {p: '1869', t: false}, {p: '1876', t: false}, {p: '1939', t: false}, + + // EG -- SS + {p: '20', t: false}, {p: '210', t: false}, {p: '211', t: false}, + // MA,EH DZ -- -- TN + {p: '212', t: false}, {p: '213', t: false}, {p: '214', t: false}, {p: '215', t: false}, {p: '216', t: false}, + // -- LY -- GM SN + {p: '217', t: false}, {p: '218', t: false}, {p: '219', t: false}, {p: '220', t: false}, {p: '221', t: false}, + // MR ML GN CI BF + {p: '222', t: false}, {p: '223', t: false}, {p: '224', t: false}, {p: '225', t: false}, {p: '226', t: false}, + // NE TG BJ MU LR + {p: '227', t: false}, {p: '228', t: false}, {p: '229', t: false}, {p: '230', t: false}, {p: '231', t: false}, + // SL GH NG TD CF + {p: '232', t: false}, {p: '233', t: false}, {p: '234', t: false}, {p: '235', t: false}, {p: '236', t: false}, + // CM CV ST GQ GA + {p: '237', t: false}, {p: '238', t: false}, {p: '239', t: false}, {p: '240', t: false}, {p: '241', t: false}, + // CG CD AO GW IO + {p: '242', t: false}, {p: '243', t: false}, {p: '244', t: false}, {p: '245', t: false}, {p: '246', t: false}, + // AC SC SD RW ET + {p: '247', t: false}, {p: '248', t: false}, {p: '249', t: false}, {p: '250', t: false}, {p: '251', t: false}, + // SO,QS DJ KE TZ UG + {p: '252', t: false}, {p: '253', t: false}, {p: '254', t: false}, {p: '255', t: false}, {p: '256', t: false}, + // BI MZ -- ZM MG + {p: '257', t: false}, {p: '258', t: false}, {p: '259', t: false}, {p: '260', t: false}, {p: '261', t: false}, + // RE,YT ZW NA MW LS + {p: '262', t: false}, {p: '263', t: false}, {p: '264', t: false}, {p: '265', t: false}, {p: '266', t: false}, + // BW SZ KM ZA -- + {p: '267', t: false}, {p: '268', t: false}, {p: '269', t: false}, {p: '27', t: false}, {p: '28', t: false}, + // SH,TA ER -- -- -- + {p: '290', t: false}, {p: '291', t: false}, {p: '292', t: false}, {p: '293', t: false}, {p: '294', t: false}, + // -- -- AW FO GL + {p: '295', t: false}, {p: '296', t: false}, {p: '297', t: false}, {p: '298', t: false}, {p: '299', t: false}, + + // GR NL BE + {p: '30', t: false}, {p: '31', t: true}, {p: '32', t: true}, + // FR ES GI PT LU + {p: '33', t: true}, {p: '34', t: false}, {p: '350', t: false}, {p: '351', t: true}, {p: '352', t: false}, + // IE IS AL MT CY + {p: '353', t: false}, {p: '354', t: false}, {p: '355', t: true}, {p: '356', t: false}, {p: '357', t: false}, + // FI,AX BG HU LT LV + {p: '358', t: false}, {p: '359', t: true}, {p: '36', t: true}, {p: '370', t: true}, {p: '371', t: false}, + // EE MD AM,QN BY AD + {p: '372', t: false}, {p: '373', t: true}, {p: '374', t: false}, {p: '375', t: true}, {p: '376', t: false}, + // MC SM VA UA RS + {p: '377', t: false}, {p: '378', t: false}, {p: '379', t: false}, {p: '380', t: true}, {p: '381', t: true}, + // ME -- -- HR SI + {p: '382', t: true}, {p: '383', t: false}, {p: '384', t: false}, {p: '385', t: true}, {p: '386', t: false}, + // BA EU MK IT,VA + {p: '387', t: true}, {p: '388', t: false}, {p: '389', t: true}, {p: '39', t: false}, + + // RO CH CZ + {p: '40', t: true}, {p: '41', t: true}, {p: '420', t: false}, + // SK -- LI -- -- + {p: '421', t: false}, {p: '422', t: false}, {p: '423', t: false}, {p: '424', t: false}, {p: '425', t: false}, + // -- -- -- -- AT + {p: '426', t: false}, {p: '427', t: false}, {p: '428', t: false}, {p: '429', t: false}, {p: '43', t: true}, + // GB/UK,GG,IM,JE DK SE NO,SJ PL + {p: '44', t: true}, {p: '45', t: false}, {p: '46', t: true}, {p: '47', t: false}, {p: '48', t: true}, + // DE + {p: '49', t: true}, + + // FK BZ GT + {p: '500', t: false}, {p: '501', t: false}, {p: '502', t: false}, + // SV HN NI CR PA + {p: '503', t: false}, {p: '504', t: false}, {p: '505', t: false}, {p: '506', t: false}, {p: '507', t: false}, + // PM HT PE MX CU + {p: '508', t: false}, {p: '509', t: false}, {p: '51', t: true}, {p: '52', t: false}, {p: '53', t: false}, + // AR BR CL CO VE + {p: '54', t: true}, {p: '55', t: true}, {p: '56', t: false}, {p: '57', t: false}, {p: '58', t: false}, + // GP,BL,MF BO GY EC GF + {p: '590', t: false}, {p: '591', t: true}, {p: '592', t: false}, {p: '593', t: false}, {p: '594', t: false}, + // PY MQ SR UY BQ,CW + {p: '595', t: false}, {p: '596', t: false}, {p: '597', t: false}, {p: '598', t: false}, {p: '599', t: true}, + + // MY AU,CX,CC ID + {p: '60', t: true}, {p: '61', t: true}, {p: '62', t: true}, + // PH NZ SG TH TL + {p: '63', t: true}, {p: '64', t: false}, {p: '65', t: true}, {p: '66', t: true}, {p: '670', t: false}, + // -- NF,AQ BN NR PG + {p: '671', t: false}, {p: '672', t: false}, {p: '673', t: true}, {p:'674', t: false}, {p: '675', t: false}, + // TO SB VU FJ PW + {p: '676', t: false}, {p: '677', t: false}, {p: '678', t: false}, {p:'679', t: false}, {p: '680', t: false}, + // WF CK NU -- WS + {p: '681', t: false}, {p: '682', t: false}, {p: '683', t: false}, {p:'684', t: false}, {p: '685', t: false}, + // KI NC TV PF TK + {p: '686', t: false}, {p: '687', t: false}, {p: '688', t: false}, {p:'689', t: false}, {p: '690', t: false}, + // FM MH -- -- -- + {p: '691', t: false}, {p: '692', t: false}, {p: '693', t: false}, {p: '694', t: false}, {p: '695', t: false}, + // -- -- -- -- -- + {p: '696', t: false}, {p: '697', t: false}, {p: '698', t: false}, {p: '699', t: false}, {p: '699', t: false}, + + // RU,KZ + {p: '7', t: true}, + + // KZ KZ Abkhazia Abkhazia + {p: '76', t: true}, {p: '77', t: true}, {p: '7840', t: false}, {p: '7940', t: false}, + + // XT -- -- + {p: '800', t: false}, {p: '801', t: false}, {p: '802', t: false}, + // -- -- -- -- -- + {p: '803', t: false}, {p: '804', t: false}, {p: '805', t: false}, {p: '806', t: false}, {p: '807', t: false}, + // XS -- JP KR -- + {p: '808', t: false}, {p: '809', t: false}, {p: '81', t: false}, {p: '82', t: true}, {p: '83', t: false}, + // VN KP -- HK MO + {p: '84', t: true}, {p: '850', t: true}, {p: '851', t: false}, {p: '852', t: false}, {p: '853', t: false}, + // -- KH LA -- -- + {p: '854', t: false}, {p: '855', t: true}, {p: '856', t: true}, {p: '857', t: false}, {p: '858', t: false}, + // -- CN XN -- -- + {p: '859', t: false}, {p: '86', t: true}, {p: '870', t: false}, {p: '871', t: false}, {p: '872', t: false}, + // -- -- -- -- -- + {p: '873', t: false}, {p: '874', t: false}, {p: '875', t: false}, {p: '876', t: false}, {p: '877', t: false}, + // XP -- BD XG XV + {p: '878', t: false}, {p: '879', t: false}, {p: '880', t: true}, {p: '881', t: false}, {p: '882', t: false}, + // XV -- -- TW -- + {p: '883', t: false}, {p: '884', t: false}, {p: '885', t: false}, {p: '886', t: true}, {p: '887', t: false}, + // XD -- -- + {p: '888', t: false}, {p: '889', t: false}, {p: '89', t: false}, + + // TR,QY IN PK + {p: '90', t: false}, {p: '91', t: true}, {p: '92', t: true}, + // AF LK MM MV LB + {p: '93', t: true}, {p: '94', t: false}, {p: '95', t: true}, {p: '960', t: false}, {p: '961', t: false}, + // JO SY IQ KW SA + {p: '962', t: false}, {p: '963', t: false}, {p: '964', t: false}, {p: '965', t: false}, {p: '966', t: false}, + // YE OM -- PS AE + {p: '967', t: false}, {p: '968', t: false}, {p: '969', t: false}, {p: '970', t: false}, {p: '971', t: false}, + // IL BH QA BT MN + {p: '972', t: false}, {p: '973', t: false}, {p: '974', t: false}, {p: '975', t: true}, {p: '976', t: true}, + // NP -- XR IR -- + {p: '977', t: true}, {p: '978', t: false}, {p: '979', t: false}, {p: '98', t: false}, {p: '990', t: false}, + // XC TJ TM AZ GE + {p: '991', t: false}, {p: '992', t: false}, {p: '993', t: true}, {p: '994', t: true}, {p: '995', t: true}, + // KG -- UZ -- + {p: '996', t: false}, {p: '997', t: false}, {p: '998', t: true}, {p: '999', t: false} + ], + _trunkCodes: ['0'], + + // https://en.wikipedia.org/wiki/List_of_dialling_codes_in_Brazil + // https://en.wikipedia.org/wiki/Telephone_numbers_in_the_United_Kingdom + // https://en.wikipedia.org/wiki/Telephone_numbering_plan + // country code -> length of the area code + _areaCodeSwipe: { + '55': 2, + '44': 3, + '1': 3 + }, + + _internationalPrefixes: function spm_internatialPrefixes(number) { + var variants = [number]; + + var internationalPrefix = ''; + if (this._mccWith00Prefix.indexOf(this.mcc) !== -1) { + internationalPrefix = '00'; + } + if (this._mccWith011Prefix.indexOf(this.mcc) !== -1) { + internationalPrefix = '011'; + } + + var plusRegexp = new RegExp('^\\+'); + if (number.match(plusRegexp)) { + variants.push(number.replace(plusRegexp, internationalPrefix)); + } + + var ipRegexp = new RegExp('^' + internationalPrefix); + if (number.match(ipRegexp)) { + variants.push(number.replace(ipRegexp, '+')); + } + + return variants; + }, + + _trunkPrefixes: function spm_trunkPrefixes(number) { + var variants = []; + + var prefixesWithTrunk0 = []; + var prefixesWithNoTrunk = []; + this._countryPrefixes.forEach(function(prefix) { + if (prefix.t) { + prefixesWithTrunk0.push(prefix.p); + } else { + prefixesWithNoTrunk.push(prefix.p); + } + }); + + var trunk0Join = prefixesWithTrunk0.join('|') + var trunk0Regexp = new RegExp('^\\+(' + trunk0Join + ')'); + this._internationalPrefixes(number).some(function match(variant) { + var match = variant.match(trunk0Regexp); + + if (match) { + variants.push(variant.replace(trunk0Regexp, '0')); + variants.push(variant.replace(trunk0Regexp, '')); + } + + return match; + }); + + var noTrunkJoin = prefixesWithNoTrunk.join('|'); + var noTrunkRegexp = new RegExp('^\\+(' + noTrunkJoin + ')'); + this._internationalPrefixes(number).some(function match(variant) { + var match = variant.match(noTrunkRegexp); + + if (match) { + variants.push(variant.replace(noTrunkRegexp, '')); + } + + return match; + }); + + // If the number has a trunk prefix already we need a variant without it + var withTrunkRegexp = new RegExp('^(' + this._trunkCodes.join('|') + ')'); + if (number.match(withTrunkRegexp)) { + variants.push(number.replace(withTrunkRegexp, '')); + } + + return variants; + }, + + _areaPrefixes: function spm_areaPrefixes(number) { + var variants = []; + + Object.keys(this._areaCodeSwipe).forEach(function(country) { + var re = new RegExp('^\\+' + country); + + this._internationalPrefixes(number).some(function match(variant) { + var match = variant.match(re); + + if (match) { + var afterArea = 1 + country.length + this._areaCodeSwipe[country]; + variants.push(variant.substring(afterArea)); + } + + return match; + }, this); + }, this); + + return variants; + }, + + // http://thebrazilbusiness.com/article/telephone-system-in-brazil + _carrierPrefixes: function spm_carrierPrefix(number) { + if (this.mcc != '724') { + return []; + } + + var variants = []; + var withTrunk = new RegExp('^0'); + + // A number with carrier prefix will have a trunk code and at + // lest 13 digits + if (number.length >= 13 && number.match(withTrunk)) { + var afterCarrier = 3; + variants.push(number.substring(afterCarrier)); + } + + return variants; + } +}; + -- cgit v0.9.1