ros.grant.common 2.0.1583 → 2.0.1584

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1,1147 +1,1574 @@
1
1
  /*
2
- * International Telephone Input v12.3.0
2
+ * International Telephone Input v18.1.8
3
3
  * https://github.com/jackocnr/intl-tel-input.git
4
4
  * Licensed under the MIT license
5
5
  */
6
6
 
7
- // wrap in UMD - see https://github.com/umdjs/umd/blob/master/jqueryPluginCommonjs.js
8
- (function (factory) {
9
- if (typeof define === "function" && define.amd) {
10
- define(["jquery"], function ($) {
11
- factory($, window, document);
7
+ // wrap in UMD
8
+ (function(factory) {
9
+ if (typeof module === "object" && module.exports) {
10
+ module.exports = factory(require("jquery"));
11
+ } else if (typeof define === "function" && define.amd) {
12
+ define([ "jquery" ], function($) {
13
+ factory($);
12
14
  });
13
- } else if (typeof module === "object" && module.exports) {
14
- module.exports = factory(require("jquery"), window, document);
15
- } else {
16
- factory(jQuery, window, document);
15
+ } else factory(jQuery);
16
+ })(function($, undefined) {
17
+ "use strict";
18
+ // Array of country objects for the flag dropdown.
19
+ // Here is the criteria for the plugin to support a given country/territory
20
+ // - It has an iso2 code: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
21
+ // - It has it's own country calling code (it is not a sub-region of another country): https://en.wikipedia.org/wiki/List_of_country_calling_codes
22
+ // - It has a flag in the region-flags project: https://github.com/behdad/region-flags/tree/gh-pages/png
23
+ // - It is supported by libphonenumber (it must be listed on this page): https://github.com/googlei18n/libphonenumber/blob/master/resources/ShortNumberMetadata.xml
24
+ // Each country array has the following information:
25
+ // [
26
+ // Country name,
27
+ // iso2 code,
28
+ // International dial code,
29
+ // Order (if >1 country with same dial code),
30
+ // Area codes
31
+ // ]
32
+ var allCountries = [ [ "Afghanistan (‫افغانستان‬‎)", "af", "93" ], [ "Albania (Shqipëri)", "al", "355" ], [ "Algeria (‫الجزائر‬‎)", "dz", "213" ], [ "American Samoa", "as", "1", 5, [ "684" ] ], [ "Andorra", "ad", "376" ], [ "Angola", "ao", "244" ], [ "Anguilla", "ai", "1", 6, [ "264" ] ], [ "Antigua and Barbuda", "ag", "1", 7, [ "268" ] ], [ "Argentina", "ar", "54" ], [ "Armenia (Հայաստան)", "am", "374" ], [ "Aruba", "aw", "297" ], [ "Ascension Island", "ac", "247" ], [ "Australia", "au", "61", 0 ], [ "Austria (Österreich)", "at", "43" ], [ "Azerbaijan (Azərbaycan)", "az", "994" ], [ "Bahamas", "bs", "1", 8, [ "242" ] ], [ "Bahrain (‫البحرين‬‎)", "bh", "973" ], [ "Bangladesh (বাংলাদেশ)", "bd", "880" ], [ "Barbados", "bb", "1", 9, [ "246" ] ], [ "Belarus (Беларусь)", "by", "375" ], [ "Belgium (België)", "be", "32" ], [ "Belize", "bz", "501" ], [ "Benin (Bénin)", "bj", "229" ], [ "Bermuda", "bm", "1", 10, [ "441" ] ], [ "Bhutan (འབྲུག)", "bt", "975" ], [ "Bolivia", "bo", "591" ], [ "Bosnia and Herzegovina (Босна и Херцеговина)", "ba", "387" ], [ "Botswana", "bw", "267" ], [ "Brazil (Brasil)", "br", "55" ], [ "British Indian Ocean Territory", "io", "246" ], [ "British Virgin Islands", "vg", "1", 11, [ "284" ] ], [ "Brunei", "bn", "673" ], [ "Bulgaria (България)", "bg", "359" ], [ "Burkina Faso", "bf", "226" ], [ "Burundi (Uburundi)", "bi", "257" ], [ "Cambodia (កម្ពុជា)", "kh", "855" ], [ "Cameroon (Cameroun)", "cm", "237" ], [ "Canada", "ca", "1", 1, [ "204", "226", "236", "249", "250", "263", "289", "306", "343", "354", "365", "367", "368", "382", "387", "403", "416", "418", "428", "431", "437", "438", "450", "584", "468", "474", "506", "514", "519", "548", "579", "581", "584", "587", "604", "613", "639", "647", "672", "683", "705", "709", "742", "753", "778", "780", "782", "807", "819", "825", "867", "873", "902", "905" ] ], [ "Cape Verde (Kabu Verdi)", "cv", "238" ], [ "Caribbean Netherlands", "bq", "599", 1, [ "3", "4", "7" ] ], [ "Cayman Islands", "ky", "1", 12, [ "345" ] ], [ "Central African Republic (République centrafricaine)", "cf", "236" ], [ "Chad (Tchad)", "td", "235" ], [ "Chile", "cl", "56" ], [ "China (中国)", "cn", "86" ], [ "Christmas Island", "cx", "61", 2, [ "89164" ] ], [ "Cocos (Keeling) Islands", "cc", "61", 1, [ "89162" ] ], [ "Colombia", "co", "57" ], [ "Comoros (‫جزر القمر‬‎)", "km", "269" ], [ "Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)", "cd", "243" ], [ "Congo (Republic) (Congo-Brazzaville)", "cg", "242" ], [ "Cook Islands", "ck", "682" ], [ "Costa Rica", "cr", "506" ], [ "Côte d’Ivoire", "ci", "225" ], [ "Croatia (Hrvatska)", "hr", "385" ], [ "Cuba", "cu", "53" ], [ "Curaçao", "cw", "599", 0 ], [ "Cyprus (Κύπρος)", "cy", "357" ], [ "Czech Republic (Česká republika)", "cz", "420" ], [ "Denmark (Danmark)", "dk", "45" ], [ "Djibouti", "dj", "253" ], [ "Dominica", "dm", "1", 13, [ "767" ] ], [ "Dominican Republic (República Dominicana)", "do", "1", 2, [ "809", "829", "849" ] ], [ "Ecuador", "ec", "593" ], [ "Egypt (‫مصر‬‎)", "eg", "20" ], [ "El Salvador", "sv", "503" ], [ "Equatorial Guinea (Guinea Ecuatorial)", "gq", "240" ], [ "Eritrea", "er", "291" ], [ "Estonia (Eesti)", "ee", "372" ], [ "Eswatini", "sz", "268" ], [ "Ethiopia", "et", "251" ], [ "Falkland Islands (Islas Malvinas)", "fk", "500" ], [ "Faroe Islands (Føroyar)", "fo", "298" ], [ "Fiji", "fj", "679" ], [ "Finland (Suomi)", "fi", "358", 0 ], [ "France", "fr", "33" ], [ "French Guiana (Guyane française)", "gf", "594" ], [ "French Polynesia (Polynésie française)", "pf", "689" ], [ "Gabon", "ga", "241" ], [ "Gambia", "gm", "220" ], [ "Georgia (საქართველო)", "ge", "995" ], [ "Germany (Deutschland)", "de", "49" ], [ "Ghana (Gaana)", "gh", "233" ], [ "Gibraltar", "gi", "350" ], [ "Greece (Ελλάδα)", "gr", "30" ], [ "Greenland (Kalaallit Nunaat)", "gl", "299" ], [ "Grenada", "gd", "1", 14, [ "473" ] ], [ "Guadeloupe", "gp", "590", 0 ], [ "Guam", "gu", "1", 15, [ "671" ] ], [ "Guatemala", "gt", "502" ], [ "Guernsey", "gg", "44", 1, [ "1481", "7781", "7839", "7911" ] ], [ "Guinea (Guinée)", "gn", "224" ], [ "Guinea-Bissau (Guiné Bissau)", "gw", "245" ], [ "Guyana", "gy", "592" ], [ "Haiti", "ht", "509" ], [ "Honduras", "hn", "504" ], [ "Hong Kong (香港)", "hk", "852" ], [ "Hungary (Magyarország)", "hu", "36" ], [ "Iceland (Ísland)", "is", "354" ], [ "India (भारत)", "in", "91" ], [ "Indonesia", "id", "62" ], [ "Iran (‫ایران‬‎)", "ir", "98" ], [ "Iraq (‫العراق‬‎)", "iq", "964" ], [ "Ireland", "ie", "353" ], [ "Isle of Man", "im", "44", 2, [ "1624", "74576", "7524", "7924", "7624" ] ], [ "Israel (‫ישראל‬‎)", "il", "972" ], [ "Italy (Italia)", "it", "39", 0 ], [ "Jamaica", "jm", "1", 4, [ "876", "658" ] ], [ "Japan (日本)", "jp", "81" ], [ "Jersey", "je", "44", 3, [ "1534", "7509", "7700", "7797", "7829", "7937" ] ], [ "Jordan (‫الأردن‬‎)", "jo", "962" ], [ "Kazakhstan (Казахстан)", "kz", "7", 1, [ "33", "7" ] ], [ "Kenya", "ke", "254" ], [ "Kiribati", "ki", "686" ], [ "Kosovo", "xk", "383" ], [ "Kuwait (‫الكويت‬‎)", "kw", "965" ], [ "Kyrgyzstan (Кыргызстан)", "kg", "996" ], [ "Laos (ລາວ)", "la", "856" ], [ "Latvia (Latvija)", "lv", "371" ], [ "Lebanon (‫لبنان‬‎)", "lb", "961" ], [ "Lesotho", "ls", "266" ], [ "Liberia", "lr", "231" ], [ "Libya (‫ليبيا‬‎)", "ly", "218" ], [ "Liechtenstein", "li", "423" ], [ "Lithuania (Lietuva)", "lt", "370" ], [ "Luxembourg", "lu", "352" ], [ "Macau (澳門)", "mo", "853" ], [ "Madagascar (Madagasikara)", "mg", "261" ], [ "Malawi", "mw", "265" ], [ "Malaysia", "my", "60" ], [ "Maldives", "mv", "960" ], [ "Mali", "ml", "223" ], [ "Malta", "mt", "356" ], [ "Marshall Islands", "mh", "692" ], [ "Martinique", "mq", "596" ], [ "Mauritania (‫موريتانيا‬‎)", "mr", "222" ], [ "Mauritius (Moris)", "mu", "230" ], [ "Mayotte", "yt", "262", 1, [ "269", "639" ] ], [ "Mexico (México)", "mx", "52" ], [ "Micronesia", "fm", "691" ], [ "Moldova (Republica Moldova)", "md", "373" ], [ "Monaco", "mc", "377" ], [ "Mongolia (Монгол)", "mn", "976" ], [ "Montenegro (Crna Gora)", "me", "382" ], [ "Montserrat", "ms", "1", 16, [ "664" ] ], [ "Morocco (‫المغرب‬‎)", "ma", "212", 0 ], [ "Mozambique (Moçambique)", "mz", "258" ], [ "Myanmar (Burma) (မြန်မာ)", "mm", "95" ], [ "Namibia (Namibië)", "na", "264" ], [ "Nauru", "nr", "674" ], [ "Nepal (नेपाल)", "np", "977" ], [ "Netherlands (Nederland)", "nl", "31" ], [ "New Caledonia (Nouvelle-Calédonie)", "nc", "687" ], [ "New Zealand", "nz", "64" ], [ "Nicaragua", "ni", "505" ], [ "Niger (Nijar)", "ne", "227" ], [ "Nigeria", "ng", "234" ], [ "Niue", "nu", "683" ], [ "Norfolk Island", "nf", "672" ], [ "North Korea (조선 민주주의 인민 공화국)", "kp", "850" ], [ "North Macedonia (Северна Македонија)", "mk", "389" ], [ "Northern Mariana Islands", "mp", "1", 17, [ "670" ] ], [ "Norway (Norge)", "no", "47", 0 ], [ "Oman (‫عُمان‬‎)", "om", "968" ], [ "Pakistan (‫پاکستان‬‎)", "pk", "92" ], [ "Palau", "pw", "680" ], [ "Palestine (‫فلسطين‬‎)", "ps", "970" ], [ "Panama (Panamá)", "pa", "507" ], [ "Papua New Guinea", "pg", "675" ], [ "Paraguay", "py", "595" ], [ "Peru (Perú)", "pe", "51" ], [ "Philippines", "ph", "63" ], [ "Poland (Polska)", "pl", "48" ], [ "Portugal", "pt", "351" ], [ "Puerto Rico", "pr", "1", 3, [ "787", "939" ] ], [ "Qatar (‫قطر‬‎)", "qa", "974" ], [ "Réunion (La Réunion)", "re", "262", 0 ], [ "Romania (România)", "ro", "40" ], [ "Russia (Россия)", "ru", "7", 0 ], [ "Rwanda", "rw", "250" ], [ "Saint Barthélemy", "bl", "590", 1 ], [ "Saint Helena", "sh", "290" ], [ "Saint Kitts and Nevis", "kn", "1", 18, [ "869" ] ], [ "Saint Lucia", "lc", "1", 19, [ "758" ] ], [ "Saint Martin (Saint-Martin (partie française))", "mf", "590", 2 ], [ "Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)", "pm", "508" ], [ "Saint Vincent and the Grenadines", "vc", "1", 20, [ "784" ] ], [ "Samoa", "ws", "685" ], [ "San Marino", "sm", "378" ], [ "São Tomé and Príncipe (São Tomé e Príncipe)", "st", "239" ], [ "Saudi Arabia (‫المملكة العربية السعودية‬‎)", "sa", "966" ], [ "Senegal (Sénégal)", "sn", "221" ], [ "Serbia (Србија)", "rs", "381" ], [ "Seychelles", "sc", "248" ], [ "Sierra Leone", "sl", "232" ], [ "Singapore", "sg", "65" ], [ "Sint Maarten", "sx", "1", 21, [ "721" ] ], [ "Slovakia (Slovensko)", "sk", "421" ], [ "Slovenia (Slovenija)", "si", "386" ], [ "Solomon Islands", "sb", "677" ], [ "Somalia (Soomaaliya)", "so", "252" ], [ "South Africa", "za", "27" ], [ "South Korea (대한민국)", "kr", "82" ], [ "South Sudan (‫جنوب السودان‬‎)", "ss", "211" ], [ "Spain (España)", "es", "34" ], [ "Sri Lanka (ශ්‍රී ලංකාව)", "lk", "94" ], [ "Sudan (‫السودان‬‎)", "sd", "249" ], [ "Suriname", "sr", "597" ], [ "Svalbard and Jan Mayen", "sj", "47", 1, [ "79" ] ], [ "Sweden (Sverige)", "se", "46" ], [ "Switzerland (Schweiz)", "ch", "41" ], [ "Syria (‫سوريا‬‎)", "sy", "963" ], [ "Taiwan (台灣)", "tw", "886" ], [ "Tajikistan", "tj", "992" ], [ "Tanzania", "tz", "255" ], [ "Thailand (ไทย)", "th", "66" ], [ "Timor-Leste", "tl", "670" ], [ "Togo", "tg", "228" ], [ "Tokelau", "tk", "690" ], [ "Tonga", "to", "676" ], [ "Trinidad and Tobago", "tt", "1", 22, [ "868" ] ], [ "Tunisia (‫تونس‬‎)", "tn", "216" ], [ "Turkey (Türkiye)", "tr", "90" ], [ "Turkmenistan", "tm", "993" ], [ "Turks and Caicos Islands", "tc", "1", 23, [ "649" ] ], [ "Tuvalu", "tv", "688" ], [ "U.S. Virgin Islands", "vi", "1", 24, [ "340" ] ], [ "Uganda", "ug", "256" ], [ "Ukraine (Україна)", "ua", "380" ], [ "United Arab Emirates (‫الإمارات العربية المتحدة‬‎)", "ae", "971" ], [ "United Kingdom", "gb", "44", 0 ], [ "United States", "us", "1", 0 ], [ "Uruguay", "uy", "598" ], [ "Uzbekistan (Oʻzbekiston)", "uz", "998" ], [ "Vanuatu", "vu", "678" ], [ "Vatican City (Città del Vaticano)", "va", "39", 1, [ "06698" ] ], [ "Venezuela", "ve", "58" ], [ "Vietnam (Việt Nam)", "vn", "84" ], [ "Wallis and Futuna (Wallis-et-Futuna)", "wf", "681" ], [ "Western Sahara (‫الصحراء الغربية‬‎)", "eh", "212", 1, [ "5288", "5289" ] ], [ "Yemen (‫اليمن‬‎)", "ye", "967" ], [ "Zambia", "zm", "260" ], [ "Zimbabwe", "zw", "263" ], [ "Åland Islands", "ax", "358", 1, [ "18" ] ] ];
33
+ // loop over all of the countries above, restructuring the data to be objects with named keys
34
+ for (var i = 0; i < allCountries.length; i++) {
35
+ var c = allCountries[i];
36
+ allCountries[i] = {
37
+ name: c[0],
38
+ iso2: c[1],
39
+ dialCode: c[2],
40
+ priority: c[3] || 0,
41
+ areaCodes: c[4] || null
42
+ };
17
43
  }
18
- })(function ($, window, document, undefined) {
19
44
  "use strict";
20
- // these vars persist through all instances of the plugin
21
- var pluginName = "intlTelInput", id = 1, // give each instance it's own id for namespaced event handling
22
- defaults = {
23
- // whether or not to allow the dropdown
24
- allowDropdown: true,
25
- // if there is just a dial code in the input: remove it on blur, and re-add it on focus
26
- autoHideDialCode: true,
27
- // add a placeholder in the input with an example number for the selected country
28
- autoPlaceholder: "polite",
29
- // modify the auto placeholder
30
- customPlaceholder: null,
31
- // append menu to a specific element
32
- dropdownContainer: "",
33
- // don't display these countries
34
- excludeCountries: [],
35
- // format the input value during initialisation and on setNumber
36
- formatOnDisplay: true,
37
- // geoIp lookup function
38
- geoIpLookup: null,
39
- // inject a hidden input with this name, and on submit, populate it with the result of getNumber
40
- hiddenInput: "",
41
- // initial country
42
- initialCountry: "",
43
- // don't insert international dial codes
44
- nationalMode: true,
45
- // display only these countries
46
- onlyCountries: [],
47
- // number type to use for placeholders
48
- placeholderNumberType: "MOBILE",
49
- // the countries at the top of the list. defaults to united states and united kingdom
50
- preferredCountries: ["us", "gb"],
51
- // display the country dial code next to the selected flag so it's not part of the typed number
52
- separateDialCode: false,
53
- // specify the path to the libphonenumber script to enable validation/formatting
54
- utilsScript: ""
55
- }, keys = {
56
- UP: 38,
57
- DOWN: 40,
58
- ENTER: 13,
59
- ESC: 27,
60
- PLUS: 43,
61
- A: 65,
62
- Z: 90,
63
- SPACE: 32,
64
- TAB: 9
65
- }, // https://en.wikipedia.org/wiki/List_of_North_American_Numbering_Plan_area_codes#Non-geographic_area_codes
66
- regionlessNanpNumbers = ["800", "822", "833", "844", "855", "866", "877", "880", "881", "882", "883", "884", "885", "886", "887", "888", "889"];
67
- // keep track of if the window.load event has fired as impossible to check after the fact
68
- $(window).on("load", function () {
69
- // UPDATE: use a public static field so we can fudge it in the tests
70
- $.fn[pluginName].windowLoaded = true;
71
- });
72
- function Plugin(element, options) {
73
- this.telInput = $(element);
74
- this.options = $.extend({}, defaults, options);
75
- // event namespace
76
- this.ns = "." + pluginName + id++;
77
- // Chrome, FF, Safari, IE9+
78
- this.isGoodBrowser = Boolean(element.setSelectionRange);
79
- this.hadInitialPlaceholder = Boolean($(element).attr("placeholder"));
45
+ function _objectSpread(target) {
46
+ for (var i = 1; i < arguments.length; i++) {
47
+ var source = arguments[i] != null ? Object(arguments[i]) : {};
48
+ var ownKeys = Object.keys(source);
49
+ if (typeof Object.getOwnPropertySymbols === "function") {
50
+ ownKeys.push.apply(ownKeys, Object.getOwnPropertySymbols(source).filter(function(sym) {
51
+ return Object.getOwnPropertyDescriptor(source, sym).enumerable;
52
+ }));
53
+ }
54
+ ownKeys.forEach(function(key) {
55
+ _defineProperty(target, key, source[key]);
56
+ });
57
+ }
58
+ return target;
80
59
  }
81
- Plugin.prototype = {
82
- _init: function () {
83
- // if in nationalMode, disable options relating to dial codes
84
- if (this.options.nationalMode) {
85
- this.options.autoHideDialCode = false;
86
- }
87
- // if separateDialCode then doesn't make sense to A) insert dial code into input (autoHideDialCode), and B) display national numbers (because we're displaying the country dial code next to them)
88
- if (this.options.separateDialCode) {
89
- this.options.autoHideDialCode = this.options.nationalMode = false;
90
- }
91
- // we cannot just test screen size as some smartphones/website meta tags will report desktop resolutions
92
- // Note: for some reason jasmine breaks if you put this in the main Plugin function with the rest of these declarations
93
- // Note: to target Android Mobiles (and not Tablets), we must find "Android" and "Mobile"
94
- this.isMobile = /Android.+Mobile|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
95
- if (this.isMobile) {
96
- // trigger the mobile dropdown css
97
- $("body").addClass("iti-mobile");
98
- // on mobile, we want a full screen dropdown, so we must append it to the body
99
- if (!this.options.dropdownContainer) {
100
- this.options.dropdownContainer = "body";
101
- }
102
- }
103
- // we return these deferred objects from the _init() call so they can be watched, and then we resolve them when each specific request returns
104
- // Note: again, jasmine breaks when I put these in the Plugin function
105
- this.autoCountryDeferred = new $.Deferred();
106
- this.utilsScriptDeferred = new $.Deferred();
107
- // in various situations there could be no country selected initially, but we need to be able to assume this variable exists
108
- this.selectedCountryData = {};
109
- // process all the data: onlyCountries, excludeCountries, preferredCountries etc
110
- this._processCountryData();
111
- // generate the markup
112
- this._generateMarkup();
113
- // set the initial state of the input value and the selected flag
114
- this._setInitialState();
115
- // start all of the event listeners: autoHideDialCode, input keydown, selectedFlag click
116
- this._initListeners();
117
- // utils script, and auto country
118
- this._initRequests();
119
- // return the deferreds
120
- return [this.autoCountryDeferred, this.utilsScriptDeferred];
121
- },
122
- /********************
123
- * PRIVATE METHODS
124
- ********************/
125
- // prepare all of the country data, including onlyCountries, excludeCountries and preferredCountries options
126
- _processCountryData: function () {
127
- // process onlyCountries or excludeCountries array if present
128
- this._processAllCountries();
129
- // process the countryCodes map
130
- this._processCountryCodes();
131
- // process the preferredCountries
132
- this._processPreferredCountries();
60
+ function _defineProperty(obj, key, value) {
61
+ key = _toPropertyKey(key);
62
+ if (key in obj) {
63
+ Object.defineProperty(obj, key, {
64
+ value: value,
65
+ enumerable: true,
66
+ configurable: true,
67
+ writable: true
68
+ });
69
+ } else {
70
+ obj[key] = value;
71
+ }
72
+ return obj;
73
+ }
74
+ function _classCallCheck(instance, Constructor) {
75
+ if (!(instance instanceof Constructor)) {
76
+ throw new TypeError("Cannot call a class as a function");
77
+ }
78
+ }
79
+ function _defineProperties(target, props) {
80
+ for (var i = 0; i < props.length; i++) {
81
+ var descriptor = props[i];
82
+ descriptor.enumerable = descriptor.enumerable || false;
83
+ descriptor.configurable = true;
84
+ if ("value" in descriptor) descriptor.writable = true;
85
+ Object.defineProperty(target, _toPropertyKey(descriptor.key), descriptor);
86
+ }
87
+ }
88
+ function _createClass(Constructor, protoProps, staticProps) {
89
+ if (protoProps) _defineProperties(Constructor.prototype, protoProps);
90
+ if (staticProps) _defineProperties(Constructor, staticProps);
91
+ Object.defineProperty(Constructor, "prototype", {
92
+ writable: false
93
+ });
94
+ return Constructor;
95
+ }
96
+ function _toPropertyKey(arg) {
97
+ var key = _toPrimitive(arg, "string");
98
+ return typeof key === "symbol" ? key : String(key);
99
+ }
100
+ function _toPrimitive(input, hint) {
101
+ if (typeof input !== "object" || input === null) return input;
102
+ var prim = input[Symbol.toPrimitive];
103
+ if (prim !== undefined) {
104
+ var res = prim.call(input, hint || "default");
105
+ if (typeof res !== "object") return res;
106
+ throw new TypeError("@@toPrimitive must return a primitive value.");
107
+ }
108
+ return (hint === "string" ? String : Number)(input);
109
+ }
110
+ var intlTelInputGlobals = {
111
+ getInstance: function getInstance(input) {
112
+ var id = input.getAttribute("data-intl-tel-input-id");
113
+ return window.intlTelInputGlobals.instances[id];
133
114
  },
134
- // add a country code to this.countryCodes
135
- _addCountryCode: function (iso2, dialCode, priority) {
136
- if (!(dialCode in this.countryCodes)) {
137
- this.countryCodes[dialCode] = [];
115
+ instances: {},
116
+ // using a global like this allows us to mock it in the tests
117
+ documentReady: function documentReady() {
118
+ return document.readyState === "complete";
119
+ }
120
+ };
121
+ if (typeof window === "object") {
122
+ window.intlTelInputGlobals = intlTelInputGlobals;
123
+ }
124
+ // these vars persist through all instances of the plugin
125
+ var id = 0;
126
+ var defaults = {
127
+ // whether or not to allow the dropdown
128
+ allowDropdown: true,
129
+ // auto insert dial code (A) on init, (B) on user selecting a country, (C) on calling setCountry
130
+ // also listen for blur/submit and auto remove dial code if that's all there is
131
+ autoInsertDialCode: false,
132
+ // add a placeholder in the input with an example number for the selected country
133
+ autoPlaceholder: "polite",
134
+ // modify the parentClass
135
+ customContainer: "",
136
+ // modify the auto placeholder
137
+ customPlaceholder: null,
138
+ // append menu to specified element
139
+ dropdownContainer: null,
140
+ // don't display these countries
141
+ excludeCountries: [],
142
+ // format the input value during initialisation and on setNumber
143
+ formatOnDisplay: true,
144
+ // geoIp lookup function
145
+ geoIpLookup: null,
146
+ // inject a hidden input with this name, and on submit, populate it with the result of getNumber
147
+ hiddenInput: "",
148
+ // initial country
149
+ initialCountry: "",
150
+ // localized country names e.g. { 'de': 'Deutschland' }
151
+ localizedCountries: null,
152
+ // national vs international formatting for numbers e.g. placeholders and displaying existing numbers
153
+ nationalMode: true,
154
+ // display only these countries
155
+ onlyCountries: [],
156
+ // number type to use for placeholders
157
+ placeholderNumberType: "MOBILE",
158
+ // the countries at the top of the list. defaults to united states and united kingdom
159
+ preferredCountries: [ "us", "gb" ],
160
+ // display the country dial code next to the selected flag
161
+ separateDialCode: false,
162
+ // option to hide the flags - must be used with separateDialCode, or allowDropdown=false
163
+ showFlags: true,
164
+ // specify the path to the libphonenumber script to enable validation/formatting
165
+ utilsScript: ""
166
+ };
167
+ // https://en.wikipedia.org/wiki/List_of_North_American_Numbering_Plan_area_codes#Non-geographic_area_codes
168
+ var regionlessNanpNumbers = [ "800", "822", "833", "844", "855", "866", "877", "880", "881", "882", "883", "884", "885", "886", "887", "888", "889" ];
169
+ // utility function to iterate over an object. can't use Object.entries or native forEach because
170
+ // of IE11
171
+ var forEachProp = function forEachProp(obj, callback) {
172
+ var keys = Object.keys(obj);
173
+ for (var i = 0; i < keys.length; i++) {
174
+ callback(keys[i], obj[keys[i]]);
175
+ }
176
+ };
177
+ // run a method on each instance of the plugin
178
+ var forEachInstance = function forEachInstance(method) {
179
+ forEachProp(window.intlTelInputGlobals.instances, function(key) {
180
+ window.intlTelInputGlobals.instances[key][method]();
181
+ });
182
+ };
183
+ // this is our plugin class that we will create an instance of
184
+ // eslint-disable-next-line no-unused-vars
185
+ var Iti = /*#__PURE__*/ function() {
186
+ function Iti(input, options) {
187
+ var _this = this;
188
+ _classCallCheck(this, Iti);
189
+ this.id = id++;
190
+ this.telInput = input;
191
+ this.activeItem = null;
192
+ this.highlightedItem = null;
193
+ // process specified options / defaults
194
+ // alternative to Object.assign, which isn't supported by IE11
195
+ var customOptions = options || {};
196
+ this.options = {};
197
+ forEachProp(defaults, function(key, value) {
198
+ _this.options[key] = customOptions.hasOwnProperty(key) ? customOptions[key] : value;
199
+ });
200
+ this.hadInitialPlaceholder = Boolean(input.getAttribute("placeholder"));
201
+ }
202
+ _createClass(Iti, [ {
203
+ key: "_init",
204
+ value: function _init() {
205
+ var _this2 = this;
206
+ // if in nationalMode, do not insert dial codes
207
+ if (this.options.nationalMode) {
208
+ this.options.autoInsertDialCode = false;
209
+ }
210
+ // if separateDialCode enabled, do not insert dial codes
211
+ if (this.options.separateDialCode) {
212
+ this.options.autoInsertDialCode = false;
213
+ }
214
+ // force showFlags=true if there's a dropdown and we're not displaying the dial code,
215
+ // as otherwise you just have a down arrow on it's own which doesn't make sense
216
+ var forceShowFlags = this.options.allowDropdown && !this.options.separateDialCode;
217
+ if (!this.options.showFlags && forceShowFlags) {
218
+ this.options.showFlags = true;
219
+ }
220
+ // we cannot just test screen size as some smartphones/website meta tags will report desktop
221
+ // resolutions
222
+ // Note: for some reason jasmine breaks if you put this in the main Plugin function with the
223
+ // rest of these declarations
224
+ // Note: to target Android Mobiles (and not Tablets), we must find 'Android' and 'Mobile'
225
+ this.isMobile = /Android.+Mobile|webOS|iPhone|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent);
226
+ if (this.isMobile) {
227
+ // trigger the mobile dropdown css
228
+ document.body.classList.add("iti-mobile");
229
+ // on mobile, we want a full screen dropdown, so we must append it to the body
230
+ if (!this.options.dropdownContainer) {
231
+ this.options.dropdownContainer = document.body;
232
+ }
233
+ }
234
+ // check if input has one parent with RTL
235
+ this.isRTL = !!this.telInput.closest("[dir=rtl]");
236
+ // these promises get resolved when their individual requests complete
237
+ // this way the dev can do something like iti.promise.then(...) to know when all requests are
238
+ // complete
239
+ if (typeof Promise !== "undefined") {
240
+ var autoCountryPromise = new Promise(function(resolve, reject) {
241
+ _this2.resolveAutoCountryPromise = resolve;
242
+ _this2.rejectAutoCountryPromise = reject;
243
+ });
244
+ var utilsScriptPromise = new Promise(function(resolve, reject) {
245
+ _this2.resolveUtilsScriptPromise = resolve;
246
+ _this2.rejectUtilsScriptPromise = reject;
247
+ });
248
+ this.promise = Promise.all([ autoCountryPromise, utilsScriptPromise ]);
249
+ } else {
250
+ // prevent errors when Promise doesn't exist
251
+ this.resolveAutoCountryPromise = this.rejectAutoCountryPromise = function() {};
252
+ this.resolveUtilsScriptPromise = this.rejectUtilsScriptPromise = function() {};
253
+ }
254
+ // in various situations there could be no country selected initially, but we need to be able
255
+ // to assume this variable exists
256
+ this.selectedCountryData = {};
257
+ // process all the data: onlyCountries, excludeCountries, preferredCountries etc
258
+ this._processCountryData();
259
+ // generate the markup
260
+ this._generateMarkup();
261
+ // set the initial state of the input value and the selected flag
262
+ this._setInitialState();
263
+ // start all of the event listeners: autoInsertDialCode, input keydown, selectedFlag click
264
+ this._initListeners();
265
+ // utils script, and auto country
266
+ this._initRequests();
138
267
  }
139
- var index = priority || 0;
140
- this.countryCodes[dialCode][index] = iso2;
141
- },
142
- // process onlyCountries or excludeCountries array if present
143
- _processAllCountries: function () {
144
- if (this.options.onlyCountries.length) {
145
- var lowerCaseOnlyCountries = this.options.onlyCountries.map(function (country) {
146
- return country.toLowerCase();
147
- });
148
- this.countries = allCountries.filter(function (country) {
149
- return lowerCaseOnlyCountries.indexOf(country.iso2) > -1;
150
- });
151
- this.countries.sort(this._countryNameSort);
152
- } else if (this.options.excludeCountries.length) {
153
- var lowerCaseExcludeCountries = this.options.excludeCountries.map(function (country) {
154
- return country.toLowerCase();
155
- });
156
- this.countries = allCountries.filter(function (country) {
157
- return lowerCaseExcludeCountries.indexOf(country.iso2) === -1;
158
- });
159
- } else {
160
- this.countries = allCountries;
268
+ }, {
269
+ key: "_processCountryData",
270
+ value: function _processCountryData() {
271
+ // process onlyCountries or excludeCountries array if present
272
+ this._processAllCountries();
273
+ // process the countryCodes map
274
+ this._processCountryCodes();
275
+ // process the preferredCountries
276
+ this._processPreferredCountries();
277
+ // translate countries according to localizedCountries option
278
+ if (this.options.localizedCountries) {
279
+ this._translateCountriesByLocale();
280
+ }
281
+ // sort countries by name
282
+ if (this.options.onlyCountries.length || this.options.localizedCountries) {
283
+ this.countries.sort(this._countryNameSort);
284
+ }
161
285
  }
162
- },
163
- // sort by country name
164
- _countryNameSort: function (a, b) {
165
- return a.name.localeCompare(b.name);
166
- },
167
- // process the countryCodes map
168
- _processCountryCodes: function () {
169
- this.countryCodes = {};
170
- for (var i = 0; i < this.countries.length; i++) {
171
- var c = this.countries[i];
172
- this._addCountryCode(c.iso2, c.dialCode, c.priority);
173
- // area codes
174
- if (c.areaCodes) {
175
- for (var j = 0; j < c.areaCodes.length; j++) {
176
- // full dial code is country code + dial code
177
- this._addCountryCode(c.iso2, c.dialCode + c.areaCodes[j]);
286
+ }, {
287
+ key: "_addCountryCode",
288
+ value: function _addCountryCode(iso2, countryCode, priority) {
289
+ if (countryCode.length > this.countryCodeMaxLen) {
290
+ this.countryCodeMaxLen = countryCode.length;
291
+ }
292
+ if (!this.countryCodes.hasOwnProperty(countryCode)) {
293
+ this.countryCodes[countryCode] = [];
294
+ }
295
+ // bail if we already have this country for this countryCode
296
+ for (var i = 0; i < this.countryCodes[countryCode].length; i++) {
297
+ if (this.countryCodes[countryCode][i] === iso2) {
298
+ return;
178
299
  }
179
300
  }
301
+ // check for undefined as 0 is falsy
302
+ var index = priority !== undefined ? priority : this.countryCodes[countryCode].length;
303
+ this.countryCodes[countryCode][index] = iso2;
180
304
  }
181
- },
182
- // process preferred countries - iterate through the preferences, fetching the country data for each one
183
- _processPreferredCountries: function () {
184
- this.preferredCountries = [];
185
- for (var i = 0; i < this.options.preferredCountries.length; i++) {
186
- var countryCode = this.options.preferredCountries[i].toLowerCase(), countryData = this._getCountryData(countryCode, false, true);
187
- if (countryData) {
188
- this.preferredCountries.push(countryData);
305
+ }, {
306
+ key: "_processAllCountries",
307
+ value: function _processAllCountries() {
308
+ if (this.options.onlyCountries.length) {
309
+ var lowerCaseOnlyCountries = this.options.onlyCountries.map(function(country) {
310
+ return country.toLowerCase();
311
+ });
312
+ this.countries = allCountries.filter(function(country) {
313
+ return lowerCaseOnlyCountries.indexOf(country.iso2) > -1;
314
+ });
315
+ } else if (this.options.excludeCountries.length) {
316
+ var lowerCaseExcludeCountries = this.options.excludeCountries.map(function(country) {
317
+ return country.toLowerCase();
318
+ });
319
+ this.countries = allCountries.filter(function(country) {
320
+ return lowerCaseExcludeCountries.indexOf(country.iso2) === -1;
321
+ });
322
+ } else {
323
+ this.countries = allCountries;
189
324
  }
190
325
  }
191
- },
192
- // generate all of the markup for the plugin: the selected flag overlay, and the dropdown
193
- _generateMarkup: function () {
194
- // prevent autocomplete as there's no safe, cross-browser event we can react to, so it can easily put the plugin in an inconsistent state e.g. the wrong flag selected for the autocompleted number, which on submit could mean the wrong number is saved (esp in nationalMode)
195
- this.telInput.attr("autocomplete", "off");
196
- // containers (mostly for positioning)
197
- var parentClass = "intl-tel-input";
198
- if (this.options.allowDropdown) {
199
- parentClass += " allow-dropdown";
200
- }
201
- if (this.options.separateDialCode) {
202
- parentClass += " separate-dial-code";
203
- }
204
- this.telInput.wrap($("<div>", {
205
- "class": parentClass
206
- }));
207
- this.flagsContainer = $("<div>", {
208
- "class": "flag-container"
209
- }).insertBefore(this.telInput);
210
- // currently selected flag (displayed to left of input)
211
- var selectedFlag = $("<div>", {
212
- "class": "selected-flag"
213
- });
214
- selectedFlag.appendTo(this.flagsContainer);
215
- this.selectedFlagInner = $("<div>", {
216
- "class": "iti-flag"
217
- }).appendTo(selectedFlag);
218
- if (this.options.separateDialCode) {
219
- this.selectedDialCode = $("<div>", {
220
- "class": "selected-dial-code"
221
- }).appendTo(selectedFlag);
222
- }
223
- if (this.options.allowDropdown) {
224
- // make element focusable and tab naviagable
225
- selectedFlag.attr("tabindex", "0");
226
- // CSS triangle
227
- $("<div>", {
228
- "class": "iti-arrow"
229
- }).appendTo(selectedFlag);
230
- // country dropdown: preferred countries, then divider, then all countries
231
- this.countryList = $("<ul>", {
232
- "class": "country-list hide"
233
- });
234
- if (this.preferredCountries.length) {
235
- this._appendListItems(this.preferredCountries, "preferred");
236
- $("<li>", {
237
- "class": "divider"
238
- }).appendTo(this.countryList);
239
- }
240
- this._appendListItems(this.countries, "");
241
- // this is useful in lots of places
242
- this.countryListItems = this.countryList.children(".country");
243
- // create dropdownContainer markup
244
- if (this.options.dropdownContainer) {
245
- this.dropdown = $("<div>", {
246
- "class": "intl-tel-input iti-container"
247
- }).append(this.countryList);
248
- } else {
249
- this.countryList.appendTo(this.flagsContainer);
326
+ }, {
327
+ key: "_translateCountriesByLocale",
328
+ value: function _translateCountriesByLocale() {
329
+ for (var i = 0; i < this.countries.length; i++) {
330
+ var iso = this.countries[i].iso2.toLowerCase();
331
+ if (this.options.localizedCountries.hasOwnProperty(iso)) {
332
+ this.countries[i].name = this.options.localizedCountries[iso];
333
+ }
250
334
  }
251
- } else {
252
- // a little hack so we don't break anything
253
- this.countryListItems = $();
254
335
  }
255
- if (this.options.hiddenInput) {
256
- this.hiddenInput = $("<input>", {
257
- type: "hidden",
258
- name: this.options.hiddenInput
259
- }).insertAfter(this.telInput);
336
+ }, {
337
+ key: "_countryNameSort",
338
+ value: function _countryNameSort(a, b) {
339
+ if (a.name < b.name) {
340
+ return -1;
341
+ }
342
+ if (a.name > b.name) {
343
+ return 1;
344
+ }
345
+ return 0;
260
346
  }
261
- },
262
- // add a country <li> to the countryList <ul> container
263
- _appendListItems: function (countries, className) {
264
- // we create so many DOM elements, it is faster to build a temp string
265
- // and then add everything to the DOM in one go at the end
266
- var tmp = "";
267
- // for each country
268
- for (var i = 0; i < countries.length; i++) {
269
- var c = countries[i];
270
- // open the list item
271
- tmp += "<li class='country " + className + "' data-dial-code='" + c.dialCode + "' data-country-code='" + c.iso2 + "'>";
272
- // add the flag
273
- tmp += "<div class='flag-box'><div class='iti-flag " + c.iso2 + "'></div></div>";
274
- // and the country name and dial code
275
- tmp += "<span class='country-name'>" + c.name + "</span>";
276
- tmp += "<span class='dial-code'>+" + c.dialCode + "</span>";
277
- // close the list item
278
- tmp += "</li>";
279
- }
280
- this.countryList.append(tmp);
281
- },
282
- // set the initial state of the input value and the selected flag by:
283
- // 1. extracting a dial code from the given number
284
- // 2. using explicit initialCountry
285
- // 3. picking the first preferred country
286
- // 4. picking the first country
287
- _setInitialState: function () {
288
- var val = this.telInput.val();
289
- // if we already have a dial code, and it's not a regionlessNanp, we can go ahead and set the flag, else fall back to the default country
290
- // UPDATE: actually we do want to set the flag for a regionlessNanp in one situation: if we're in nationalMode and there's no initialCountry - otherwise we lose the +1 and we're left with an invalid number
291
- if (this._getDialCode(val) && (!this._isRegionlessNanp(val) || this.options.nationalMode && !this.options.initialCountry)) {
292
- this._updateFlagFromNumber(val);
293
- } else if (this.options.initialCountry !== "auto") {
294
- // see if we should select a flag
295
- if (this.options.initialCountry) {
296
- this._setFlag(this.options.initialCountry.toLowerCase());
297
- } else {
298
- // no dial code and no initialCountry, so default to first in list
299
- this.defaultCountry = this.preferredCountries.length ? this.preferredCountries[0].iso2 : this.countries[0].iso2;
300
- if (!val) {
301
- this._setFlag(this.defaultCountry);
347
+ }, {
348
+ key: "_processCountryCodes",
349
+ value: function _processCountryCodes() {
350
+ this.countryCodeMaxLen = 0;
351
+ // here we store just dial codes
352
+ this.dialCodes = {};
353
+ // here we store "country codes" (both dial codes and their area codes)
354
+ this.countryCodes = {};
355
+ // first: add dial codes
356
+ for (var i = 0; i < this.countries.length; i++) {
357
+ var c = this.countries[i];
358
+ if (!this.dialCodes[c.dialCode]) {
359
+ this.dialCodes[c.dialCode] = true;
302
360
  }
361
+ this._addCountryCode(c.iso2, c.dialCode, c.priority);
303
362
  }
304
- // if empty and no nationalMode and no autoHideDialCode then insert the default dial code
305
- if (!val && !this.options.nationalMode && !this.options.autoHideDialCode && !this.options.separateDialCode) {
306
- this.telInput.val("+" + this.selectedCountryData.dialCode);
363
+ // next: add area codes
364
+ // this is a second loop over countries, to make sure we have all of the "root" countries
365
+ // already in the map, so that we can access them, as each time we add an area code substring
366
+ // to the map, we also need to include the "root" country's code, as that also matches
367
+ for (var _i = 0; _i < this.countries.length; _i++) {
368
+ var _c = this.countries[_i];
369
+ // area codes
370
+ if (_c.areaCodes) {
371
+ var rootCountryCode = this.countryCodes[_c.dialCode][0];
372
+ // for each area code
373
+ for (var j = 0; j < _c.areaCodes.length; j++) {
374
+ var areaCode = _c.areaCodes[j];
375
+ // for each digit in the area code to add all partial matches as well
376
+ for (var k = 1; k < areaCode.length; k++) {
377
+ var partialDialCode = _c.dialCode + areaCode.substr(0, k);
378
+ // start with the root country, as that also matches this dial code
379
+ this._addCountryCode(rootCountryCode, partialDialCode);
380
+ this._addCountryCode(_c.iso2, partialDialCode);
381
+ }
382
+ // add the full area code
383
+ this._addCountryCode(_c.iso2, _c.dialCode + areaCode);
384
+ }
385
+ }
307
386
  }
308
387
  }
309
- // NOTE: if initialCountry is set to auto, that will be handled separately
310
- // format
311
- if (val) {
312
- // this wont be run after _updateDialCode as that's only called if no val
313
- this._updateValFromNumber(val);
388
+ }, {
389
+ key: "_processPreferredCountries",
390
+ value: function _processPreferredCountries() {
391
+ this.preferredCountries = [];
392
+ for (var i = 0; i < this.options.preferredCountries.length; i++) {
393
+ var countryCode = this.options.preferredCountries[i].toLowerCase();
394
+ var countryData = this._getCountryData(countryCode, false, true);
395
+ if (countryData) {
396
+ this.preferredCountries.push(countryData);
397
+ }
398
+ }
314
399
  }
315
- },
316
- // initialise the main event listeners: input keyup, and click selected flag
317
- _initListeners: function () {
318
- this._initKeyListeners();
319
- if (this.options.autoHideDialCode) {
320
- this._initFocusListeners();
400
+ }, {
401
+ key: "_createEl",
402
+ value: function _createEl(name, attrs, container) {
403
+ var el = document.createElement(name);
404
+ if (attrs) {
405
+ forEachProp(attrs, function(key, value) {
406
+ return el.setAttribute(key, value);
407
+ });
408
+ }
409
+ if (container) {
410
+ container.appendChild(el);
411
+ }
412
+ return el;
321
413
  }
322
- if (this.options.allowDropdown) {
323
- this._initDropdownListeners();
414
+ }, {
415
+ key: "_generateMarkup",
416
+ value: function _generateMarkup() {
417
+ // if autocomplete does not exist on the element and its form, then
418
+ // prevent autocomplete as there's no safe, cross-browser event we can react to, so it can
419
+ // easily put the plugin in an inconsistent state e.g. the wrong flag selected for the
420
+ // autocompleted number, which on submit could mean wrong number is saved
421
+ if (!this.telInput.hasAttribute("autocomplete") && !(this.telInput.form && this.telInput.form.hasAttribute("autocomplete"))) {
422
+ this.telInput.setAttribute("autocomplete", "off");
423
+ }
424
+ var _this$options = this.options, allowDropdown = _this$options.allowDropdown, separateDialCode = _this$options.separateDialCode, showFlags = _this$options.showFlags, customContainer = _this$options.customContainer, hiddenInput = _this$options.hiddenInput, dropdownContainer = _this$options.dropdownContainer;
425
+ // containers (mostly for positioning)
426
+ var parentClass = "iti";
427
+ if (allowDropdown) {
428
+ parentClass += " iti--allow-dropdown";
429
+ }
430
+ if (separateDialCode) {
431
+ parentClass += " iti--separate-dial-code";
432
+ }
433
+ if (showFlags) {
434
+ parentClass += " iti--show-flags";
435
+ }
436
+ if (customContainer) {
437
+ parentClass += " ".concat(customContainer);
438
+ }
439
+ var wrapper = this._createEl("div", {
440
+ "class": parentClass
441
+ });
442
+ this.telInput.parentNode.insertBefore(wrapper, this.telInput);
443
+ // only hide the flagsContainer if allowDropdown, showFlags and separateDialCode are all false
444
+ var showFlagsContainer = allowDropdown || showFlags || separateDialCode;
445
+ if (showFlagsContainer) {
446
+ this.flagsContainer = this._createEl("div", {
447
+ "class": "iti__flag-container"
448
+ }, wrapper);
449
+ }
450
+ wrapper.appendChild(this.telInput);
451
+ // selected flag (displayed to left of input)
452
+ // using Aria tags for "Select-Only Combobox Example"
453
+ // https://www.w3.org/WAI/ARIA/apg/patterns/combobox/examples/combobox-select-only/
454
+ if (showFlagsContainer) {
455
+ this.selectedFlag = this._createEl("div", _objectSpread({
456
+ "class": "iti__selected-flag"
457
+ }, allowDropdown && {
458
+ role: "combobox",
459
+ "aria-haspopup": "listbox",
460
+ "aria-controls": "iti-".concat(this.id, "__country-listbox"),
461
+ "aria-expanded": "false",
462
+ "aria-label": "Telephone country code"
463
+ }), this.flagsContainer);
464
+ }
465
+ if (showFlags) {
466
+ this.selectedFlagInner = this._createEl("div", {
467
+ "class": "iti__flag"
468
+ }, this.selectedFlag);
469
+ }
470
+ if (this.selectedFlag && this.telInput.disabled) {
471
+ this.selectedFlag.setAttribute("aria-disabled", "true");
472
+ }
473
+ if (separateDialCode) {
474
+ this.selectedDialCode = this._createEl("div", {
475
+ "class": "iti__selected-dial-code"
476
+ }, this.selectedFlag);
477
+ }
478
+ if (allowDropdown) {
479
+ if (!this.telInput.disabled) {
480
+ // make element focusable and tab navigable
481
+ this.selectedFlag.setAttribute("tabindex", "0");
482
+ }
483
+ this.dropdownArrow = this._createEl("div", {
484
+ "class": "iti__arrow"
485
+ }, this.selectedFlag);
486
+ // country dropdown: preferred countries, then divider, then all countries
487
+ this.countryList = this._createEl("ul", {
488
+ "class": "iti__country-list iti__hide",
489
+ id: "iti-".concat(this.id, "__country-listbox"),
490
+ role: "listbox",
491
+ "aria-label": "List of countries"
492
+ });
493
+ if (this.preferredCountries.length) {
494
+ this._appendListItems(this.preferredCountries, "iti__preferred", true);
495
+ this._createEl("li", {
496
+ "class": "iti__divider",
497
+ role: "separator",
498
+ "aria-disabled": "true"
499
+ }, this.countryList);
500
+ }
501
+ this._appendListItems(this.countries, "iti__standard");
502
+ // create dropdownContainer markup
503
+ if (dropdownContainer) {
504
+ this.dropdown = this._createEl("div", {
505
+ "class": "iti iti--container"
506
+ });
507
+ this.dropdown.appendChild(this.countryList);
508
+ } else {
509
+ this.flagsContainer.appendChild(this.countryList);
510
+ }
511
+ }
512
+ if (hiddenInput) {
513
+ var hiddenInputName = hiddenInput;
514
+ var name = this.telInput.getAttribute("name");
515
+ if (name) {
516
+ var i = name.lastIndexOf("[");
517
+ // if input name contains square brackets, then give the hidden input the same name,
518
+ // replacing the contents of the last set of brackets with the given hiddenInput name
519
+ if (i !== -1) {
520
+ hiddenInputName = "".concat(name.substr(0, i), "[").concat(hiddenInputName, "]");
521
+ }
522
+ }
523
+ this.hiddenInput = this._createEl("input", {
524
+ type: "hidden",
525
+ name: hiddenInputName
526
+ });
527
+ wrapper.appendChild(this.hiddenInput);
528
+ }
324
529
  }
325
- if (this.hiddenInput) {
326
- this._initHiddenInputListener();
530
+ }, {
531
+ key: "_appendListItems",
532
+ value: function _appendListItems(countries, className, preferred) {
533
+ // we create so many DOM elements, it is faster to build a temp string
534
+ // and then add everything to the DOM in one go at the end
535
+ var tmp = "";
536
+ // for each country
537
+ for (var i = 0; i < countries.length; i++) {
538
+ var c = countries[i];
539
+ var idSuffix = preferred ? "-preferred" : "";
540
+ // open the list item
541
+ tmp += "<li class='iti__country ".concat(className, "' tabIndex='-1' id='iti-").concat(this.id, "__item-").concat(c.iso2).concat(idSuffix, "' role='option' data-dial-code='").concat(c.dialCode, "' data-country-code='").concat(c.iso2, "' aria-selected='false'>");
542
+ // add the flag
543
+ if (this.options.showFlags) {
544
+ tmp += "<div class='iti__flag-box'><div class='iti__flag iti__".concat(c.iso2, "'></div></div>");
545
+ }
546
+ // and the country name and dial code
547
+ tmp += "<span class='iti__country-name'>".concat(c.name, "</span>");
548
+ tmp += "<span class='iti__dial-code'>+".concat(c.dialCode, "</span>");
549
+ // close the list item
550
+ tmp += "</li>";
551
+ }
552
+ this.countryList.insertAdjacentHTML("beforeend", tmp);
327
553
  }
328
- },
329
- // update hidden input on form submit
330
- _initHiddenInputListener: function () {
331
- var that = this;
332
- var form = this.telInput.closest("form");
333
- if (form.length) {
334
- form.submit(function () {
335
- that.hiddenInput.val(that.getNumber());
336
- });
554
+ }, {
555
+ key: "_setInitialState",
556
+ value: function _setInitialState() {
557
+ // fix firefox bug: when first load page (with input with value set to number with intl dial
558
+ // code) and initialising plugin removes the dial code from the input, then refresh page,
559
+ // and we try to init plugin again but this time on number without dial code so get grey flag
560
+ var attributeValue = this.telInput.getAttribute("value");
561
+ var inputValue = this.telInput.value;
562
+ var useAttribute = attributeValue && attributeValue.charAt(0) === "+" && (!inputValue || inputValue.charAt(0) !== "+");
563
+ var val = useAttribute ? attributeValue : inputValue;
564
+ var dialCode = this._getDialCode(val);
565
+ var isRegionlessNanp = this._isRegionlessNanp(val);
566
+ var _this$options2 = this.options, initialCountry = _this$options2.initialCountry, autoInsertDialCode = _this$options2.autoInsertDialCode;
567
+ // if we already have a dial code, and it's not a regionlessNanp, we can go ahead and set the
568
+ // flag, else fall back to the default country
569
+ if (dialCode && !isRegionlessNanp) {
570
+ this._updateFlagFromNumber(val);
571
+ } else if (initialCountry !== "auto") {
572
+ // see if we should select a flag
573
+ if (initialCountry) {
574
+ this._setFlag(initialCountry.toLowerCase());
575
+ } else {
576
+ if (dialCode && isRegionlessNanp) {
577
+ // has intl dial code, is regionless nanp, and no initialCountry, so default to US
578
+ this._setFlag("us");
579
+ } else {
580
+ // no dial code and no initialCountry, so default to first in list
581
+ this.defaultCountry = this.preferredCountries.length ? this.preferredCountries[0].iso2 : this.countries[0].iso2;
582
+ if (!val) {
583
+ this._setFlag(this.defaultCountry);
584
+ }
585
+ }
586
+ }
587
+ // if empty and autoInsertDialCode then insert the dial code
588
+ if (!val && autoInsertDialCode) {
589
+ this.telInput.value = "+".concat(this.selectedCountryData.dialCode);
590
+ }
591
+ }
592
+ // NOTE: if initialCountry is set to auto, that will be handled separately
593
+ // format - note this wont be run after _updateDialCode as that's only called if no val
594
+ if (val) {
595
+ this._updateValFromNumber(val);
596
+ }
337
597
  }
338
- },
339
- // initialise the dropdown listeners
340
- _initDropdownListeners: function () {
341
- var that = this;
342
- // hack for input nested inside label: clicking the selected-flag to open the dropdown would then automatically trigger a 2nd click on the input which would close it again
343
- var label = this.telInput.closest("label");
344
- if (label.length) {
345
- label.on("click" + this.ns, function (e) {
598
+ }, {
599
+ key: "_initListeners",
600
+ value: function _initListeners() {
601
+ this._initKeyListeners();
602
+ if (this.options.autoInsertDialCode) {
603
+ this._initBlurListeners();
604
+ }
605
+ if (this.options.allowDropdown) {
606
+ this._initDropdownListeners();
607
+ }
608
+ if (this.hiddenInput) {
609
+ this._initHiddenInputListener();
610
+ }
611
+ }
612
+ }, {
613
+ key: "_initHiddenInputListener",
614
+ value: function _initHiddenInputListener() {
615
+ var _this3 = this;
616
+ this._handleHiddenInputSubmit = function() {
617
+ _this3.hiddenInput.value = _this3.getNumber();
618
+ };
619
+ if (this.telInput.form) {
620
+ this.telInput.form.addEventListener("submit", this._handleHiddenInputSubmit);
621
+ }
622
+ }
623
+ }, {
624
+ key: "_getClosestLabel",
625
+ value: function _getClosestLabel() {
626
+ var el = this.telInput;
627
+ while (el && el.tagName !== "LABEL") {
628
+ el = el.parentNode;
629
+ }
630
+ return el;
631
+ }
632
+ }, {
633
+ key: "_initDropdownListeners",
634
+ value: function _initDropdownListeners() {
635
+ var _this4 = this;
636
+ // hack for input nested inside label (which is valid markup): clicking the selected-flag to
637
+ // open the dropdown would then automatically trigger a 2nd click on the input which would
638
+ // close it again
639
+ this._handleLabelClick = function(e) {
346
640
  // if the dropdown is closed, then focus the input, else ignore the click
347
- if (that.countryList.hasClass("hide")) {
348
- that.telInput.focus();
641
+ if (_this4.countryList.classList.contains("iti__hide")) {
642
+ _this4.telInput.focus();
349
643
  } else {
350
644
  e.preventDefault();
351
645
  }
352
- });
353
- }
354
- // toggle country dropdown on click
355
- var selectedFlag = this.selectedFlagInner.parent();
356
- selectedFlag.on("click" + this.ns, function (e) {
357
- // only intercept this event if we're opening the dropdown
358
- // else let it bubble up to the top ("click-off-to-close" listener)
359
- // we cannot just stopPropagation as it may be needed to close another instance
360
- if (that.countryList.hasClass("hide") && !that.telInput.prop("disabled") && !that.telInput.prop("readonly")) {
361
- that._showDropdown();
362
- }
363
- });
364
- // open dropdown list if currently focused
365
- this.flagsContainer.on("keydown" + that.ns, function (e) {
366
- var isDropdownHidden = that.countryList.hasClass("hide");
367
- if (isDropdownHidden && (e.which == keys.UP || e.which == keys.DOWN || e.which == keys.SPACE || e.which == keys.ENTER)) {
368
- // prevent form from being submitted if "ENTER" was pressed
369
- e.preventDefault();
370
- // prevent event from being handled again by document
371
- e.stopPropagation();
372
- that._showDropdown();
646
+ };
647
+ var label = this._getClosestLabel();
648
+ if (label) {
649
+ label.addEventListener("click", this._handleLabelClick);
373
650
  }
374
- // allow navigation from dropdown to input on TAB
375
- if (e.which == keys.TAB) {
376
- that._closeDropdown();
651
+ // toggle country dropdown on click
652
+ this._handleClickSelectedFlag = function() {
653
+ // only intercept this event if we're opening the dropdown
654
+ // else let it bubble up to the top ("click-off-to-close" listener)
655
+ // we cannot just stopPropagation as it may be needed to close another instance
656
+ if (_this4.countryList.classList.contains("iti__hide") && !_this4.telInput.disabled && !_this4.telInput.readOnly) {
657
+ _this4._showDropdown();
658
+ }
659
+ };
660
+ this.selectedFlag.addEventListener("click", this._handleClickSelectedFlag);
661
+ // open dropdown list if currently focused
662
+ this._handleFlagsContainerKeydown = function(e) {
663
+ var isDropdownHidden = _this4.countryList.classList.contains("iti__hide");
664
+ if (isDropdownHidden && [ "ArrowUp", "Up", "ArrowDown", "Down", " ", "Enter" ].indexOf(e.key) !== -1) {
665
+ // prevent form from being submitted if "ENTER" was pressed
666
+ e.preventDefault();
667
+ // prevent event from being handled again by document
668
+ e.stopPropagation();
669
+ _this4._showDropdown();
670
+ }
671
+ // allow navigation from dropdown to input on TAB
672
+ if (e.key === "Tab") {
673
+ _this4._closeDropdown();
674
+ }
675
+ };
676
+ this.flagsContainer.addEventListener("keydown", this._handleFlagsContainerKeydown);
677
+ }
678
+ }, {
679
+ key: "_initRequests",
680
+ value: function _initRequests() {
681
+ var _this5 = this;
682
+ // if the user has specified the path to the utils script, fetch it on window.load, else resolve
683
+ if (this.options.utilsScript && !window.intlTelInputUtils) {
684
+ // if the plugin is being initialised after the window.load event has already been fired
685
+ if (window.intlTelInputGlobals.documentReady()) {
686
+ window.intlTelInputGlobals.loadUtils(this.options.utilsScript);
687
+ } else {
688
+ // wait until the load event so we don't block any other requests e.g. the flags image
689
+ window.addEventListener("load", function() {
690
+ window.intlTelInputGlobals.loadUtils(_this5.options.utilsScript);
691
+ });
692
+ }
693
+ } else {
694
+ this.resolveUtilsScriptPromise();
377
695
  }
378
- });
379
- },
380
- // init many requests: utils script / geo ip lookup
381
- _initRequests: function () {
382
- var that = this;
383
- // if the user has specified the path to the utils script, fetch it on window.load, else resolve
384
- if (this.options.utilsScript) {
385
- // if the plugin is being initialised after the window.load event has already been fired
386
- if ($.fn[pluginName].windowLoaded) {
387
- $.fn[pluginName].loadUtils(this.options.utilsScript, this.utilsScriptDeferred);
696
+ if (this.options.initialCountry === "auto") {
697
+ this._loadAutoCountry();
388
698
  } else {
389
- // wait until the load event so we don't block any other requests e.g. the flags image
390
- $(window).on("load", function () {
391
- $.fn[pluginName].loadUtils(that.options.utilsScript, that.utilsScriptDeferred);
392
- });
699
+ this.resolveAutoCountryPromise();
393
700
  }
394
- } else {
395
- this.utilsScriptDeferred.resolve();
396
- }
397
- if (this.options.initialCountry === "auto") {
398
- this._loadAutoCountry();
399
- } else {
400
- this.autoCountryDeferred.resolve();
401
701
  }
402
- },
403
- // perform the geo ip lookup
404
- _loadAutoCountry: function () {
405
- var that = this;
406
- // 3 options:
407
- // 1) already loaded (we're done)
408
- // 2) not already started loading (start)
409
- // 3) already started loading (do nothing - just wait for loading callback to fire)
410
- if ($.fn[pluginName].autoCountry) {
411
- this.handleAutoCountry();
412
- } else if (!$.fn[pluginName].startedLoadingAutoCountry) {
413
- // don't do this twice!
414
- $.fn[pluginName].startedLoadingAutoCountry = true;
415
- if (typeof this.options.geoIpLookup === "function") {
416
- this.options.geoIpLookup(function (countryCode) {
417
- $.fn[pluginName].autoCountry = countryCode.toLowerCase();
418
- // tell all instances the auto country is ready
419
- // TODO: this should just be the current instances
420
- // UPDATE: use setTimeout in case their geoIpLookup function calls this callback straight away (e.g. if they have already done the geo ip lookup somewhere else). Using setTimeout means that the current thread of execution will finish before executing this, which allows the plugin to finish initialising.
421
- setTimeout(function () {
422
- $(".intl-tel-input input").intlTelInput("handleAutoCountry");
702
+ }, {
703
+ key: "_loadAutoCountry",
704
+ value: function _loadAutoCountry() {
705
+ // 3 options:
706
+ // 1) already loaded (we're done)
707
+ // 2) not already started loading (start)
708
+ // 3) already started loading (do nothing - just wait for loading callback to fire)
709
+ if (window.intlTelInputGlobals.autoCountry) {
710
+ this.handleAutoCountry();
711
+ } else if (!window.intlTelInputGlobals.startedLoadingAutoCountry) {
712
+ // don't do this twice!
713
+ window.intlTelInputGlobals.startedLoadingAutoCountry = true;
714
+ if (typeof this.options.geoIpLookup === "function") {
715
+ this.options.geoIpLookup(function(countryCode) {
716
+ window.intlTelInputGlobals.autoCountry = countryCode.toLowerCase();
717
+ // tell all instances the auto country is ready
718
+ // TODO: this should just be the current instances
719
+ // UPDATE: use setTimeout in case their geoIpLookup function calls this callback straight
720
+ // away (e.g. if they have already done the geo ip lookup somewhere else). Using
721
+ // setTimeout means that the current thread of execution will finish before executing
722
+ // this, which allows the plugin to finish initialising.
723
+ setTimeout(function() {
724
+ return forEachInstance("handleAutoCountry");
725
+ });
726
+ }, function() {
727
+ return forEachInstance("rejectAutoCountryPromise");
423
728
  });
424
- });
729
+ }
425
730
  }
426
731
  }
427
- },
428
- // initialize any key listeners
429
- _initKeyListeners: function () {
430
- var that = this;
431
- // update flag on keyup
432
- // (keep this listener separate otherwise the setTimeout breaks all the tests)
433
- this.telInput.on("keyup" + this.ns, function () {
434
- if (that._updateFlagFromNumber(that.telInput.val())) {
435
- that._triggerCountryChange();
732
+ }, {
733
+ key: "_initKeyListeners",
734
+ value: function _initKeyListeners() {
735
+ var _this6 = this;
736
+ // update flag on keyup
737
+ this._handleKeyupEvent = function() {
738
+ if (_this6._updateFlagFromNumber(_this6.telInput.value)) {
739
+ _this6._triggerCountryChange();
740
+ }
741
+ };
742
+ this.telInput.addEventListener("keyup", this._handleKeyupEvent);
743
+ // update flag on cut/paste events (now supported in all major browsers)
744
+ this._handleClipboardEvent = function() {
745
+ // hack because "paste" event is fired before input is updated
746
+ setTimeout(_this6._handleKeyupEvent);
747
+ };
748
+ this.telInput.addEventListener("cut", this._handleClipboardEvent);
749
+ this.telInput.addEventListener("paste", this._handleClipboardEvent);
750
+ }
751
+ }, {
752
+ key: "_cap",
753
+ value: function _cap(number) {
754
+ var max = this.telInput.getAttribute("maxlength");
755
+ return max && number.length > max ? number.substr(0, max) : number;
756
+ }
757
+ }, {
758
+ key: "_initBlurListeners",
759
+ value: function _initBlurListeners() {
760
+ var _this7 = this;
761
+ // on blur or form submit: if just a dial code then remove it
762
+ this._handleSubmitOrBlurEvent = function() {
763
+ _this7._removeEmptyDialCode();
764
+ };
765
+ if (this.telInput.form) {
766
+ this.telInput.form.addEventListener("submit", this._handleSubmitOrBlurEvent);
436
767
  }
437
- });
438
- // update flag on cut/paste events (now supported in all major browsers)
439
- this.telInput.on("cut" + this.ns + " paste" + this.ns, function () {
440
- // hack because "paste" event is fired before input is updated
441
- setTimeout(function () {
442
- if (that._updateFlagFromNumber(that.telInput.val())) {
443
- that._triggerCountryChange();
768
+ this.telInput.addEventListener("blur", this._handleSubmitOrBlurEvent);
769
+ }
770
+ }, {
771
+ key: "_removeEmptyDialCode",
772
+ value: function _removeEmptyDialCode() {
773
+ if (this.telInput.value.charAt(0) === "+") {
774
+ var numeric = this._getNumeric(this.telInput.value);
775
+ // if just a plus, or if just a dial code
776
+ if (!numeric || this.selectedCountryData.dialCode === numeric) {
777
+ this.telInput.value = "";
444
778
  }
445
- });
446
- });
447
- },
448
- // adhere to the input's maxlength attr
449
- _cap: function (number) {
450
- var max = this.telInput.attr("maxlength");
451
- return max && number.length > max ? number.substr(0, max) : number;
452
- },
453
- // listen for mousedown, focus and blur
454
- _initFocusListeners: function () {
455
- var that = this;
456
- // mousedown decides where the cursor goes, so if we're focusing we must preventDefault as we'll be inserting the dial code, and we want the cursor to be at the end no matter where they click
457
- this.telInput.on("mousedown" + this.ns, function (e) {
458
- if (!that.telInput.is(":focus") && !that.telInput.val()) {
459
- e.preventDefault();
460
- // but this also cancels the focus, so we must trigger that manually
461
- that.telInput.focus();
462
779
  }
463
- });
464
- // on focus: if empty, insert the dial code for the currently selected flag
465
- this.telInput.on("focus" + this.ns, function (e) {
466
- if (!that.telInput.val() && !that.telInput.prop("readonly") && that.selectedCountryData.dialCode) {
467
- // insert the dial code
468
- that.telInput.val("+" + that.selectedCountryData.dialCode);
469
- // after auto-inserting a dial code, if the first key they hit is '+' then assume they are entering a new number, so remove the dial code. use keypress instead of keydown because keydown gets triggered for the shift key (required to hit the + key), and instead of keyup because that shows the new '+' before removing the old one
470
- that.telInput.one("keypress.plus" + that.ns, function (e) {
471
- if (e.which == keys.PLUS) {
472
- that.telInput.val("");
473
- }
474
- });
475
- // after tabbing in, make sure the cursor is at the end we must use setTimeout to get outside of the focus handler as it seems the selection happens after that
476
- setTimeout(function () {
477
- var input = that.telInput[0];
478
- if (that.isGoodBrowser) {
479
- var len = that.telInput.val().length;
480
- input.setSelectionRange(len, len);
481
- }
482
- });
780
+ }
781
+ }, {
782
+ key: "_getNumeric",
783
+ value: function _getNumeric(s) {
784
+ return s.replace(/\D/g, "");
785
+ }
786
+ }, {
787
+ key: "_trigger",
788
+ value: function _trigger(name) {
789
+ // have to use old school document.createEvent as IE11 doesn't support `new Event()` syntax
790
+ var e = document.createEvent("Event");
791
+ e.initEvent(name, true, true);
792
+ // can bubble, and is cancellable
793
+ this.telInput.dispatchEvent(e);
794
+ }
795
+ }, {
796
+ key: "_showDropdown",
797
+ value: function _showDropdown() {
798
+ this.countryList.classList.remove("iti__hide");
799
+ this.selectedFlag.setAttribute("aria-expanded", "true");
800
+ this._setDropdownPosition();
801
+ // update highlighting and scroll to active list item
802
+ if (this.activeItem) {
803
+ this._highlightListItem(this.activeItem, false);
804
+ this._scrollTo(this.activeItem, true);
483
805
  }
484
- });
485
- // on blur or form submit: if just a dial code then remove it
486
- var form = this.telInput.prop("form");
487
- if (form) {
488
- $(form).on("submit" + this.ns, function () {
489
- that._removeEmptyDialCode();
490
- });
806
+ // bind all the dropdown-related listeners: mouseover, click, click-off, keydown
807
+ this._bindDropdownListeners();
808
+ // update the arrow
809
+ this.dropdownArrow.classList.add("iti__arrow--up");
810
+ this._trigger("open:countrydropdown");
491
811
  }
492
- this.telInput.on("blur" + this.ns, function () {
493
- that._removeEmptyDialCode();
494
- });
495
- },
496
- _removeEmptyDialCode: function () {
497
- var value = this.telInput.val(), startsPlus = value.charAt(0) == "+";
498
- if (startsPlus) {
499
- var numeric = this._getNumeric(value);
500
- // if just a plus, or if just a dial code
501
- if (!numeric || this.selectedCountryData.dialCode == numeric) {
502
- this.telInput.val("");
812
+ }, {
813
+ key: "_toggleClass",
814
+ value: function _toggleClass(el, className, shouldHaveClass) {
815
+ if (shouldHaveClass && !el.classList.contains(className)) {
816
+ el.classList.add(className);
817
+ } else if (!shouldHaveClass && el.classList.contains(className)) {
818
+ el.classList.remove(className);
503
819
  }
504
820
  }
505
- // remove the keypress listener we added on focus
506
- this.telInput.off("keypress.plus" + this.ns);
507
- },
508
- // extract the numeric digits from the given string
509
- _getNumeric: function (s) {
510
- return s.replace(/\D/g, "");
511
- },
512
- // show the dropdown
513
- _showDropdown: function () {
514
- this._setDropdownPosition();
515
- // update highlighting and scroll to active list item
516
- var activeListItem = this.countryList.children(".active");
517
- if (activeListItem.length) {
518
- this._highlightListItem(activeListItem);
519
- this._scrollTo(activeListItem);
520
- }
521
- // bind all the dropdown-related listeners: mouseover, click, click-off, keydown
522
- this._bindDropdownListeners();
523
- // update the arrow
524
- this.selectedFlagInner.children(".iti-arrow").addClass("up");
525
- this.telInput.trigger("open:countrydropdown");
526
- },
527
- // decide where to position dropdown (depends on position within viewport, and scroll)
528
- _setDropdownPosition: function () {
529
- var that = this;
530
- if (this.options.dropdownContainer) {
531
- this.dropdown.appendTo(this.options.dropdownContainer);
532
- }
533
- // show the menu and grab the dropdown height
534
- this.dropdownHeight = this.countryList.removeClass("hide").outerHeight();
535
- if (!this.isMobile) {
536
- var pos = this.telInput.offset(), inputTop = pos.top, windowTop = $(window).scrollTop(), // dropdownFitsBelow = (dropdownBottom < windowBottom)
537
- dropdownFitsBelow = inputTop + this.telInput.outerHeight() + this.dropdownHeight < windowTop + $(window).height(), dropdownFitsAbove = inputTop - this.dropdownHeight > windowTop;
538
- // by default, the dropdown will be below the input. If we want to position it above the input, we add the dropup class.
539
- this.countryList.toggleClass("dropup", !dropdownFitsBelow && dropdownFitsAbove);
540
- // if dropdownContainer is enabled, calculate postion
821
+ }, {
822
+ key: "_setDropdownPosition",
823
+ value: function _setDropdownPosition() {
824
+ var _this8 = this;
541
825
  if (this.options.dropdownContainer) {
542
- // by default the dropdown will be directly over the input because it's not in the flow. If we want to position it below, we need to add some extra top value.
543
- var extraTop = !dropdownFitsBelow && dropdownFitsAbove ? 0 : this.telInput.innerHeight();
544
- // calculate placement
545
- this.dropdown.css({
546
- top: inputTop + extraTop,
547
- left: pos.left
548
- });
549
- // close menu on window scroll
550
- $(window).on("scroll" + this.ns, function () {
551
- that._closeDropdown();
552
- });
826
+ this.options.dropdownContainer.appendChild(this.dropdown);
827
+ }
828
+ if (!this.isMobile) {
829
+ var pos = this.telInput.getBoundingClientRect();
830
+ // windowTop from https://stackoverflow.com/a/14384091/217866
831
+ var windowTop = window.pageYOffset || document.documentElement.scrollTop;
832
+ var inputTop = pos.top + windowTop;
833
+ var dropdownHeight = this.countryList.offsetHeight;
834
+ // dropdownFitsBelow = (dropdownBottom < windowBottom)
835
+ var dropdownFitsBelow = inputTop + this.telInput.offsetHeight + dropdownHeight < windowTop + window.innerHeight;
836
+ var dropdownFitsAbove = inputTop - dropdownHeight > windowTop;
837
+ // by default, the dropdown will be below the input. If we want to position it above the
838
+ // input, we add the dropup class.
839
+ this._toggleClass(this.countryList, "iti__country-list--dropup", !dropdownFitsBelow && dropdownFitsAbove);
840
+ // if dropdownContainer is enabled, calculate postion
841
+ if (this.options.dropdownContainer) {
842
+ // by default the dropdown will be directly over the input because it's not in the flow.
843
+ // If we want to position it below, we need to add some extra top value.
844
+ var extraTop = !dropdownFitsBelow && dropdownFitsAbove ? 0 : this.telInput.offsetHeight;
845
+ // calculate placement
846
+ this.dropdown.style.top = "".concat(inputTop + extraTop, "px");
847
+ this.dropdown.style.left = "".concat(pos.left + document.body.scrollLeft, "px");
848
+ // close menu on window scroll
849
+ this._handleWindowScroll = function() {
850
+ return _this8._closeDropdown();
851
+ };
852
+ window.addEventListener("scroll", this._handleWindowScroll);
853
+ }
553
854
  }
554
855
  }
555
- },
556
- // we only bind dropdown listeners when the dropdown is open
557
- _bindDropdownListeners: function () {
558
- var that = this;
559
- // when mouse over a list item, just highlight that one
560
- // we add the class "highlight", so if they hit "enter" we know which one to select
561
- this.countryList.on("mouseover" + this.ns, ".country", function (e) {
562
- that._highlightListItem($(this));
563
- });
564
- // listen for country selection
565
- this.countryList.on("click" + this.ns, ".country", function (e) {
566
- that._selectListItem($(this));
567
- });
568
- // click off to close
569
- // (except when this initial opening click is bubbling up)
570
- // we cannot just stopPropagation as it may be needed to close another instance
571
- var isOpening = true;
572
- $("html").on("click" + this.ns, function (e) {
573
- if (!isOpening) {
574
- that._closeDropdown();
575
- }
576
- isOpening = false;
577
- });
578
- // listen for up/down scrolling, enter to select, or letters to jump to country name.
579
- // use keydown as keypress doesn't fire for non-char keys and we want to catch if they
580
- // just hit down and hold it to scroll down (no keyup event).
581
- // listen on the document because that's where key events are triggered if no input has focus
582
- var query = "", queryTimer = null;
583
- $(document).on("keydown" + this.ns, function (e) {
584
- // prevent down key from scrolling the whole page,
585
- // and enter key from submitting a form etc
586
- e.preventDefault();
587
- if (e.which == keys.UP || e.which == keys.DOWN) {
856
+ }, {
857
+ key: "_getClosestListItem",
858
+ value: function _getClosestListItem(target) {
859
+ var el = target;
860
+ while (el && el !== this.countryList && !el.classList.contains("iti__country")) {
861
+ el = el.parentNode;
862
+ }
863
+ // if we reached the countryList element, then return null
864
+ return el === this.countryList ? null : el;
865
+ }
866
+ }, {
867
+ key: "_bindDropdownListeners",
868
+ value: function _bindDropdownListeners() {
869
+ var _this9 = this;
870
+ // when mouse over a list item, just highlight that one
871
+ // we add the class "highlight", so if they hit "enter" we know which one to select
872
+ this._handleMouseoverCountryList = function(e) {
873
+ // handle event delegation, as we're listening for this event on the countryList
874
+ var listItem = _this9._getClosestListItem(e.target);
875
+ if (listItem) {
876
+ _this9._highlightListItem(listItem, false);
877
+ }
878
+ };
879
+ this.countryList.addEventListener("mouseover", this._handleMouseoverCountryList);
880
+ // listen for country selection
881
+ this._handleClickCountryList = function(e) {
882
+ var listItem = _this9._getClosestListItem(e.target);
883
+ if (listItem) {
884
+ _this9._selectListItem(listItem);
885
+ }
886
+ };
887
+ this.countryList.addEventListener("click", this._handleClickCountryList);
888
+ // click off to close
889
+ // (except when this initial opening click is bubbling up)
890
+ // we cannot just stopPropagation as it may be needed to close another instance
891
+ var isOpening = true;
892
+ this._handleClickOffToClose = function() {
893
+ if (!isOpening) {
894
+ _this9._closeDropdown();
895
+ }
896
+ isOpening = false;
897
+ };
898
+ document.documentElement.addEventListener("click", this._handleClickOffToClose);
899
+ // listen for up/down scrolling, enter to select, or letters to jump to country name.
900
+ // use keydown as keypress doesn't fire for non-char keys and we want to catch if they
901
+ // just hit down and hold it to scroll down (no keyup event).
902
+ // listen on the document because that's where key events are triggered if no input has focus
903
+ var query = "";
904
+ var queryTimer = null;
905
+ this._handleKeydownOnDropdown = function(e) {
906
+ // prevent down key from scrolling the whole page,
907
+ // and enter key from submitting a form etc
908
+ e.preventDefault();
588
909
  // up and down to navigate
589
- that._handleUpDownKey(e.which);
590
- } else if (e.which == keys.ENTER) {
591
- // enter to select
592
- that._handleEnterKey();
593
- } else if (e.which == keys.ESC) {
594
- // esc to close
595
- that._closeDropdown();
596
- } else if (e.which >= keys.A && e.which <= keys.Z || e.which == keys.SPACE) {
597
- // upper case letters (note: keyup/keydown only return upper case letters)
598
- // jump to countries that start with the query string
599
- if (queryTimer) {
600
- clearTimeout(queryTimer);
910
+ if (e.key === "ArrowUp" || e.key === "Up" || e.key === "ArrowDown" || e.key === "Down") {
911
+ _this9._handleUpDownKey(e.key);
912
+ } else if (e.key === "Enter") {
913
+ _this9._handleEnterKey();
914
+ } else if (e.key === "Escape") {
915
+ _this9._closeDropdown();
916
+ } else if (/^[a-zA-ZÀ-ÿа-яА-Я ]$/.test(e.key)) {
917
+ // jump to countries that start with the query string
918
+ if (queryTimer) {
919
+ clearTimeout(queryTimer);
920
+ }
921
+ query += e.key.toLowerCase();
922
+ _this9._searchForCountry(query);
923
+ // if the timer hits 1 second, reset the query
924
+ queryTimer = setTimeout(function() {
925
+ query = "";
926
+ }, 1e3);
927
+ }
928
+ };
929
+ document.addEventListener("keydown", this._handleKeydownOnDropdown);
930
+ }
931
+ }, {
932
+ key: "_handleUpDownKey",
933
+ value: function _handleUpDownKey(key) {
934
+ var next = key === "ArrowUp" || key === "Up" ? this.highlightedItem.previousElementSibling : this.highlightedItem.nextElementSibling;
935
+ if (next) {
936
+ // skip the divider
937
+ if (next.classList.contains("iti__divider")) {
938
+ next = key === "ArrowUp" || key === "Up" ? next.previousElementSibling : next.nextElementSibling;
601
939
  }
602
- query += String.fromCharCode(e.which);
603
- that._searchForCountry(query);
604
- // if the timer hits 1 second, reset the query
605
- queryTimer = setTimeout(function () {
606
- query = "";
607
- }, 1e3);
940
+ this._highlightListItem(next, true);
608
941
  }
609
- });
610
- },
611
- // highlight the next/prev item in the list (and ensure it is visible)
612
- _handleUpDownKey: function (key) {
613
- var current = this.countryList.children(".highlight").first();
614
- var next = key == keys.UP ? current.prev() : current.next();
615
- if (next.length) {
616
- // skip the divider
617
- if (next.hasClass("divider")) {
618
- next = key == keys.UP ? next.prev() : next.next();
619
- }
620
- this._highlightListItem(next);
621
- this._scrollTo(next);
622
942
  }
623
- },
624
- // select the currently highlighted item
625
- _handleEnterKey: function () {
626
- var currentCountry = this.countryList.children(".highlight").first();
627
- if (currentCountry.length) {
628
- this._selectListItem(currentCountry);
943
+ }, {
944
+ key: "_handleEnterKey",
945
+ value: function _handleEnterKey() {
946
+ if (this.highlightedItem) {
947
+ this._selectListItem(this.highlightedItem);
948
+ }
629
949
  }
630
- },
631
- // find the first list item whose name starts with the query string
632
- _searchForCountry: function (query) {
633
- for (var i = 0; i < this.countries.length; i++) {
634
- if (this._startsWith(this.countries[i].name, query)) {
635
- var listItem = this.countryList.children("[data-country-code=" + this.countries[i].iso2 + "]").not(".preferred");
636
- // update highlighting and scroll
637
- this._highlightListItem(listItem);
638
- this._scrollTo(listItem, true);
639
- break;
950
+ }, {
951
+ key: "_searchForCountry",
952
+ value: function _searchForCountry(query) {
953
+ for (var i = 0; i < this.countries.length; i++) {
954
+ if (this._startsWith(this.countries[i].name, query)) {
955
+ var listItem = this.countryList.querySelector("#iti-".concat(this.id, "__item-").concat(this.countries[i].iso2));
956
+ // update highlighting and scroll
957
+ this._highlightListItem(listItem, false);
958
+ this._scrollTo(listItem, true);
959
+ break;
960
+ }
640
961
  }
641
962
  }
642
- },
643
- // check if (uppercase) string a starts with string b
644
- _startsWith: function (a, b) {
645
- return a.substr(0, b.length).toUpperCase() == b;
646
- },
647
- // update the input's value to the given val (format first if possible)
648
- // NOTE: this is called from _setInitialState, handleUtils and setNumber
649
- _updateValFromNumber: function (number) {
650
- if (this.options.formatOnDisplay && window.intlTelInputUtils && this.selectedCountryData) {
651
- var format = !this.options.separateDialCode && (this.options.nationalMode || number.charAt(0) != "+") ? intlTelInputUtils.numberFormat.NATIONAL : intlTelInputUtils.numberFormat.INTERNATIONAL;
652
- number = intlTelInputUtils.formatNumber(number, this.selectedCountryData.iso2, format);
653
- }
654
- number = this._beforeSetNumber(number);
655
- this.telInput.val(number);
656
- },
657
- // check if need to select a new flag based on the given number
658
- // Note: called from _setInitialState, keyup handler, setNumber
659
- _updateFlagFromNumber: function (number) {
660
- // if we're in nationalMode and we already have US/Canada selected, make sure the number starts with a +1 so _getDialCode will be able to extract the area code
661
- // update: if we dont yet have selectedCountryData, but we're here (trying to update the flag from the number), that means we're initialising the plugin with a number that already has a dial code, so fine to ignore this bit
662
- if (number && this.options.nationalMode && this.selectedCountryData.dialCode == "1" && number.charAt(0) != "+") {
663
- if (number.charAt(0) != "1") {
664
- number = "1" + number;
665
- }
666
- number = "+" + number;
667
- }
668
- // try and extract valid dial code from input
669
- var dialCode = this._getDialCode(number), countryCode = null, numeric = this._getNumeric(number);
670
- if (dialCode) {
671
- // check if one of the matching countries is already selected
672
- var countryCodes = this.countryCodes[this._getNumeric(dialCode)], alreadySelected = $.inArray(this.selectedCountryData.iso2, countryCodes) > -1, // check if the given number contains a NANP area code i.e. the only dialCode that could be extracted was +1 (instead of say +1204) and the actual number's length is >=4
673
- isNanpAreaCode = dialCode == "+1" && numeric.length >= 4, nanpSelected = this.selectedCountryData.dialCode == "1";
674
- // only update the flag if:
675
- // A) NOT (we currently have a NANP flag selected, and the number is a regionlessNanp)
676
- // AND
677
- // B) either a matching country is not already selected OR the number contains a NANP area code (ensure the flag is set to the first matching country)
678
- if (!(nanpSelected && this._isRegionlessNanp(numeric)) && (!alreadySelected || isNanpAreaCode)) {
679
- // if using onlyCountries option, countryCodes[0] may be empty, so we must find the first non-empty index
680
- for (var j = 0; j < countryCodes.length; j++) {
681
- if (countryCodes[j]) {
682
- countryCode = countryCodes[j];
683
- break;
963
+ }, {
964
+ key: "_startsWith",
965
+ value: function _startsWith(a, b) {
966
+ return a.substr(0, b.length).toLowerCase() === b;
967
+ }
968
+ }, {
969
+ key: "_updateValFromNumber",
970
+ value: function _updateValFromNumber(originalNumber) {
971
+ var number = originalNumber;
972
+ if (this.options.formatOnDisplay && window.intlTelInputUtils && this.selectedCountryData) {
973
+ var useNational = this.options.nationalMode || number.charAt(0) !== "+" && !this.options.separateDialCode;
974
+ var _intlTelInputUtils$nu = intlTelInputUtils.numberFormat, NATIONAL = _intlTelInputUtils$nu.NATIONAL, INTERNATIONAL = _intlTelInputUtils$nu.INTERNATIONAL;
975
+ var format = useNational ? NATIONAL : INTERNATIONAL;
976
+ number = intlTelInputUtils.formatNumber(number, this.selectedCountryData.iso2, format);
977
+ }
978
+ number = this._beforeSetNumber(number);
979
+ this.telInput.value = number;
980
+ }
981
+ }, {
982
+ key: "_updateFlagFromNumber",
983
+ value: function _updateFlagFromNumber(originalNumber) {
984
+ // if we already have US/Canada selected, make sure the number starts
985
+ // with a +1 so _getDialCode will be able to extract the area code
986
+ // update: if we dont yet have selectedCountryData, but we're here (trying to update the flag
987
+ // from the number), that means we're initialising the plugin with a number that already has a
988
+ // dial code, so fine to ignore this bit
989
+ var number = originalNumber;
990
+ var selectedDialCode = this.selectedCountryData.dialCode;
991
+ var isNanp = selectedDialCode === "1";
992
+ if (number && isNanp && number.charAt(0) !== "+") {
993
+ if (number.charAt(0) !== "1") {
994
+ number = "1".concat(number);
995
+ }
996
+ number = "+".concat(number);
997
+ }
998
+ // if separateDialCode enabled, then consider the selected dial code to be part of the number
999
+ if (this.options.separateDialCode && selectedDialCode && number.charAt(0) !== "+") {
1000
+ number = "+".concat(selectedDialCode).concat(number);
1001
+ }
1002
+ // try and extract valid dial code from input
1003
+ var dialCode = this._getDialCode(number, true);
1004
+ var numeric = this._getNumeric(number);
1005
+ var countryCode = null;
1006
+ if (dialCode) {
1007
+ var countryCodes = this.countryCodes[this._getNumeric(dialCode)];
1008
+ // check if the right country is already selected. this should be false if the number is
1009
+ // longer than the matched dial code because in this case we need to make sure that if
1010
+ // there are multiple country matches, that the first one is selected (note: we could
1011
+ // just check that here, but it requires the same loop that we already have later)
1012
+ var alreadySelected = countryCodes.indexOf(this.selectedCountryData.iso2) !== -1 && numeric.length <= dialCode.length - 1;
1013
+ var isRegionlessNanpNumber = selectedDialCode === "1" && this._isRegionlessNanp(numeric);
1014
+ // only update the flag if:
1015
+ // A) NOT (we currently have a NANP flag selected, and the number is a regionlessNanp)
1016
+ // AND
1017
+ // B) the right country is not already selected
1018
+ if (!isRegionlessNanpNumber && !alreadySelected) {
1019
+ // if using onlyCountries option, countryCodes[0] may be empty, so we must find the first
1020
+ // non-empty index
1021
+ for (var j = 0; j < countryCodes.length; j++) {
1022
+ if (countryCodes[j]) {
1023
+ countryCode = countryCodes[j];
1024
+ break;
1025
+ }
684
1026
  }
685
1027
  }
1028
+ } else if (number.charAt(0) === "+" && numeric.length) {
1029
+ // invalid dial code, so empty
1030
+ // Note: use getNumeric here because the number has not been formatted yet, so could contain
1031
+ // bad chars
1032
+ countryCode = "";
1033
+ } else if (!number || number === "+") {
1034
+ // empty, or just a plus, so default
1035
+ countryCode = this.defaultCountry;
1036
+ }
1037
+ if (countryCode !== null) {
1038
+ return this._setFlag(countryCode);
686
1039
  }
687
- } else if (number.charAt(0) == "+" && numeric.length) {
688
- // invalid dial code, so empty
689
- // Note: use getNumeric here because the number has not been formatted yet, so could contain bad chars
690
- countryCode = "";
691
- } else if (!number || number == "+") {
692
- // empty, or just a plus, so default
693
- countryCode = this.defaultCountry;
1040
+ return false;
694
1041
  }
695
- if (countryCode !== null) {
696
- return this._setFlag(countryCode);
1042
+ }, {
1043
+ key: "_isRegionlessNanp",
1044
+ value: function _isRegionlessNanp(number) {
1045
+ var numeric = this._getNumeric(number);
1046
+ if (numeric.charAt(0) === "1") {
1047
+ var areaCode = numeric.substr(1, 3);
1048
+ return regionlessNanpNumbers.indexOf(areaCode) !== -1;
1049
+ }
1050
+ return false;
697
1051
  }
698
- return false;
699
- },
700
- // check if the given number is a regionless NANP number (expects the number to contain an international dial code)
701
- _isRegionlessNanp: function (number) {
702
- var numeric = this._getNumeric(number);
703
- if (numeric.charAt(0) == "1") {
704
- var areaCode = numeric.substr(1, 3);
705
- return $.inArray(areaCode, regionlessNanpNumbers) > -1;
706
- }
707
- return false;
708
- },
709
- // remove highlighting from other list items and highlight the given item
710
- _highlightListItem: function (listItem) {
711
- this.countryListItems.removeClass("highlight");
712
- listItem.addClass("highlight");
713
- },
714
- // find the country data for the given country code
715
- // the ignoreOnlyCountriesOption is only used during init() while parsing the onlyCountries array
716
- _getCountryData: function (countryCode, ignoreOnlyCountriesOption, allowFail) {
717
- var countryList = ignoreOnlyCountriesOption ? allCountries : this.countries;
718
- for (var i = 0; i < countryList.length; i++) {
719
- if (countryList[i].iso2 == countryCode) {
720
- return countryList[i];
1052
+ }, {
1053
+ key: "_highlightListItem",
1054
+ value: function _highlightListItem(listItem, shouldFocus) {
1055
+ var prevItem = this.highlightedItem;
1056
+ if (prevItem) {
1057
+ prevItem.classList.remove("iti__highlight");
1058
+ }
1059
+ this.highlightedItem = listItem;
1060
+ this.highlightedItem.classList.add("iti__highlight");
1061
+ this.selectedFlag.setAttribute("aria-activedescendant", listItem.getAttribute("id"));
1062
+ if (shouldFocus) {
1063
+ this.highlightedItem.focus();
721
1064
  }
722
1065
  }
723
- if (allowFail) {
724
- return null;
725
- } else {
726
- throw new Error("No country data for '" + countryCode + "'");
1066
+ }, {
1067
+ key: "_getCountryData",
1068
+ value: function _getCountryData(countryCode, ignoreOnlyCountriesOption, allowFail) {
1069
+ var countryList = ignoreOnlyCountriesOption ? allCountries : this.countries;
1070
+ for (var i = 0; i < countryList.length; i++) {
1071
+ if (countryList[i].iso2 === countryCode) {
1072
+ return countryList[i];
1073
+ }
1074
+ }
1075
+ if (allowFail) {
1076
+ return null;
1077
+ }
1078
+ throw new Error("No country data for '".concat(countryCode, "'"));
727
1079
  }
728
- },
729
- // select the given flag, update the placeholder and the active list item
730
- // Note: called from _setInitialState, _updateFlagFromNumber, _selectListItem, setCountry
731
- _setFlag: function (countryCode) {
732
- var prevCountry = this.selectedCountryData.iso2 ? this.selectedCountryData : {};
733
- // do this first as it will throw an error and stop if countryCode is invalid
734
- this.selectedCountryData = countryCode ? this._getCountryData(countryCode, false, false) : {};
735
- // update the defaultCountry - we only need the iso2 from now on, so just store that
736
- if (this.selectedCountryData.iso2) {
737
- this.defaultCountry = this.selectedCountryData.iso2;
738
- }
739
- this.selectedFlagInner.attr("class", "iti-flag " + countryCode);
740
- // update the selected country's title attribute
741
- var title = countryCode ? this.selectedCountryData.name + ": +" + this.selectedCountryData.dialCode : "Unknown";
742
- this.selectedFlagInner.parent().attr("title", title);
743
- if (this.options.separateDialCode) {
744
- var dialCode = this.selectedCountryData.dialCode ? "+" + this.selectedCountryData.dialCode : "", parent = this.telInput.parent();
745
- if (prevCountry.dialCode) {
746
- parent.removeClass("iti-sdc-" + (prevCountry.dialCode.length + 1));
1080
+ }, {
1081
+ key: "_setFlag",
1082
+ value: function _setFlag(countryCode) {
1083
+ var _this$options3 = this.options, allowDropdown = _this$options3.allowDropdown, separateDialCode = _this$options3.separateDialCode, showFlags = _this$options3.showFlags;
1084
+ var prevCountry = this.selectedCountryData.iso2 ? this.selectedCountryData : {};
1085
+ // do this first as it will throw an error and stop if countryCode is invalid
1086
+ this.selectedCountryData = countryCode ? this._getCountryData(countryCode, false, false) : {};
1087
+ // update the defaultCountry - we only need the iso2 from now on, so just store that
1088
+ if (this.selectedCountryData.iso2) {
1089
+ this.defaultCountry = this.selectedCountryData.iso2;
747
1090
  }
748
- if (dialCode) {
749
- parent.addClass("iti-sdc-" + dialCode.length);
1091
+ if (showFlags) {
1092
+ this.selectedFlagInner.setAttribute("class", "iti__flag iti__".concat(countryCode));
1093
+ }
1094
+ this._setSelectedCountryFlagTitleAttribute(countryCode, separateDialCode);
1095
+ if (separateDialCode) {
1096
+ var dialCode = this.selectedCountryData.dialCode ? "+".concat(this.selectedCountryData.dialCode) : "";
1097
+ this.selectedDialCode.innerHTML = dialCode;
1098
+ // offsetWidth is zero if input is in a hidden container during initialisation
1099
+ var selectedFlagWidth = this.selectedFlag.offsetWidth || this._getHiddenSelectedFlagWidth();
1100
+ // add 6px of padding after the grey selected-dial-code box, as this is what we use in the css
1101
+ if (this.isRTL) {
1102
+ this.telInput.style.paddingRight = "".concat(selectedFlagWidth + 6, "px");
1103
+ } else {
1104
+ this.telInput.style.paddingLeft = "".concat(selectedFlagWidth + 6, "px");
1105
+ }
1106
+ }
1107
+ // and the input's placeholder
1108
+ this._updatePlaceholder();
1109
+ // update the active list item
1110
+ if (allowDropdown) {
1111
+ var prevItem = this.activeItem;
1112
+ if (prevItem) {
1113
+ prevItem.classList.remove("iti__active");
1114
+ prevItem.setAttribute("aria-selected", "false");
1115
+ }
1116
+ if (countryCode) {
1117
+ // check if there is a preferred item first, else fall back to standard
1118
+ var nextItem = this.countryList.querySelector("#iti-".concat(this.id, "__item-").concat(countryCode, "-preferred")) || this.countryList.querySelector("#iti-".concat(this.id, "__item-").concat(countryCode));
1119
+ nextItem.setAttribute("aria-selected", "true");
1120
+ nextItem.classList.add("iti__active");
1121
+ this.activeItem = nextItem;
1122
+ }
750
1123
  }
751
- this.selectedDialCode.text(dialCode);
1124
+ // return if the flag has changed or not
1125
+ return prevCountry.iso2 !== countryCode;
752
1126
  }
753
- // and the input's placeholder
754
- this._updatePlaceholder();
755
- // update the active list item
756
- this.countryListItems.removeClass("active");
757
- if (countryCode) {
758
- this.countryListItems.find(".iti-flag." + countryCode).first().closest(".country").addClass("active");
1127
+ }, {
1128
+ key: "_setSelectedCountryFlagTitleAttribute",
1129
+ value: function _setSelectedCountryFlagTitleAttribute(countryCode, separateDialCode) {
1130
+ if (!this.selectedFlag) {
1131
+ return;
1132
+ }
1133
+ var title;
1134
+ if (countryCode && !separateDialCode) {
1135
+ title = "".concat(this.selectedCountryData.name, ": +").concat(this.selectedCountryData.dialCode);
1136
+ } else if (countryCode) {
1137
+ // For screen reader output, we don't want to include the dial code in the reader output twice
1138
+ // so just use the selected country name here:
1139
+ title = this.selectedCountryData.name;
1140
+ } else {
1141
+ title = "Unknown";
1142
+ }
1143
+ this.selectedFlag.setAttribute("title", title);
759
1144
  }
760
- // return if the flag has changed or not
761
- return prevCountry.iso2 !== countryCode;
762
- },
763
- // update the input placeholder to an example number from the currently selected country
764
- _updatePlaceholder: function () {
765
- var shouldSetPlaceholder = this.options.autoPlaceholder === "aggressive" || !this.hadInitialPlaceholder && (this.options.autoPlaceholder === true || this.options.autoPlaceholder === "polite");
766
- if (window.intlTelInputUtils && shouldSetPlaceholder) {
767
- var numberType = intlTelInputUtils.numberType[this.options.placeholderNumberType], placeholder = this.selectedCountryData.iso2 ? intlTelInputUtils.getExampleNumber(this.selectedCountryData.iso2, this.options.nationalMode, numberType) : "";
768
- placeholder = this._beforeSetNumber(placeholder);
769
- if (typeof this.options.customPlaceholder === "function") {
770
- placeholder = this.options.customPlaceholder(placeholder, this.selectedCountryData);
1145
+ }, {
1146
+ key: "_getHiddenSelectedFlagWidth",
1147
+ value: function _getHiddenSelectedFlagWidth() {
1148
+ // to get the right styling to apply, all we need is a shallow clone of the container,
1149
+ // and then to inject a deep clone of the selectedFlag element
1150
+ var containerClone = this.telInput.parentNode.cloneNode();
1151
+ containerClone.style.visibility = "hidden";
1152
+ document.body.appendChild(containerClone);
1153
+ var flagsContainerClone = this.flagsContainer.cloneNode();
1154
+ containerClone.appendChild(flagsContainerClone);
1155
+ var selectedFlagClone = this.selectedFlag.cloneNode(true);
1156
+ flagsContainerClone.appendChild(selectedFlagClone);
1157
+ var width = selectedFlagClone.offsetWidth;
1158
+ containerClone.parentNode.removeChild(containerClone);
1159
+ return width;
1160
+ }
1161
+ }, {
1162
+ key: "_updatePlaceholder",
1163
+ value: function _updatePlaceholder() {
1164
+ var shouldSetPlaceholder = this.options.autoPlaceholder === "aggressive" || !this.hadInitialPlaceholder && this.options.autoPlaceholder === "polite";
1165
+ if (window.intlTelInputUtils && shouldSetPlaceholder) {
1166
+ var numberType = intlTelInputUtils.numberType[this.options.placeholderNumberType];
1167
+ var placeholder = this.selectedCountryData.iso2 ? intlTelInputUtils.getExampleNumber(this.selectedCountryData.iso2, this.options.nationalMode, numberType) : "";
1168
+ placeholder = this._beforeSetNumber(placeholder);
1169
+ if (typeof this.options.customPlaceholder === "function") {
1170
+ placeholder = this.options.customPlaceholder(placeholder, this.selectedCountryData);
1171
+ }
1172
+ this.telInput.setAttribute("placeholder", placeholder);
771
1173
  }
772
- this.telInput.attr("placeholder", placeholder);
773
1174
  }
774
- },
775
- // called when the user selects a list item from the dropdown
776
- _selectListItem: function (listItem) {
777
- // update selected flag and active list item
778
- var flagChanged = this._setFlag(listItem.attr("data-country-code"));
779
- this._closeDropdown();
780
- this._updateDialCode(listItem.attr("data-dial-code"), true);
781
- // focus the input
782
- this.telInput.focus();
783
- // put cursor at end - this fix is required for FF and IE11 (with nationalMode=false i.e. auto inserting dial code), who try to put the cursor at the beginning the first time
784
- if (this.isGoodBrowser) {
785
- var len = this.telInput.val().length;
786
- this.telInput[0].setSelectionRange(len, len);
787
- }
788
- if (flagChanged) {
789
- this._triggerCountryChange();
1175
+ }, {
1176
+ key: "_selectListItem",
1177
+ value: function _selectListItem(listItem) {
1178
+ // update selected flag and active list item
1179
+ var flagChanged = this._setFlag(listItem.getAttribute("data-country-code"));
1180
+ this._closeDropdown();
1181
+ this._updateDialCode(listItem.getAttribute("data-dial-code"));
1182
+ // focus the input
1183
+ this.telInput.focus();
1184
+ // put cursor at end - this fix is required for FF and IE11 (with auto inserting dial code),
1185
+ // who try to put the cursor at the beginning the first time
1186
+ var len = this.telInput.value.length;
1187
+ this.telInput.setSelectionRange(len, len);
1188
+ if (flagChanged) {
1189
+ this._triggerCountryChange();
1190
+ }
790
1191
  }
791
- },
792
- // close the dropdown and unbind any listeners
793
- _closeDropdown: function () {
794
- this.countryList.addClass("hide");
795
- // update the arrow
796
- this.selectedFlagInner.children(".iti-arrow").removeClass("up");
797
- // unbind key events
798
- $(document).off(this.ns);
799
- // unbind click-off-to-close
800
- $("html").off(this.ns);
801
- // unbind hover and click listeners
802
- this.countryList.off(this.ns);
803
- // remove menu from container
804
- if (this.options.dropdownContainer) {
805
- if (!this.isMobile) {
806
- $(window).off("scroll" + this.ns);
1192
+ }, {
1193
+ key: "_closeDropdown",
1194
+ value: function _closeDropdown() {
1195
+ this.countryList.classList.add("iti__hide");
1196
+ this.selectedFlag.setAttribute("aria-expanded", "false");
1197
+ this.selectedFlag.removeAttribute("aria-activedescendant");
1198
+ // update the arrow
1199
+ this.dropdownArrow.classList.remove("iti__arrow--up");
1200
+ // unbind key events
1201
+ document.removeEventListener("keydown", this._handleKeydownOnDropdown);
1202
+ document.documentElement.removeEventListener("click", this._handleClickOffToClose);
1203
+ this.countryList.removeEventListener("mouseover", this._handleMouseoverCountryList);
1204
+ this.countryList.removeEventListener("click", this._handleClickCountryList);
1205
+ // remove menu from container
1206
+ if (this.options.dropdownContainer) {
1207
+ if (!this.isMobile) {
1208
+ window.removeEventListener("scroll", this._handleWindowScroll);
1209
+ }
1210
+ if (this.dropdown.parentNode) {
1211
+ this.dropdown.parentNode.removeChild(this.dropdown);
1212
+ }
807
1213
  }
808
- this.dropdown.detach();
1214
+ this._trigger("close:countrydropdown");
809
1215
  }
810
- this.telInput.trigger("close:countrydropdown");
811
- },
812
- // check if an element is visible within it's container, else scroll until it is
813
- _scrollTo: function (element, middle) {
814
- var container = this.countryList, containerHeight = container.height(), containerTop = container.offset().top, containerBottom = containerTop + containerHeight, elementHeight = element.outerHeight(), elementTop = element.offset().top, elementBottom = elementTop + elementHeight, newScrollTop = elementTop - containerTop + container.scrollTop(), middleOffset = containerHeight / 2 - elementHeight / 2;
815
- if (elementTop < containerTop) {
816
- // scroll up
817
- if (middle) {
818
- newScrollTop -= middleOffset;
819
- }
820
- container.scrollTop(newScrollTop);
821
- } else if (elementBottom > containerBottom) {
822
- // scroll down
823
- if (middle) {
824
- newScrollTop += middleOffset;
825
- }
826
- var heightDifference = containerHeight - elementHeight;
827
- container.scrollTop(newScrollTop - heightDifference);
1216
+ }, {
1217
+ key: "_scrollTo",
1218
+ value: function _scrollTo(element, middle) {
1219
+ var container = this.countryList;
1220
+ // windowTop from https://stackoverflow.com/a/14384091/217866
1221
+ var windowTop = window.pageYOffset || document.documentElement.scrollTop;
1222
+ var containerHeight = container.offsetHeight;
1223
+ var containerTop = container.getBoundingClientRect().top + windowTop;
1224
+ var containerBottom = containerTop + containerHeight;
1225
+ var elementHeight = element.offsetHeight;
1226
+ var elementTop = element.getBoundingClientRect().top + windowTop;
1227
+ var elementBottom = elementTop + elementHeight;
1228
+ var newScrollTop = elementTop - containerTop + container.scrollTop;
1229
+ var middleOffset = containerHeight / 2 - elementHeight / 2;
1230
+ if (elementTop < containerTop) {
1231
+ // scroll up
1232
+ if (middle) {
1233
+ newScrollTop -= middleOffset;
1234
+ }
1235
+ container.scrollTop = newScrollTop;
1236
+ } else if (elementBottom > containerBottom) {
1237
+ // scroll down
1238
+ if (middle) {
1239
+ newScrollTop += middleOffset;
1240
+ }
1241
+ var heightDifference = containerHeight - elementHeight;
1242
+ container.scrollTop = newScrollTop - heightDifference;
1243
+ }
828
1244
  }
829
- },
830
- // replace any existing dial code with the new one
831
- // Note: called from _selectListItem and setCountry
832
- _updateDialCode: function (newDialCode, hasSelectedListItem) {
833
- var inputVal = this.telInput.val(), newNumber;
834
- // save having to pass this every time
835
- newDialCode = "+" + newDialCode;
836
- if (inputVal.charAt(0) == "+") {
837
- // there's a plus so we're dealing with a replacement (doesn't matter if nationalMode or not)
838
- var prevDialCode = this._getDialCode(inputVal);
839
- if (prevDialCode) {
840
- // current number contains a valid dial code, so replace it
841
- newNumber = inputVal.replace(prevDialCode, newDialCode);
842
- } else {
843
- // current number contains an invalid dial code, so ditch it
844
- // (no way to determine where the invalid dial code ends and the rest of the number begins)
845
- newNumber = newDialCode;
846
- }
847
- } else if (this.options.nationalMode || this.options.separateDialCode) {
848
- // don't do anything
849
- return;
850
- } else {
851
- // nationalMode is disabled
852
- if (inputVal) {
853
- // there is an existing value with no dial code: prefix the new dial code
854
- newNumber = newDialCode + inputVal;
855
- } else if (hasSelectedListItem || !this.options.autoHideDialCode) {
856
- // no existing value and either they've just selected a list item, or autoHideDialCode is disabled: insert new dial code
857
- newNumber = newDialCode;
858
- } else {
859
- return;
1245
+ }, {
1246
+ key: "_updateDialCode",
1247
+ value: function _updateDialCode(newDialCodeBare) {
1248
+ var inputVal = this.telInput.value;
1249
+ // save having to pass this every time
1250
+ var newDialCode = "+".concat(newDialCodeBare);
1251
+ var newNumber;
1252
+ if (inputVal.charAt(0) === "+") {
1253
+ // there's a plus so we're dealing with a replacement
1254
+ var prevDialCode = this._getDialCode(inputVal);
1255
+ if (prevDialCode) {
1256
+ // current number contains a valid dial code, so replace it
1257
+ newNumber = inputVal.replace(prevDialCode, newDialCode);
1258
+ } else {
1259
+ // current number contains an invalid dial code, so ditch it
1260
+ // (no way to determine where the invalid dial code ends and the rest of the number begins)
1261
+ newNumber = newDialCode;
1262
+ }
1263
+ this.telInput.value = newNumber;
1264
+ } else if (this.options.autoInsertDialCode) {
1265
+ if (inputVal) {
1266
+ // there is an existing value with no dial code: prefix the new dial code
1267
+ newNumber = newDialCode + inputVal;
1268
+ } else {
1269
+ newNumber = newDialCode;
1270
+ }
1271
+ this.telInput.value = newNumber;
860
1272
  }
861
1273
  }
862
- this.telInput.val(newNumber);
863
- },
864
- // try and extract a valid international dial code from a full telephone number
865
- // Note: returns the raw string inc plus character and any whitespace/dots etc
866
- _getDialCode: function (number) {
867
- var dialCode = "";
868
- // only interested in international numbers (starting with a plus)
869
- if (number.charAt(0) == "+") {
870
- var numericChars = "";
871
- // iterate over chars
872
- for (var i = 0; i < number.length; i++) {
873
- var c = number.charAt(i);
874
- // if char is number
875
- if ($.isNumeric(c)) {
876
- numericChars += c;
877
- // if current numericChars make a valid dial code
878
- if (this.countryCodes[numericChars]) {
879
- // store the actual raw string (useful for matching later)
880
- dialCode = number.substr(0, i + 1);
881
- }
882
- // longest dial code is 4 chars
883
- if (numericChars.length == 4) {
884
- break;
1274
+ }, {
1275
+ key: "_getDialCode",
1276
+ value: function _getDialCode(number, includeAreaCode) {
1277
+ var dialCode = "";
1278
+ // only interested in international numbers (starting with a plus)
1279
+ if (number.charAt(0) === "+") {
1280
+ var numericChars = "";
1281
+ // iterate over chars
1282
+ for (var i = 0; i < number.length; i++) {
1283
+ var c = number.charAt(i);
1284
+ // if char is number (https://stackoverflow.com/a/8935649/217866)
1285
+ if (!isNaN(parseInt(c, 10))) {
1286
+ numericChars += c;
1287
+ // if current numericChars make a valid dial code
1288
+ if (includeAreaCode) {
1289
+ if (this.countryCodes[numericChars]) {
1290
+ // store the actual raw string (useful for matching later)
1291
+ dialCode = number.substr(0, i + 1);
1292
+ }
1293
+ } else {
1294
+ if (this.dialCodes[numericChars]) {
1295
+ dialCode = number.substr(0, i + 1);
1296
+ // if we're just looking for a dial code, we can break as soon as we find one
1297
+ break;
1298
+ }
1299
+ }
1300
+ // stop searching as soon as we can - in this case when we hit max len
1301
+ if (numericChars.length === this.countryCodeMaxLen) {
1302
+ break;
1303
+ }
885
1304
  }
886
1305
  }
887
1306
  }
1307
+ return dialCode;
888
1308
  }
889
- return dialCode;
890
- },
891
- // get the input val, adding the dial code if separateDialCode is enabled
892
- _getFullNumber: function () {
893
- var val = $.trim(this.telInput.val()), dialCode = this.selectedCountryData.dialCode, prefix, numericVal = this._getNumeric(val), // normalized means ensure starts with a 1, so we can match against the full dial code
894
- normalizedVal = numericVal.charAt(0) == "1" ? numericVal : "1" + numericVal;
895
- if (this.options.separateDialCode) {
896
- prefix = "+" + dialCode;
897
- } else if (val.charAt(0) != "+" && val.charAt(0) != "1" && dialCode && dialCode.charAt(0) == "1" && dialCode.length == 4 && dialCode != normalizedVal.substr(0, 4)) {
898
- // if the user has entered a national NANP number, then ensure it includes the full dial code / area code
899
- prefix = dialCode.substr(1);
900
- } else {
901
- prefix = "";
902
- }
903
- return prefix + val;
904
- },
905
- // remove the dial code if separateDialCode is enabled
906
- _beforeSetNumber: function (number) {
907
- if (this.options.separateDialCode) {
908
- var dialCode = this._getDialCode(number);
909
- if (dialCode) {
910
- // US dialCode is "+1", which is what we want
911
- // CA dialCode is "+1 123", which is wrong - should be "+1" (as it has multiple area codes)
912
- // AS dialCode is "+1 684", which is what we want
913
- // Solution: if the country has area codes, then revert to just the dial code
914
- if (this.selectedCountryData.areaCodes !== null) {
915
- dialCode = "+" + this.selectedCountryData.dialCode;
1309
+ }, {
1310
+ key: "_getFullNumber",
1311
+ value: function _getFullNumber() {
1312
+ var val = this.telInput.value.trim();
1313
+ var dialCode = this.selectedCountryData.dialCode;
1314
+ var prefix;
1315
+ var numericVal = this._getNumeric(val);
1316
+ if (this.options.separateDialCode && val.charAt(0) !== "+" && dialCode && numericVal) {
1317
+ // when using separateDialCode, it is visible so is effectively part of the typed number
1318
+ prefix = "+".concat(dialCode);
1319
+ } else {
1320
+ prefix = "";
1321
+ }
1322
+ return prefix + val;
1323
+ }
1324
+ }, {
1325
+ key: "_beforeSetNumber",
1326
+ value: function _beforeSetNumber(originalNumber) {
1327
+ var number = originalNumber;
1328
+ if (this.options.separateDialCode) {
1329
+ var dialCode = this._getDialCode(number);
1330
+ // if there is a valid dial code
1331
+ if (dialCode) {
1332
+ // in case _getDialCode returned an area code as well
1333
+ dialCode = "+".concat(this.selectedCountryData.dialCode);
1334
+ // a lot of numbers will have a space separating the dial code and the main number, and
1335
+ // some NANP numbers will have a hyphen e.g. +1 684-733-1234 - in both cases we want to get
1336
+ // rid of it
1337
+ // NOTE: don't just trim all non-numerics as may want to preserve an open parenthesis etc
1338
+ var start = number[dialCode.length] === " " || number[dialCode.length] === "-" ? dialCode.length + 1 : dialCode.length;
1339
+ number = number.substr(start);
916
1340
  }
917
- // a lot of numbers will have a space separating the dial code and the main number, and some NANP numbers will have a hyphen e.g. +1 684-733-1234 - in both cases we want to get rid of it
918
- // NOTE: don't just trim all non-numerics as may want to preserve an open parenthesis etc
919
- var start = number[dialCode.length] === " " || number[dialCode.length] === "-" ? dialCode.length + 1 : dialCode.length;
920
- number = number.substr(start);
921
1341
  }
1342
+ return this._cap(number);
922
1343
  }
923
- return this._cap(number);
924
- },
925
- // trigger the 'countrychange' event
926
- _triggerCountryChange: function () {
927
- this.telInput.trigger("countrychange", this.selectedCountryData);
928
- },
929
- /**************************
930
- * SECRET PUBLIC METHODS
931
- **************************/
932
- // this is called when the geoip call returns
933
- handleAutoCountry: function () {
934
- if (this.options.initialCountry === "auto") {
935
- // we must set this even if there is an initial val in the input: in case the initial val is invalid and they delete it - they should see their auto country
936
- this.defaultCountry = $.fn[pluginName].autoCountry;
937
- // if there's no initial value in the input, then update the flag
938
- if (!this.telInput.val()) {
939
- this.setCountry(this.defaultCountry);
940
- }
941
- this.autoCountryDeferred.resolve();
1344
+ }, {
1345
+ key: "_triggerCountryChange",
1346
+ value: function _triggerCountryChange() {
1347
+ this._trigger("countrychange");
942
1348
  }
943
- },
944
- // this is called when the utils request completes
945
- handleUtils: function () {
946
- // if the request was successful
947
- if (window.intlTelInputUtils) {
948
- // if there's an initial value in the input, then format it
949
- if (this.telInput.val()) {
950
- this._updateValFromNumber(this.telInput.val());
1349
+ }, {
1350
+ key: "handleAutoCountry",
1351
+ value: function handleAutoCountry() {
1352
+ if (this.options.initialCountry === "auto") {
1353
+ // we must set this even if there is an initial val in the input: in case the initial val is
1354
+ // invalid and they delete it - they should see their auto country
1355
+ this.defaultCountry = window.intlTelInputGlobals.autoCountry;
1356
+ // if there's no initial value in the input, then update the flag
1357
+ if (!this.telInput.value) {
1358
+ this.setCountry(this.defaultCountry);
1359
+ }
1360
+ this.resolveAutoCountryPromise();
951
1361
  }
952
- this._updatePlaceholder();
953
1362
  }
954
- this.utilsScriptDeferred.resolve();
955
- },
956
- /********************
957
- * PUBLIC METHODS
958
- ********************/
959
- // remove plugin
960
- destroy: function () {
961
- if (this.allowDropdown) {
962
- // make sure the dropdown is closed (and unbind listeners)
963
- this._closeDropdown();
964
- // click event to open dropdown
965
- this.selectedFlagInner.parent().off(this.ns);
966
- // label click hack
967
- this.telInput.closest("label").off(this.ns);
968
- }
969
- // unbind submit event handler on form
970
- if (this.options.autoHideDialCode) {
971
- var form = this.telInput.prop("form");
972
- if (form) {
973
- $(form).off(this.ns);
974
- }
975
- }
976
- // unbind all events: key events, and focus/blur events if autoHideDialCode=true
977
- this.telInput.off(this.ns);
978
- // remove markup (but leave the original input)
979
- var container = this.telInput.parent();
980
- container.before(this.telInput).remove();
981
- },
982
- // get the extension from the current number
983
- getExtension: function () {
984
- if (window.intlTelInputUtils) {
985
- return intlTelInputUtils.getExtension(this._getFullNumber(), this.selectedCountryData.iso2);
1363
+ }, {
1364
+ key: "handleUtils",
1365
+ value: function handleUtils() {
1366
+ // if the request was successful
1367
+ if (window.intlTelInputUtils) {
1368
+ // if there's an initial value in the input, then format it
1369
+ if (this.telInput.value) {
1370
+ this._updateValFromNumber(this.telInput.value);
1371
+ }
1372
+ this._updatePlaceholder();
1373
+ }
1374
+ this.resolveUtilsScriptPromise();
986
1375
  }
987
- return "";
988
- },
989
- // format the number to the given format
990
- getNumber: function (format) {
991
- if (window.intlTelInputUtils) {
992
- return intlTelInputUtils.formatNumber(this._getFullNumber(), this.selectedCountryData.iso2, format);
1376
+ }, {
1377
+ key: "destroy",
1378
+ value: function destroy() {
1379
+ var form = this.telInput.form;
1380
+ if (this.options.allowDropdown) {
1381
+ // make sure the dropdown is closed (and unbind listeners)
1382
+ this._closeDropdown();
1383
+ this.selectedFlag.removeEventListener("click", this._handleClickSelectedFlag);
1384
+ this.flagsContainer.removeEventListener("keydown", this._handleFlagsContainerKeydown);
1385
+ // label click hack
1386
+ var label = this._getClosestLabel();
1387
+ if (label) {
1388
+ label.removeEventListener("click", this._handleLabelClick);
1389
+ }
1390
+ }
1391
+ // unbind hiddenInput listeners
1392
+ if (this.hiddenInput && form) {
1393
+ form.removeEventListener("submit", this._handleHiddenInputSubmit);
1394
+ }
1395
+ // unbind autoInsertDialCode listeners
1396
+ if (this.options.autoInsertDialCode) {
1397
+ if (form) {
1398
+ form.removeEventListener("submit", this._handleSubmitOrBlurEvent);
1399
+ }
1400
+ this.telInput.removeEventListener("blur", this._handleSubmitOrBlurEvent);
1401
+ }
1402
+ // unbind key events, and cut/paste events
1403
+ this.telInput.removeEventListener("keyup", this._handleKeyupEvent);
1404
+ this.telInput.removeEventListener("cut", this._handleClipboardEvent);
1405
+ this.telInput.removeEventListener("paste", this._handleClipboardEvent);
1406
+ // remove attribute of id instance: data-intl-tel-input-id
1407
+ this.telInput.removeAttribute("data-intl-tel-input-id");
1408
+ // remove markup (but leave the original input)
1409
+ var wrapper = this.telInput.parentNode;
1410
+ wrapper.parentNode.insertBefore(this.telInput, wrapper);
1411
+ wrapper.parentNode.removeChild(wrapper);
1412
+ delete window.intlTelInputGlobals.instances[this.id];
993
1413
  }
994
- return "";
995
- },
996
- // get the type of the entered number e.g. landline/mobile
997
- getNumberType: function () {
998
- if (window.intlTelInputUtils) {
999
- return intlTelInputUtils.getNumberType(this._getFullNumber(), this.selectedCountryData.iso2);
1414
+ }, {
1415
+ key: "getExtension",
1416
+ value: function getExtension() {
1417
+ if (window.intlTelInputUtils) {
1418
+ return intlTelInputUtils.getExtension(this._getFullNumber(), this.selectedCountryData.iso2);
1419
+ }
1420
+ return "";
1000
1421
  }
1001
- return -99;
1002
- },
1003
- // get the country data for the currently selected flag
1004
- getSelectedCountryData: function () {
1005
- return this.selectedCountryData;
1006
- },
1007
- // get the validation error
1008
- getValidationError: function () {
1009
- if (window.intlTelInputUtils) {
1010
- return intlTelInputUtils.getValidationError(this._getFullNumber(), this.selectedCountryData.iso2);
1422
+ }, {
1423
+ key: "getNumber",
1424
+ value: function getNumber(format) {
1425
+ if (window.intlTelInputUtils) {
1426
+ var iso2 = this.selectedCountryData.iso2;
1427
+ return intlTelInputUtils.formatNumber(this._getFullNumber(), iso2, format);
1428
+ }
1429
+ return "";
1011
1430
  }
1012
- return -99;
1013
- },
1014
- // validate the input val - assumes the global function isValidNumber (from utilsScript)
1015
- isValidNumber: function () {
1016
- var val = $.trim(this._getFullNumber()), countryCode = this.options.nationalMode ? this.selectedCountryData.iso2 : "";
1017
- return window.intlTelInputUtils ? intlTelInputUtils.isValidNumber(val, countryCode) : null;
1018
- },
1019
- // update the selected flag, and update the input val accordingly
1020
- setCountry: function (countryCode) {
1021
- countryCode = countryCode.toLowerCase();
1022
- // check if already selected
1023
- if (!this.selectedFlagInner.hasClass(countryCode)) {
1024
- this._setFlag(countryCode);
1025
- this._updateDialCode(this.selectedCountryData.dialCode, false);
1026
- this._triggerCountryChange();
1431
+ }, {
1432
+ key: "getNumberType",
1433
+ value: function getNumberType() {
1434
+ if (window.intlTelInputUtils) {
1435
+ return intlTelInputUtils.getNumberType(this._getFullNumber(), this.selectedCountryData.iso2);
1436
+ }
1437
+ return -99;
1027
1438
  }
1028
- },
1029
- // set the input value and update the flag
1030
- setNumber: function (number) {
1031
- // we must update the flag first, which updates this.selectedCountryData, which is used for formatting the number before displaying it
1032
- var flagChanged = this._updateFlagFromNumber(number);
1033
- this._updateValFromNumber(number);
1034
- if (flagChanged) {
1035
- this._triggerCountryChange();
1439
+ }, {
1440
+ key: "getSelectedCountryData",
1441
+ value: function getSelectedCountryData() {
1442
+ return this.selectedCountryData;
1036
1443
  }
1037
- },
1038
- // set the placeholder number typ
1039
- setPlaceholderNumberType: function (type) {
1040
- this.options.placeholderNumberType = type;
1041
- this._updatePlaceholder();
1444
+ }, {
1445
+ key: "getValidationError",
1446
+ value: function getValidationError() {
1447
+ if (window.intlTelInputUtils) {
1448
+ var iso2 = this.selectedCountryData.iso2;
1449
+ return intlTelInputUtils.getValidationError(this._getFullNumber(), iso2);
1450
+ }
1451
+ return -99;
1452
+ }
1453
+ }, {
1454
+ key: "isValidNumber",
1455
+ value: function isValidNumber() {
1456
+ var val = this._getFullNumber().trim();
1457
+ return window.intlTelInputUtils ? intlTelInputUtils.isValidNumber(val, this.selectedCountryData.iso2) : null;
1458
+ }
1459
+ }, {
1460
+ key: "setCountry",
1461
+ value: function setCountry(originalCountryCode) {
1462
+ var countryCode = originalCountryCode.toLowerCase();
1463
+ // check if already selected
1464
+ if (this.selectedCountryData.iso2 !== countryCode) {
1465
+ this._setFlag(countryCode);
1466
+ this._updateDialCode(this.selectedCountryData.dialCode);
1467
+ this._triggerCountryChange();
1468
+ }
1469
+ }
1470
+ }, {
1471
+ key: "setNumber",
1472
+ value: function setNumber(number) {
1473
+ // we must update the flag first, which updates this.selectedCountryData, which is used for
1474
+ // formatting the number before displaying it
1475
+ var flagChanged = this._updateFlagFromNumber(number);
1476
+ this._updateValFromNumber(number);
1477
+ if (flagChanged) {
1478
+ this._triggerCountryChange();
1479
+ }
1480
+ }
1481
+ }, {
1482
+ key: "setPlaceholderNumberType",
1483
+ value: function setPlaceholderNumberType(type) {
1484
+ this.options.placeholderNumberType = type;
1485
+ this._updatePlaceholder();
1486
+ }
1487
+ } ]);
1488
+ return Iti;
1489
+ }();
1490
+ /********************
1491
+ * STATIC METHODS
1492
+ ********************/
1493
+ // get the country data object
1494
+ intlTelInputGlobals.getCountryData = function() {
1495
+ return allCountries;
1496
+ };
1497
+ // inject a <script> element to load utils.js
1498
+ var injectScript = function injectScript(path, handleSuccess, handleFailure) {
1499
+ // inject a new script element into the page
1500
+ var script = document.createElement("script");
1501
+ script.onload = function() {
1502
+ forEachInstance("handleUtils");
1503
+ if (handleSuccess) {
1504
+ handleSuccess();
1505
+ }
1506
+ };
1507
+ script.onerror = function() {
1508
+ forEachInstance("rejectUtilsScriptPromise");
1509
+ if (handleFailure) {
1510
+ handleFailure();
1511
+ }
1512
+ };
1513
+ script.className = "iti-load-utils";
1514
+ script.async = true;
1515
+ script.src = path;
1516
+ document.body.appendChild(script);
1517
+ };
1518
+ // load the utils script
1519
+ intlTelInputGlobals.loadUtils = function(path) {
1520
+ // 2 options:
1521
+ // 1) not already started loading (start)
1522
+ // 2) already started loading (do nothing - just wait for the onload callback to fire, which will
1523
+ // trigger handleUtils on all instances, invoking their resolveUtilsScriptPromise functions)
1524
+ if (!window.intlTelInputUtils && !window.intlTelInputGlobals.startedLoadingUtilsScript) {
1525
+ // only do this once
1526
+ window.intlTelInputGlobals.startedLoadingUtilsScript = true;
1527
+ // if we have promises, then return a promise
1528
+ if (typeof Promise !== "undefined") {
1529
+ return new Promise(function(resolve, reject) {
1530
+ return injectScript(path, resolve, reject);
1531
+ });
1532
+ }
1533
+ injectScript(path);
1042
1534
  }
1535
+ return null;
1043
1536
  };
1044
- // using https://github.com/jquery-boilerplate/jquery-boilerplate/wiki/Extending-jQuery-Boilerplate
1045
- // (adapted to allow public functions)
1046
- $.fn[pluginName] = function (options) {
1537
+ // default options
1538
+ intlTelInputGlobals.defaults = defaults;
1539
+ // version
1540
+ intlTelInputGlobals.version = "18.1.8";
1541
+ var pluginName = "intlTelInput";
1542
+ // A really lightweight plugin wrapper around the constructor,
1543
+ // preventing against multiple instantiations
1544
+ $.fn[pluginName] = function(options) {
1047
1545
  var args = arguments;
1048
- // Is the first parameter an object (options), or was omitted,
1049
- // instantiate a new instance of the plugin.
1546
+ // Is the first parameter an object (options), or was omitted, instantiate a new instance of the plugin.
1050
1547
  if (options === undefined || typeof options === "object") {
1051
- // collect all of the deferred objects for all instances created with this selector
1052
- var deferreds = [];
1053
- this.each(function () {
1548
+ return this.each(function() {
1054
1549
  if (!$.data(this, "plugin_" + pluginName)) {
1055
- var instance = new Plugin(this, options);
1056
- var instanceDeferreds = instance._init();
1057
- // we now have 2 deffereds: 1 for auto country, 1 for utils script
1058
- deferreds.push(instanceDeferreds[0]);
1059
- deferreds.push(instanceDeferreds[1]);
1060
- $.data(this, "plugin_" + pluginName, instance);
1550
+ var iti = new Iti(this, options);
1551
+ iti._init();
1552
+ window.intlTelInputGlobals.instances[iti.id] = iti;
1553
+ $.data(this, "plugin_" + pluginName, iti);
1061
1554
  }
1062
1555
  });
1063
- // return the promise from the "master" deferred object that tracks all the others
1064
- return $.when.apply(null, deferreds);
1065
1556
  } else if (typeof options === "string" && options[0] !== "_") {
1066
- // If the first parameter is a string and it doesn't start
1067
- // with an underscore or "contains" the `init`-function,
1068
- // treat this as a call to a public method.
1557
+ // If the first parameter is a string and it doesn't start with an underscore treat this as a call to a public method.
1069
1558
  // Cache the method call to make it possible to return a value
1070
1559
  var returns;
1071
- this.each(function () {
1560
+ this.each(function() {
1072
1561
  var instance = $.data(this, "plugin_" + pluginName);
1073
- // Tests that there's already a plugin-instance
1074
- // and checks that the requested public method exists
1075
- if (instance instanceof Plugin && typeof instance[options] === "function") {
1076
- // Call the method of our plugin instance,
1077
- // and pass it the supplied arguments.
1562
+ // Tests that there's already a plugin-instance and checks that the requested public method exists
1563
+ if (instance instanceof Iti && typeof instance[options] === "function") {
1564
+ // Call the method of our plugin instance, and pass it the supplied arguments.
1078
1565
  returns = instance[options].apply(instance, Array.prototype.slice.call(args, 1));
1079
1566
  }
1080
1567
  // Allow instances to be destroyed via the 'destroy' method
1081
- if (options === "destroy") {
1082
- $.data(this, "plugin_" + pluginName, null);
1083
- }
1568
+ if (options === "destroy") $.data(this, "plugin_" + pluginName, null);
1084
1569
  });
1085
- // If the earlier cached method gives a value back return the value,
1086
- // otherwise return this to preserve chainability.
1570
+ // If the earlier cached method gives a value back return the value, otherwise return this to preserve chainability.
1087
1571
  return returns !== undefined ? returns : this;
1088
1572
  }
1089
1573
  };
1090
- /********************
1091
- * STATIC METHODS
1092
- ********************/
1093
- // get the country data object
1094
- $.fn[pluginName].getCountryData = function () {
1095
- return allCountries;
1096
- };
1097
- // load the utils script
1098
- $.fn[pluginName].loadUtils = function (path, utilsScriptDeferred) {
1099
- if (!$.fn[pluginName].loadedUtilsScript) {
1100
- // don't do this twice! (dont just check if window.intlTelInputUtils exists as if init plugin multiple times in quick succession, it may not have finished loading yet)
1101
- $.fn[pluginName].loadedUtilsScript = true;
1102
- // dont use $.getScript as it prevents caching
1103
- $.ajax({
1104
- type: "GET",
1105
- url: path,
1106
- complete: function () {
1107
- // tell all instances that the utils request is complete
1108
- $(".intl-tel-input input").intlTelInput("handleUtils");
1109
- },
1110
- dataType: "script",
1111
- cache: true
1112
- });
1113
- } else if (utilsScriptDeferred) {
1114
- utilsScriptDeferred.resolve();
1115
- }
1116
- };
1117
- // default options
1118
- $.fn[pluginName].defaults = defaults;
1119
- // version
1120
- $.fn[pluginName].version = "12.3.0";
1121
- // Array of country objects for the flag dropdown.
1122
- // Here is the criteria for the plugin to support a given country/territory
1123
- // - It has an iso2 code: https://en.wikipedia.org/wiki/ISO_3166-1_alpha-2
1124
- // - It has it's own country calling code (it is not a sub-region of another country): https://en.wikipedia.org/wiki/List_of_country_calling_codes
1125
- // - It has a flag in the region-flags project: https://github.com/behdad/region-flags/tree/gh-pages/png
1126
- // - It is supported by libphonenumber (it must be listed on this page): https://github.com/googlei18n/libphonenumber/blob/master/resources/ShortNumberMetadata.xml
1127
- // Each country array has the following information:
1128
- // [
1129
- // Country name,
1130
- // iso2 code,
1131
- // International dial code,
1132
- // Order (if >1 country with same dial code),
1133
- // Area codes
1134
- // ]
1135
- var allCountries = [["Afghanistan (‫افغانستان‬‎)", "af", "93"], ["Albania (Shqipëri)", "al", "355"], ["Algeria (‫الجزائر‬‎)", "dz", "213"], ["American Samoa", "as", "1684"], ["Andorra", "ad", "376"], ["Angola", "ao", "244"], ["Anguilla", "ai", "1264"], ["Antigua and Barbuda", "ag", "1268"], ["Argentina", "ar", "54"], ["Armenia (Հայաստան)", "am", "374"], ["Aruba", "aw", "297"], ["Australia", "au", "61", 0], ["Austria (Österreich)", "at", "43"], ["Azerbaijan (Azərbaycan)", "az", "994"], ["Bahamas", "bs", "1242"], ["Bahrain (‫البحرين‬‎)", "bh", "973"], ["Bangladesh (বাংলাদেশ)", "bd", "880"], ["Barbados", "bb", "1246"], ["Belarus (Беларусь)", "by", "375"], ["Belgium (België)", "be", "32"], ["Belize", "bz", "501"], ["Benin (Bénin)", "bj", "229"], ["Bermuda", "bm", "1441"], ["Bhutan (འབྲུག)", "bt", "975"], ["Bolivia", "bo", "591"], ["Bosnia and Herzegovina (Босна и Херцеговина)", "ba", "387"], ["Botswana", "bw", "267"], ["Brazil (Brasil)", "br", "55"], ["British Indian Ocean Territory", "io", "246"], ["British Virgin Islands", "vg", "1284"], ["Brunei", "bn", "673"], ["Bulgaria (България)", "bg", "359"], ["Burkina Faso", "bf", "226"], ["Burundi (Uburundi)", "bi", "257"], ["Cambodia (កម្ពុជា)", "kh", "855"], ["Cameroon (Cameroun)", "cm", "237"], ["Canada", "ca", "1", 1, ["204", "226", "236", "249", "250", "289", "306", "343", "365", "387", "403", "416", "418", "431", "437", "438", "450", "506", "514", "519", "548", "579", "581", "587", "604", "613", "639", "647", "672", "705", "709", "742", "778", "780", "782", "807", "819", "825", "867", "873", "902", "905"]], ["Cape Verde (Kabu Verdi)", "cv", "238"], ["Caribbean Netherlands", "bq", "599", 1], ["Cayman Islands", "ky", "1345"], ["Central African Republic (République centrafricaine)", "cf", "236"], ["Chad (Tchad)", "td", "235"], ["Chile", "cl", "56"], ["China (中国)", "cn", "86"], ["Christmas Island", "cx", "61", 2], ["Cocos (Keeling) Islands", "cc", "61", 1], ["Colombia", "co", "57"], ["Comoros (‫جزر القمر‬‎)", "km", "269"], ["Congo (DRC) (Jamhuri ya Kidemokrasia ya Kongo)", "cd", "243"], ["Congo (Republic) (Congo-Brazzaville)", "cg", "242"], ["Cook Islands", "ck", "682"], ["Costa Rica", "cr", "506"], ["Côte d’Ivoire", "ci", "225"], ["Croatia (Hrvatska)", "hr", "385"], ["Cuba", "cu", "53"], ["Curaçao", "cw", "599", 0], ["Cyprus (Κύπρος)", "cy", "357"], ["Czech Republic (Česká republika)", "cz", "420"], ["Denmark (Danmark)", "dk", "45"], ["Djibouti", "dj", "253"], ["Dominica", "dm", "1767"], ["Dominican Republic (República Dominicana)", "do", "1", 2, ["809", "829", "849"]], ["Ecuador", "ec", "593"], ["Egypt (‫مصر‬‎)", "eg", "20"], ["El Salvador", "sv", "503"], ["Equatorial Guinea (Guinea Ecuatorial)", "gq", "240"], ["Eritrea", "er", "291"], ["Estonia (Eesti)", "ee", "372"], ["Ethiopia", "et", "251"], ["Falkland Islands (Islas Malvinas)", "fk", "500"], ["Faroe Islands (Føroyar)", "fo", "298"], ["Fiji", "fj", "679"], ["Finland (Suomi)", "fi", "358", 0], ["France", "fr", "33"], ["French Guiana (Guyane française)", "gf", "594"], ["French Polynesia (Polynésie française)", "pf", "689"], ["Gabon", "ga", "241"], ["Gambia", "gm", "220"], ["Georgia (საქართველო)", "ge", "995"], ["Germany (Deutschland)", "de", "49"], ["Ghana (Gaana)", "gh", "233"], ["Gibraltar", "gi", "350"], ["Greece (Ελλάδα)", "gr", "30"], ["Greenland (Kalaallit Nunaat)", "gl", "299"], ["Grenada", "gd", "1473"], ["Guadeloupe", "gp", "590", 0], ["Guam", "gu", "1671"], ["Guatemala", "gt", "502"], ["Guernsey", "gg", "44", 1], ["Guinea (Guinée)", "gn", "224"], ["Guinea-Bissau (Guiné Bissau)", "gw", "245"], ["Guyana", "gy", "592"], ["Haiti", "ht", "509"], ["Honduras", "hn", "504"], ["Hong Kong (香港)", "hk", "852"], ["Hungary (Magyarország)", "hu", "36"], ["Iceland (Ísland)", "is", "354"], ["India (भारत)", "in", "91"], ["Indonesia", "id", "62"], ["Iran (‫ایران‬‎)", "ir", "98"], ["Iraq (‫العراق‬‎)", "iq", "964"], ["Ireland", "ie", "353"], ["Isle of Man", "im", "44", 2], ["Israel (‫ישראל‬‎)", "il", "972"], ["Italy (Italia)", "it", "39", 0], ["Jamaica", "jm", "1", 4, ["876", "658"]], ["Japan (日本)", "jp", "81"], ["Jersey", "je", "44", 3], ["Jordan (‫الأردن‬‎)", "jo", "962"], ["Kazakhstan (Казахстан)", "kz", "7", 1], ["Kenya", "ke", "254"], ["Kiribati", "ki", "686"], ["Kosovo", "xk", "383"], ["Kuwait (‫الكويت‬‎)", "kw", "965"], ["Kyrgyzstan (Кыргызстан)", "kg", "996"], ["Laos (ລາວ)", "la", "856"], ["Latvia (Latvija)", "lv", "371"], ["Lebanon (‫لبنان‬‎)", "lb", "961"], ["Lesotho", "ls", "266"], ["Liberia", "lr", "231"], ["Libya (‫ليبيا‬‎)", "ly", "218"], ["Liechtenstein", "li", "423"], ["Lithuania (Lietuva)", "lt", "370"], ["Luxembourg", "lu", "352"], ["Macau (澳門)", "mo", "853"], ["Macedonia (FYROM) (Македонија)", "mk", "389"], ["Madagascar (Madagasikara)", "mg", "261"], ["Malawi", "mw", "265"], ["Malaysia", "my", "60"], ["Maldives", "mv", "960"], ["Mali", "ml", "223"], ["Malta", "mt", "356"], ["Marshall Islands", "mh", "692"], ["Martinique", "mq", "596"], ["Mauritania (‫موريتانيا‬‎)", "mr", "222"], ["Mauritius (Moris)", "mu", "230"], ["Mayotte", "yt", "262", 1], ["Mexico (México)", "mx", "52"], ["Micronesia", "fm", "691"], ["Moldova (Republica Moldova)", "md", "373"], ["Monaco", "mc", "377"], ["Mongolia (Монгол)", "mn", "976"], ["Montenegro (Crna Gora)", "me", "382"], ["Montserrat", "ms", "1664"], ["Morocco (‫المغرب‬‎)", "ma", "212", 0], ["Mozambique (Moçambique)", "mz", "258"], ["Myanmar (Burma) (မြန်မာ)", "mm", "95"], ["Namibia (Namibië)", "na", "264"], ["Nauru", "nr", "674"], ["Nepal (नेपाल)", "np", "977"], ["Netherlands (Nederland)", "nl", "31"], ["New Caledonia (Nouvelle-Calédonie)", "nc", "687"], ["New Zealand", "nz", "64"], ["Nicaragua", "ni", "505"], ["Niger (Nijar)", "ne", "227"], ["Nigeria", "ng", "234"], ["Niue", "nu", "683"], ["Norfolk Island", "nf", "672"], ["North Korea (조선 민주주의 인민 공화국)", "kp", "850"], ["Northern Mariana Islands", "mp", "1670"], ["Norway (Norge)", "no", "47", 0], ["Oman (‫عُمان‬‎)", "om", "968"], ["Pakistan (‫پاکستان‬‎)", "pk", "92"], ["Palau", "pw", "680"], ["Palestine (‫فلسطين‬‎)", "ps", "970"], ["Panama (Panamá)", "pa", "507"], ["Papua New Guinea", "pg", "675"], ["Paraguay", "py", "595"], ["Peru (Perú)", "pe", "51"], ["Philippines", "ph", "63"], ["Poland (Polska)", "pl", "48"], ["Portugal", "pt", "351"], ["Puerto Rico", "pr", "1", 3, ["787", "939"]], ["Qatar (‫قطر‬‎)", "qa", "974"], ["Réunion (La Réunion)", "re", "262", 0], ["Romania (România)", "ro", "40"], ["Россия", "ru", "7", 0], ["Rwanda", "rw", "250"], ["Saint Barthélemy", "bl", "590", 1], ["Saint Helena", "sh", "290"], ["Saint Kitts and Nevis", "kn", "1869"], ["Saint Lucia", "lc", "1758"], ["Saint Martin (Saint-Martin (partie française))", "mf", "590", 2], ["Saint Pierre and Miquelon (Saint-Pierre-et-Miquelon)", "pm", "508"], ["Saint Vincent and the Grenadines", "vc", "1784"], ["Samoa", "ws", "685"], ["San Marino", "sm", "378"], ["São Tomé and Príncipe (São Tomé e Príncipe)", "st", "239"], ["Saudi Arabia (‫المملكة العربية السعودية‬‎)", "sa", "966"], ["Senegal (Sénégal)", "sn", "221"], ["Serbia (Србија)", "rs", "381"], ["Seychelles", "sc", "248"], ["Sierra Leone", "sl", "232"], ["Singapore", "sg", "65"], ["Sint Maarten", "sx", "1721"], ["Slovakia (Slovensko)", "sk", "421"], ["Slovenia (Slovenija)", "si", "386"], ["Solomon Islands", "sb", "677"], ["Somalia (Soomaaliya)", "so", "252"], ["South Africa", "za", "27"], ["South Korea (대한민국)", "kr", "82"], ["South Sudan (‫جنوب السودان‬‎)", "ss", "211"], ["Spain (España)", "es", "34"], ["Sri Lanka (ශ්‍රී ලංකාව)", "lk", "94"], ["Sudan (‫السودان‬‎)", "sd", "249"], ["Suriname", "sr", "597"], ["Svalbard and Jan Mayen", "sj", "47", 1], ["Swaziland", "sz", "268"], ["Sweden (Sverige)", "se", "46"], ["Switzerland (Schweiz)", "ch", "41"], ["Syria (‫سوريا‬‎)", "sy", "963"], ["Taiwan (台灣)", "tw", "886"], ["Tajikistan", "tj", "992"], ["Tanzania", "tz", "255"], ["Thailand (ไทย)", "th", "66"], ["Timor-Leste", "tl", "670"], ["Togo", "tg", "228"], ["Tokelau", "tk", "690"], ["Tonga", "to", "676"], ["Trinidad and Tobago", "tt", "1868"], ["Tunisia (‫تونس‬‎)", "tn", "216"], ["Turkey (Türkiye)", "tr", "90"], ["Turkmenistan", "tm", "993"], ["Turks and Caicos Islands", "tc", "1649"], ["Tuvalu", "tv", "688"], ["U.S. Virgin Islands", "vi", "1340"], ["Uganda", "ug", "256"], ["Ukraine (Україна)", "ua", "380"], ["United Arab Emirates (‫الإمارات العربية المتحدة‬‎)", "ae", "971"], ["United Kingdom", "gb", "44", 0], ["United States", "us", "1", 0], ["Uruguay", "uy", "598"], ["Uzbekistan (Oʻzbekiston)", "uz", "998"], ["Vanuatu", "vu", "678"], ["Vatican City (Città del Vaticano)", "va", "39", 1], ["Venezuela", "ve", "58"], ["Vietnam (Việt Nam)", "vn", "84"], ["Wallis and Futuna (Wallis-et-Futuna)", "wf", "681"], ["Western Sahara (‫الصحراء الغربية‬‎)", "eh", "212", 1], ["Yemen (‫اليمن‬‎)", "ye", "967"], ["Zambia", "zm", "260"], ["Zimbabwe", "zw", "263"], ["Åland Islands", "ax", "358", 1]];
1136
- // loop over all of the countries above
1137
- for (var i = 0; i < allCountries.length; i++) {
1138
- var c = allCountries[i];
1139
- allCountries[i] = {
1140
- name: c[0],
1141
- iso2: c[1],
1142
- dialCode: c[2],
1143
- priority: c[3] || 0,
1144
- areaCodes: c[4] || null
1145
- };
1146
- }
1147
1574
  });